settings_reader-vault_resolver 0.4.0 → 0.4.3

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: 041a3786bc1f140cee0811ed25d307ea90a0183b1e2a9b2f4b9101c9517a03f8
4
- data.tar.gz: 4449fc9d7b17afb83b69be9cf1795b9c8ce4c0aef52ecd048d52d15ff6ad58cd
3
+ metadata.gz: 200d04472a50277f38b29b18a30b565588e4c5fa7c55a2b654b70bb9dbbc0e62
4
+ data.tar.gz: 48ec7877b81d458ad9c22b14cdbce6ce05b1a22a141e7c978c3a19c7f6796037
5
5
  SHA512:
6
- metadata.gz: ff78c9900e1c2391eb8a5200aea1c5f46226c7d1924b601aaf4310bfd3b17921847f057ce9ca180cd5d438b0d37c09cc33434e581e429faa63138ddb4b2cce07
7
- data.tar.gz: 27838f4e0b45e9ee97ef13bbf757c0a7d1c3c4a1b88dcabfb1fb717ce20fc023e0e584549e94b59890abd624f4820eb2fa765df3d463c097481fc95c825b2564
6
+ metadata.gz: 365fa301486b2df995dc0eacd1e5492ee2f59dd68c26e251f13d813ed49dec7bb0d295de316c3b4edee924785bc03a61e872e48ad67c75e8dc1caa993ad194d0
7
+ data.tar.gz: 9129f937c54959ea99fcd99647889ccfa22b23783f33f89bdc665d5226b562dbcb6369629927076be3c4be869280a87477251b6bd63e1dc39ded8e8bbc62f22f
@@ -0,0 +1,114 @@
1
+
2
+ version: 2.1
3
+
4
+ orbs:
5
+ ci: matic/orb-common@0.2
6
+ ruby: circleci/ruby@1.8.0
7
+
8
+ jobs:
9
+
10
+ rspec-test:
11
+ resource_class: small
12
+ parameters:
13
+ ruby-version:
14
+ type: string
15
+ docker:
16
+ - image: cimg/ruby:<< parameters.ruby-version >>
17
+ environment:
18
+ COVERAGE: true
19
+ CODECOV_TOKEN: a0c859b6-dfb7-4d9f-9933-2dd945cdd960
20
+ VAULT_ADDR: 'http://127.0.0.1:8200'
21
+ VAULT_TOKEN: 'vault_root_token'
22
+ - image: vault
23
+ environment:
24
+ VAULT_DEV_ROOT_TOKEN_ID: vault_root_token
25
+ SKIP_SETCAP: true
26
+ - image: postgres:14.1-alpine
27
+ environment:
28
+ POSTGRES_DB: 'app_db'
29
+ POSTGRES_USER: 'vault_root'
30
+ POSTGRES_PASSWORD: 'root_password'
31
+ steps:
32
+ - checkout
33
+ - ruby/install-deps
34
+ - run:
35
+ name: Set up vault
36
+ command: sh local/vault/setup.sh
37
+ - run:
38
+ name: Run RSpec Tests
39
+ command: bundle exec rspec
40
+ - store_test_results:
41
+ path: reports/rspec
42
+ - store_artifacts:
43
+ path: reports/rspec
44
+ - ci/slack-stage-message
45
+
46
+ rubocop:
47
+ resource_class: small
48
+ docker:
49
+ - image: cimg/ruby:2.5
50
+ steps:
51
+ - checkout
52
+ - ruby/install-deps
53
+ - run:
54
+ name: Run rubocop
55
+ command: bundle exec rubocop --parallel
56
+
57
+ release:
58
+ parameters:
59
+ tag:
60
+ type: string
61
+ default: "default-tag"
62
+ docker:
63
+ - image: cimg/ruby:2.7.5
64
+ environment:
65
+ RELEASE_TAG: << parameters.tag >>
66
+ steps:
67
+ - checkout
68
+ - ruby/install-deps
69
+ - run:
70
+ name: Set up credentials
71
+ command: |
72
+ mkdir -p $HOME/.gem
73
+ touch $HOME/.gem/credentials
74
+ chmod 0600 $HOME/.gem/credentials
75
+ printf -- "---\n:rubygems_api_key: $RUBYGEMS_API_KEY\n" > $HOME/.gem/credentials
76
+ - run:
77
+ name: Set version
78
+ command: sed -i "s/[[:digit:]].[[:digit:]].[[:digit:]]/${RELEASE_TAG}/g" $(find . -name "version.rb")
79
+ - run:
80
+ name: Build gem
81
+ command: gem build *.gemspec
82
+ - run:
83
+ name: Push gem
84
+ command: gem push *.gem
85
+
86
+ workflows:
87
+
88
+ settings_reader-vault_resolver.build-pull-request:
89
+ when:
90
+ not:
91
+ equal: [ main, << pipeline.git.branch >> ]
92
+ jobs:
93
+
94
+ - rspec-test:
95
+ context: global
96
+ matrix:
97
+ parameters:
98
+ ruby-version: [ '2.5', '2.6', '2.7', '3.0' ]
99
+
100
+ - rubocop:
101
+ name: Rubocop
102
+ context: global
103
+
104
+ settings_reader-vault_resolver.release:
105
+ jobs:
106
+
107
+ - release:
108
+ tag: << pipeline.git.tag >>
109
+ context: gem-publishing
110
+ filters:
111
+ branches:
112
+ ignore: /.*/
113
+ tags:
114
+ only: /\d\.\d\.\d/ # It should be [digin dot digit dot digit] format
@@ -9,19 +9,6 @@ on:
9
9
  - cron: '30 0 * * 1'
