cloud-config 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5d99c6f38f07031a7da456fa285c345a87ed6f124a534d2b5fe004540743e85
4
- data.tar.gz: cba8c49a6fcc40d3cfac3f451826a3fddaaf6a0d8a7271033fbc7e833dc47cbb
3
+ metadata.gz: 14a075dc5489c921dd0cc57ce34900f1b44956430f04b7f65bae877191cb1146
4
+ data.tar.gz: 93ae7d5b13fa07e10f1e4f32c9e6b26707d42466aab400f6314f0542ad05d254
5
5
  SHA512:
6
- metadata.gz: b883d58ca786602fe85135a77a31959c00dcd7d3af7534e63889320fb7d1d739285bb048fa6f2c72fb309c8ecf9ed4bc95da513be39a9d073a14ec768c4cb7c7
7
- data.tar.gz: 0d61a08ecbba70c9ae743cf8fa84c68772da1a6a3566716fb9f17ed564472150ef5c6dcbc38e0f6b9722437327feef6cac85c6aca02e1bcd2c49ab0812c003fb
6
+ metadata.gz: 816e3d5ddf6ecc65d7ebbaef7fe5f37df5cc43296fd8bfb7b9e8ff89d6fa9e0fe192df70669b228196940973e1fe8558352388afd65dc8ab2949cba3f9148dde
7
+ data.tar.gz: 50661d530a79e7407faa3b1d54f9f70aa958af68f07b4fb19092027888da1129fbf689e2d92a079582a16ac7039ff5f096fa4ccc95b5889911f7c75bebc4de49
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.2] - 2023-05-21
4
+
5
+ Enhancements:
6
+
7
+ - Add AWS Secrets Manager provider
8
+
9
+ ## [Released]
10
+
11
+ ## [0.2.1] - 2023-05-21
12
+
13
+ Enhancements:
14
+
15
+ - Allow options to be passed when fetching configuration from the provider
16
+
17
+
3
18
  ## [0.2.0] - 2023-05-20
4
19
 
5
20
  Bug fixes:
@@ -11,7 +26,6 @@ Enhancements:
11
26
  - Reset cache for single key
12
27
  - Lookup providers by configuration key
13
28
 
14
- ## [Released]
15
29
 
16
30
  ## [0.1.0] - 2023-05-17
17
31
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloud-config (0.2.0)
4
+ cloud-config (0.2.2)
5
5
  parallel
6
6
 
7
7
  GEM
@@ -15,6 +15,9 @@ GEM
15
15
  aws-partitions (~> 1, >= 1.651.0)
16
16
  aws-sigv4 (~> 1.5)
17
17
  jmespath (~> 1, >= 1.6.1)
18
+ aws-sdk-secretsmanager (1.75.0)
19
+ aws-sdk-core (~> 3, >= 3.165.0)
20
+ aws-sigv4 (~> 1.1)
18
21
  aws-sdk-ssm (1.150.0)
19
22
  aws-sdk-core (~> 3, >= 3.165.0)
20
23
  aws-sigv4 (~> 1.1)
@@ -89,6 +92,7 @@ PLATFORMS
89
92
  aarch64-linux
90
93
 
91
94
  DEPENDENCIES
95
+ aws-sdk-secretsmanager
92
96
  aws-sdk-ssm
93
97
  cloud-config!
94
98
  mock_redis
data/README.md CHANGED
@@ -4,7 +4,7 @@ A library to modernise the way applications fetch configuration. Typically an ap
4
4
 
5
5
  A modern approach stores configuration remotely, often using key/value databases. Storing configurations in a single database, separately from the codebase reduces infrastructure dependency. Configuration updates can automatically sync with any application, without requiring redeployments. Security risk is greatly reduced, since configurations can be securely stored. Another goal with this approach is creating an environmentless codebase. The application no longer needs to know which environment it's running in, since all the configuration is handled by the infrastucture.
6
6
 