10
10
 
11
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
12
 
26
13
  code-ql:
27
14
  name: Analyze
@@ -10,64 +10,6 @@ on:
10
10
  types: [published]
11
11
 
12
12
  jobs:
13
- build:
14
- env:
15
- COVERAGE: true
16
- CODECOV_TOKEN: a0c859b6-dfb7-4d9f-9933-2dd945cdd960
17
- VAULT_ADDR: 'http://127.0.0.1:8200'
18
- VAULT_TOKEN: 'vault_root_token'
19
-
20
- runs-on: ubuntu-latest
21
- strategy:
22
- matrix:
23
- ruby: [ '2.5.x', '2.6.x', '2.7.x', '3.0.x' ]
24
- services:
25
- vault:
26
- image: vault
27
- ports:
28
- - "8200:8200"
29
- env:
30
- VAULT_DEV_ROOT_TOKEN_ID: vault_root_token
31
- SKIP_SETCAP: true
32
- db:
33
- image: postgres:14.1-alpine
34
- ports:
35
- - "5432:5432"
36
- env:
37
- POSTGRES_USER: 'vault_root'
38
- POSTGRES_PASSWORD: 'root_password'
39
- POSTGRES_DB: 'app_db'
40
-
41
- steps:
42
- - name: Checkout
43
- uses: actions/checkout@v1
44
- - name: Cache dependencies
45
- uses: actions/cache@v1
46
- with:
47
- path: vendor/bundle
48
- key: ${{ runner.OS }}-ruby-${{ matrix.ruby }}
49
- restore-keys: ${{ runner.OS }}-
50
-
51
- - name: Set up Ruby
52
- uses: actions/setup-ruby@v1
53
- with:
54
- ruby-version: ${{ matrix.ruby }}
55
- - name: Set up Bundler
56
- run: gem install bundler:2.1.4
57
- - name: Set up Dependencies
58
- run: bundle install --path vendor/bundle
59
- - name: Set up Vault
60
- run: sh local/vault/setup.sh
61
-
62
- - name: Run specs
63
- env:
64
- COVERAGE: true
65
- run: bundle exec rspec
66
-
67
- - name: Upload coverage
68
- env:
69
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
70
- run: bash <(curl -s https://codecov.io/bash)
71
13
 
72
14
  release:
73
15
  runs-on: ubuntu-latest
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.2]
4
+ ### Fixes
5
+ - Fix lost secret data after lease renewal
6
+ - Fix exception when getting value from secret with nil data
7
+
8
+ ## [0.4.1]
9
+ ### Changes
10
+ - Broader entry secret data access to allow retrieval of secret attributes
11
+
12
+ ### Fixes
13
+ - Fix exception when retrieving authenticating via k8s endpoint
14
+
15
+ ### New features
16
+ - Retry secret retrieval and renewal
17
+ - Capture more vault exceptions including connectivity errors
18
+ - Introduce vault engine adapter concept
19
+ - Separate kv, database, and auth engine logic
20
+
3
21
  ## [0.4.0]
4
22
  ### Breaking changes
5
23
  - Reworked authentication helpers interface
@@ -55,7 +73,9 @@
55
73
  - Secrets caching
56
74
  - Automatic secrets lease renewal
57
75
 
58
- [Unreleased]: https://github.com/matic-insurance/settings_reader-vault_resolver/compare/0.4.0...HEAD
76
+ [Unreleased]: https://github.com/matic-insurance/settings_reader-vault_resolver/compare/0.4.2...HEAD
77
+ [0.4.2]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.4.2
78
+ [0.4.1]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.4.1
59
79
  [0.4.0]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.4.0
60
80
  [0.3.0]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.3.0
61
81
  [0.2.4]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.2.4
data/README.md CHANGED
@@ -33,7 +33,8 @@ AppSettings = SettingsReader.load do |config|
33
33
  # Configure vault resolver
34
34
  SettingsReader::VaultResolver.configure do |vault_resolver_config|
35
35
  vault_resolver_config.logger = Rails.logger
36
- # ... VaultResolver configurations
36
+ vault_resolver_config.vault_initializer = -> { authenticate_vault }
37
+ # ... other VaultResolver configurations
37
38
  end
38
39
 
39
40
  # Add vault resolver as one of resolvers
data/docker-compose.yml CHANGED
@@ -7,7 +7,7 @@ services:
7
7
  - "8200:8200"
8
8
  environment:
9
9
  VAULT_DEV_ROOT_TOKEN_ID: 'vault_root_token'
10
- SKIP_SETCAP: true
10
+ SKIP_SETCAP: 'true'
11
11
  db:
12
12
  image: postgres:14.1-alpine
13
13
  ports:
@@ -26,5 +26,5 @@ services:
26
26
  environment:
27
27
  VAULT_ADDR: 'http://vault:8200'
28
28
  VAULT_TOKEN: 'vault_root_token'
29
- SKIP_SETCAP: true
29
+ SKIP_SETCAP: 'true'
30
30
  command: sh /etc/vault/setup.sh
@@ -36,6 +36,10 @@ module SettingsReader
36
36
  @secrets.each_value(&block)
37
37
  end
38
38
 
39
+ def clear_all
40
+ @secrets = {}
41
+ end
42
+
39
43
  private
40
44
 
41
45
  def cache_key(address)
@@ -30,14 +30,19 @@ module SettingsReader
30
30
  # Default: empty proc
31
31
  attr_accessor :lease_renew_error_listener
32
32
 
33
+ # Block to be executed for initialization and authorization
34
+ # Default: empty proc
35
+ attr_accessor :vault_initializer
36
+
33
37
  def initialize
34
38
  @logger = Logger.new($stdout, level: Logger::ERROR)
35
39
  @retrieval_retries = 2
36
40
  @lease_refresh_interval = 60
37
41
  @lease_renew_delay = 300
38
42
  @lease_renew_retries = 4
39
- @lease_renew_error_listener = proc {}
40
- @lease_renew_success_listener = proc {}
43
+ @lease_renew_error_listener = -> {}
44
+ @lease_renew_success_listener = -> {}
45
+ @vault_initializer = -> {}
41
46
  end
42
47
 
43
48
  def setup_lease_refresher(cache, previous_task = nil)
@@ -16,7 +16,7 @@ module SettingsReader
16
16
  end
17
17
 
18
18
  def get(address)
19
- return unless (vault_secret = get_secret_with_retries(address))
19
+ return unless (vault_secret = get_secret_with_authentication(address))
20
20
 
21
21
  wrap_secret(address, vault_secret)
22
22
  rescue Vault::VaultError => e
@@ -26,7 +26,7 @@ module SettingsReader
26
26
  def renew(entry)
27
27
  return unless entry.leased?
28
28
 
29
- new_secret = renew_lease_with_retries(entry)
29
+ new_secret = renew_lease_with_authentication(entry)
30
30
  entry.update_renewed(new_secret)