7
- Another common problem is password rotation. A typical application will need to be restarted or even redeployed when the configuration settings change, such as rotating passwords. CloudConfig can handle this elegantly, improving the uptime and resilience of the application.
7
+ Another common problem is password rotation. A typical application will need to be restarted or even redeployed when the configuration settings change. CloudConfig can handle this elegantly, improving application uptime and resilience.
8
8
 
9
9
  ## Installation
10
10
 
@@ -75,6 +75,11 @@ CloudConfig.configure do
75
75
  provider :in_memory do
76
76
  setting :key1, cache: 60 # 60 seconds
77
77
  end
78
+
79
+ # If the datastore has configurable options
80
+ provider :aws_parameter_store do
81
+ setting :key1, with_decryption: true
82
+ end
78
83
  end
79
84
  ```
80
85
 
@@ -109,7 +114,7 @@ class CustomProvider
109
114
  def initialize(params = {}); end
110
115
 
111
116
  # Define `get` for fetching keys from the remote datastore
112
- def get(key); end
117
+ def get(key, opts = {}); end
113
118
 
114
119
  # Define `set` for storing keys in the remote datastore
115
120
  def set(key, value); end
data/cloud-config.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.metadata['homepage_uri'] = spec.homepage
23
23
  spec.metadata['source_code_uri'] = spec.homepage
24
- spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
24
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
25
25
 
26
26
  # Specify which files should be added to the gem when it is released.
27
27
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  # Uncomment to register a new dependency of your gem
38
38
  spec.add_dependency 'parallel'
39
39
 
40
+ spec.add_development_dependency 'aws-sdk-secretsmanager'
40
41
  spec.add_development_dependency 'aws-sdk-ssm'
41
42
  spec.add_development_dependency 'mock_redis'
42
43
  spec.add_development_dependency 'pry'
@@ -11,15 +11,15 @@ gemfile do
11
11
  gem 'cloud-config', path: '..'
12
12
  end
13
13
 
14
- require 'benchmark'
15
14
  require 'cloud-config/providers/aws_parameter_store'
16
15
 
16
+ # @note: Make sure the `parameter_store_example` key is set in the parameter store
17
17
  CloudConfig.configure do
18
18
  provider :aws_parameter_store do
19
19
  setting :parameter_store_example
20
20
  end
21
21
  end
22
22
 
23
- puts 'Fetching key parameter_store_example'
23
+ puts 'Fetching key: parameter_store_example'
24
24
  value = CloudConfig.get(:parameter_store_example)
25
- puts "Fetched value #{value}"
25
+ puts "Fetched value: #{value}"
@@ -15,6 +15,7 @@ require 'benchmark'
15
15
  require 'cloud-config/cache/in_memory'
16
16
  require 'cloud-config/providers/aws_parameter_store'
17
17
 
18
+ # @note: Make sure the `parameter_store_example` key is set in the parameter store
18
19
  CloudConfig.configure do
19
20
  cache_client CloudConfig::Cache::InMemory.new
20
21
 
@@ -25,16 +26,20 @@ end
25
26
 
26
27
  value = nil
27
28
 
28
- puts 'Fetching key parameter_store_example'
29
+ puts 'Fetching key; parameter_store_example'
29
30
  time = Benchmark.measure { value = CloudConfig.get(:parameter_store_example) }
30
- puts "Fetched value #{value} in #{time.real.round(5)} seconds"
31
+ puts "Fetched value: #{value} in #{time.real.round(5)} seconds"
32
+
33
+ puts
31
34
 
32
- puts 'Fetching key parameter_store_example (cached)'
35
+ puts 'Fetching key: parameter_store_example (cached)'
33
36
  time = Benchmark.measure { value = CloudConfig.get(:parameter_store_example) }
34
- puts "Fetched value #{value} in #{time.real.round(5)} seconds"
37
+ puts "Fetched value: #{value} in #{time.real.round(5)} seconds"
35
38
 
36
39
  sleep 5
37
40
 
41
+ puts
42
+
38
43
  puts 'Fetching key parameter_store_example'
39
44
  time = Benchmark.measure { value = CloudConfig.get(:parameter_store_example) }
40
45
  puts "Fetched value #{value} in #{time.real.round(5)} seconds"
@@ -15,6 +15,7 @@ require 'benchmark'
15
15
  require 'cloud-config/cache/in_memory'
16
16
  require 'cloud-config/providers/aws_parameter_store'
17
17
 
18
+ # @note: Make sure the `parameter_store_example` key is set in the parameter store
18
19
  CloudConfig.configure do
19
20
  cache_client CloudConfig::Cache::InMemory.new
20
21
 
@@ -27,12 +28,14 @@ CloudConfig.preload
27
28
 
28
29
  value = nil
29
30
 
30
- puts 'Fetching key parameter_store_example (cached)'
31
+ puts 'Fetching key: parameter_store_example (cached)'
31
32
  time = Benchmark.measure { value = CloudConfig.get(:parameter_store_example) }
32
- puts "Fetched value #{value} in #{time.real.round(5)} seconds"
33
+ puts "Fetched value: #{value} in #{time.real.round(5)} seconds"
33
34
 
34
35
  sleep 5
35
36
 
36
- puts 'Fetching key parameter_store_example'
37
+ puts
38
+
39
+ puts 'Fetching key: parameter_store_example'
37
40
  time = Benchmark.measure { value = CloudConfig.get(:parameter_store_example) }
38
- puts "Fetched value #{value} in #{time.real.round(5)} seconds"
41
+ puts "Fetched value: #{value} in #{time.real.round(5)} seconds"
@@ -41,5 +41,7 @@ rescue Faraday::ServerError
41
41
 
42
42
  sleep 1
43
43
 
44
+ puts
45
+
44
46
  retry
45
47
  end
@@ -0,0 +1,40 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+
8
+ gem 'nokogiri'
9
+ gem 'aws-sdk-ssm'
10
+
11
+ gem 'cloud-config', path: '..'
12
+ end
13
+
14
+ require 'benchmark'
15
+ require 'cloud-config/providers/aws_parameter_store'
16
+
17
+ # @note: Make sure the `encrypted_key` key is set in the parameter store
18
+ CloudConfig.configure do
19
+ provider :aws_parameter_store do
20
+ setting :encrypted_key
21
+ end
22
+ end
23
+
24
+ puts 'Fetching key: encrypted_key'
25
+ value = CloudConfig.get(:encrypted_key)
26
+ puts "Fetched value: #{value}"
27
+
28
+ puts
29
+
30
+ CloudConfig.reset!
31
+
32
+ CloudConfig.configure do
33
+ provider :aws_parameter_store do
34
+ setting :encrypted_key, with_decryption: true
35
+ end
36
+ end
37
+
38
+ puts 'Fetching key: encrypted_key (decrypt)'
39
+ value = CloudConfig.get(:encrypted_key)
40
+ puts "Fetched value: #{value}"
@@ -0,0 +1,25 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+
8
+ gem 'nokogiri'
9
+ gem 'aws-sdk-secretsmanager'
10
+
11
+ gem 'cloud-config', path: '..'
12
+ end
13
+
14
+ require 'cloud-config/providers/aws_secrets_manager'
15
+
16
+ # @note: Make sure the `secret_example` key is set in AWS Secrets Manager
17
+ CloudConfig.configure do
18
+ provider :aws_secrets_manager do
19
+ setting :secret_example
20
+ end
21
+ end
22
+
23
+ puts 'Fetching key: secret_example'
24
+ value = CloudConfig.get(:secret_example)
25
+ puts "Fetched value: #{value}"
@@ -2,10 +2,10 @@
2
2
 
3
3
  module CloudConfig
4
4
  module Providers
5
- # A class for fetching configuration from the AWS Parameter Store
5
+ # A class for fetching configuration from AWS Parameter Store
6
6
  #
7
7
  # @example
8
- # provider = AwsParameterStore.new # Assuming AWS credentials are already configured
8
+ # provider = CloudConfig::Providers::AwsParameterStore.new # Assuming AWS credentials are already configured
9
9
  # provider.set(:example_key, :example_value)
10
10
  # provider.get(:example_key) #=> 'example_value'
11
11
  class AwsParameterStore
@@ -13,18 +13,31 @@ module CloudConfig
13
13
  # @return [Aws::SSM::Client]
14
14
  attr_reader :client
15
15
 
16
+ # @!attribute [r] Whether parameters need to be decrypted
17
+ # @return [Boolean]
18
+ attr_reader :with_decryption
19
+
16
20
  # Create a new instance of {AwsParameterStore}.
17
- def initialize(_params = {})
21
+ #
22
+ # @param [Hash] opts Parameter store options
23
+ # @option opts [Boolean] :with_decryption Whether all keys need to be decrypted
24
+ def initialize(opts = {})
18
25
  @client = Aws::SSM::Client.new
26
+
27
+ @with_decryption = opts.fetch(:with_decryption, false)
19
28
  end
20
29
 
21
30
  # Fetch the value of the key
22
31
  #
23
32
  # @param key [String,Symbol] Key to fetch
33
+ # @param [Hash] opts for fetching the key
34
+ # @option opts [Boolean] :with_decryption Whether the key needs decrypting
24
35
  #
25
36
  # @return [String] Value of the key
26
- def get(key)
27
- client.get_parameter(name: key).parameter.value
37
+ def get(key, opts = {})
38
+ decrypt = opts.fetch(:with_decryption) { with_decryption }
39
+
40
+ client.get_parameter(name: key, with_decryption: decrypt).parameter.value
28
41
  end
29
42
 
30
43
  # Set the value of the key
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CloudConfig
4
+ module Providers
5
+ # A class for fetching configuration from AWS Secrets Manager
6
+ #
7
+ # @example
8
+ # provider = CloudConfig::Providers::AwsSecretsManager.new # Assuming AWS credentials are already configured
9
+ # provider.set(:example_key, :example_value)
10
+ # provider.get(:example_key) #=> 'example_value'
11
+ class AwsSecretsManager
12
+ # @!attribute [r] An instance of the AWS Secrets Manager client
13
+ # @return [Aws::SSM::Client]
14
+ attr_reader :client
15
+
16
+ # Create a new instance of {AwsSecretsManager}.
17
+ def initialize(_opts = {})
18
+ @client = Aws::SecretsManager::Client.new
19
+ end
20
+
21
+ # Fetch the value of the key
22
+ #
23
+ # @param key [String,Symbol] Key to fetch
24
+ #
25
+ # @return [String] Value of the key
26
+ def get(key, _opts = {})
27
+ secret = client.get_secret_value(secret_id: key)
28
+
29
+ secret.secret_binary || secret.secret_string
30
+ end
31
+
32
+ # Set the value of the key
33
+ #
34
+ # @param key [String,Symbol] Key to set
35
+ # @param value [Object] Value of the key
36
+ def set(key, value)
37
+ client.put_secret_value(secret_id: key, secret_string: value)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -5,7 +5,7 @@ module CloudConfig
5
5
  # A class that acts as a provider for storing configuration in-memory
6
6
  #
7
7
  # @example
8
- # provider = InMemory.new # Assuming AWS credentials are already configured
8
+ # provider = CloudConfig::Providers::InMemory.new # Assuming AWS credentials are already configured
9
9
  # provider.set(:example_key, :example_value)
10
10
  # provider.get(:example_key) #=> 'example_value'
11
11
  class InMemory
@@ -14,7 +14,7 @@ module CloudConfig
14
14
  attr_reader :settings
15
15
 
16
16
  # Create an instance of {InMemory}
17
- def initialize(_params = {})
17
+ def initialize(_opts = {})
18
18
  @settings = {}
19
19
  end
20
20
 
@@ -23,7 +23,7 @@ module CloudConfig
23
23
  # @param key [String,Symbol] Key to fetch
24
24
  #
25
25
  # @return [Object] Value of the key
26
- def get(key)
26
+ def get(key, _opts = {})
27
27
  settings[key]
28
28
  end
29
29
 
@@ -5,7 +5,7 @@ module CloudConfig
5
5
  # A class for fetching configuration from the AWS Parameter Store
6
6
  #
7
7
  # @example
8
- # provider = YamlFile.new # Assuming AWS credentials are already configured
8
+ # provider = CloudConfig::Providers::YamlFile.new # Assuming AWS credentials are already configured
9
9
  # provider.set(:example_key, :example_value)
10
10
  # provider.get(:example_key) #=> 'example_value'
11
11
  class YamlFile
@@ -15,9 +15,10 @@ module CloudConfig
15
15
 
16
16
  # Create an instance of {YamlFile}
17
17
  #
18
- # @option params [Hash] :filename Name of the YAML file
19
- def initialize(params = {})
20
- @contents = YAML.load_file(params[:filename]) || {}
18
+ # @param [Hash] opts Yaml file options
19
+ # @option opts [String] :filename Name of the YAML file
20
+ def initialize(opts = {})
21
+ @contents = YAML.load_file(opts[:filename]) || {}
21
22
  end
22
23
 
23
24
  # Fetch the value of the key
@@ -25,7 +26,7 @@ module CloudConfig
25
26
  # @param key [String,Symbol] Key to fetch
26
27
  #
27
28
  # @return [Object] Value of the key
28
- def get(key)
29
+ def get(key, _opts = {})
29
30
  contents[key]
30
31
  end
31
32
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module CloudConfig
4
4
  # Version of CloudConfig
5
- VERSION = '0.2.0'
5
+ VERSION = '0.2.2'
6
6
  end
data/lib/cloud-config.rb CHANGED
@@ -90,7 +90,7 @@ module CloudConfig
90
90
  # @return [Object] Value of the key
91
91
  def load_key(provider_config, key, reset_cache: false)
92
92
  with_cache(key, reset_cache:, expire_in: provider_config.settings[key][:cache]) do
93
- provider_config.provider.get(key)
93
+ provider_config.provider.get(key, provider_config.settings[key])
94
94
  end
95
95
  end
96
96
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - hypernova2002
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-20 00:00:00.000000000 Z
11
+ date: 2023-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk-secretsmanager
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: aws-sdk-ssm
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +245,8 @@ files:
231
245
  - examples/002_parameter_store_with_cache.rb
232
246
  - examples/003_parameter_store_with_preload.rb
233
247
  - examples/004_handling_configuration_changes.rb
248
+ - examples/005_parameter_store_encrypted_key.rb
249
+ - examples/006_secrets_manager.rb
234
250
  - lib/cloud-config.rb
235
251
  - lib/cloud-config/cache.rb
236
252
  - lib/cloud-config/cache/in_memory.rb
@@ -240,6 +256,7 @@ files:
240
256
  - lib/cloud-config/provider_options.rb
241
257
  - lib/cloud-config/providers.rb
242
258
  - lib/cloud-config/providers/aws_parameter_store.rb
259
+ - lib/cloud-config/providers/aws_secrets_manager.rb
243
260
  - lib/cloud-config/providers/in_memory.rb
244
261
  - lib/cloud-config/providers/yaml_file.rb
245
262
  - lib/cloud-config/version.rb
@@ -250,7 +267,7 @@ licenses:
250
267
  metadata:
251
268
  homepage_uri: http://github.com/hypernova2002/cloud-config
252
269
  source_code_uri: http://github.com/hypernova2002/cloud-config
253
- changelog_uri: http://github.com/hypernova2002/cloud-config/CHANGELOG.md
270
+ changelog_uri: http://github.com/hypernova2002/cloud-config/blob/main/CHANGELOG.md
254
271
  rubygems_mfa_required: 'true'
255
272
  post_install_message:
256
273
  rdoc_options: []