31
31
  true
32
32
  rescue Vault::VaultError => e
@@ -35,12 +35,30 @@ module SettingsReader
35
35
 
36
36
  protected
37
37
 
38
+ def get_secret_with_authentication(address)
39
+ get_secret_with_retries(address)
40
+ rescue Vault::HTTPClientError => e # if not authenticated, let's reauthenticate and try once more
41
+ raise unless e.code == 403
42
+
43
+ config.vault_initializer.call
44
+ get_secret_with_retries(address)
45
+ end
46
+
38
47
  def get_secret_with_retries(address)
39
48
  Vault.with_retries(Vault::HTTPConnectionError, attempts: config.retrieval_retries) do
40
49
  get_secret(address)
41
50
  end
42
51
  end
43
52
 
53
+ def renew_lease_with_authentication(address)
54
+ renew_lease_with_retries(address)
55
+ rescue Vault::HTTPClientError => e # if not authenticated, let's reauthenticate and try once more
56
+ raise unless e.code == 403
57
+
58
+ config.vault_initializer.call
59
+ renew_lease_with_retries(address)
60
+ end
61
+
44
62
  def renew_lease_with_retries(address)
45
63
  Vault.with_retries(Vault::HTTPConnectionError, attempts: config.lease_renew_retries) do
46
64
  renew_lease(address)
@@ -2,13 +2,14 @@ module SettingsReader
2
2
  module VaultResolver
3
3
  # Wrapper around vault secret object
4
4
  class Entry
5
- attr_reader :address, :secret
5
+ attr_reader :address, :secret, :data
6
6
 
7
7
  MONTH = 30 * 60 * 60
8
8
 
9
9
  def initialize(address, secret)
10
10
  @address = address
11
11
  @secret = secret
12
+ @data = extract_data(secret)
12
13
  @lease_started = Time.now
13
14
  end
14
15
 
@@ -34,11 +35,15 @@ module SettingsReader
34
35
 
35
36
  def update_renewed(new_secret)
36
37
  @secret = new_secret
38
+ @data = @data.merge(extract_data(new_secret).compact)
37
39
  @lease_started = Time.now
38
40
  end
39
41
 
40
42
  def value_for(attribute)
41
- secret.data[attribute.to_sym]
43
+ return data[attribute.to_sym] if data.key?(attribute.to_sym)
44
+ return secret.public_send(attribute) if secret.respond_to?(attribute)
45
+
46
+ nil
42
47
  end
43
48
 
44
49
  def to_s
@@ -48,6 +53,12 @@ module SettingsReader
48
53
  def lease_duration
49
54
  @secret.lease_duration.to_i
50
55
  end
56
+
57
+ private
58
+
59
+ def extract_data(secret)
60
+ secret.respond_to?(:data) && secret.data ? secret.data : {}
61
+ end
51
62
  end
52
63
  end
53
64
  end
@@ -1,5 +1,5 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
- VERSION = '0.4.0'.freeze
3
+ VERSION = '0.4.3'.freeze
4
4
  end
5
5
  end
@@ -28,6 +28,7 @@ module SettingsReader
28
28
  def self.configure(&block)
29
29
  @configuration = SettingsReader::VaultResolver::Configuration.new
30
30
  block&.call(@configuration)
31
+ @configuration.vault_initializer.call
31
32
  @refresher_timer_task = @configuration.setup_lease_refresher(cache, refresher_timer_task)
32
33
  end
33
34
 
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.0
4
+ version: 0.4.3
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-04-12 00:00:00.000000000 Z
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -62,6 +62,7 @@ executables: []
62
62
  extensions: []
63
63
  extra_rdoc_files: []
64
64
  files:
65
+ - ".circleci/config.yml"
65
66
  - ".github/workflows/linters.yml"
66
67
  - ".github/workflows/main.yml"
67
68
  - ".gitignore"
@@ -118,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
119
  - !ruby/object:Gem::Version
119
120
  version: '0'
120
121
  requirements: []
121
- rubygems_version: 3.1.6
122
+ rubygems_version: 3.2.32
122
123
  signing_key:
123
124
  specification_version: 4
124
125
  summary: Settings Reader plugin to resolve values using in Hashicorp Vault