rrx_config 0.1.0 → 0.1.1

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: ec601c3c455ddac07928729e842a56bdf68169c7c79933a2f9fbf1f4f73ef731
4
- data.tar.gz: 5c6b2d173c96c364e8a950d8b73629d621bf2efe9ee6c0116e31b62b5249a264
3
+ metadata.gz: 189f07461b184201b231e0ec6e8c6259b7f4b19b94f5a45f3096bb13a48f859c
4
+ data.tar.gz: b25f916d5035b9c39ec42b8a0568d9b82c1bb2e80478c4ebc1149aee4cce1de2
5
5
  SHA512:
6
- metadata.gz: 93bfbb4cd84cf2dd39781d68073c85e76a9dc77e66c64d034395870fb79c4c14d1016890720aa5bc312fdb8d21e91c832b6adbb4879dd8cb4cc9aafced95f5b2
7
- data.tar.gz: 9241012dda9185d410020eb2ed98fce23ec8061fc5c0821164578d83ef1a6997e893ee5457019ef0d7fee35f4debdcde54e7746691ae8f2c965996f90d47311d
6
+ metadata.gz: ba6405b01d5bcc63f4ff0d2e05f08bcd7f7aade7150d77c2ba9b19a77553cf6f5f73b1ca3395bf4e6da035e8181b52832295d689e8bbe40e236a4f78a673dfd4
7
+ data.tar.gz: 77448022e1afa2d5cf43877600e0a738cf62bb9dcdd5dd47b92ba94a7626694a2ede76c388e47128b661a0ebe811e34c6493a5052ab594ec263de433124b1104
@@ -2,6 +2,7 @@
2
2
  <profile version="1.0">
3
3
  <option name="myName" value="Project Default" />
4
4
  <inspection_tool class="RbsMissingTypeSignature" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
5
+ <inspection_tool class="RubyCaseWithoutElseBlockInspection" enabled="false" level="WARNING" enabled_by_default="false" />
5
6
  <inspection_tool class="RubyMismatchedParameterType" enabled="false" level="WARNING" enabled_by_default="false" />
6
7
  </profile>
7
8
  </component>
data/.idea/rrx_config.iml CHANGED
@@ -12,7 +12,7 @@
12
12
  <orderEntry type="jdk" jdkName="Remote-asdf: ruby-3.2.2 (-p53" jdkType="RUBY_SDK" />
13
13
  <orderEntry type="sourceFolder" forTests="false" />
14
14
  <orderEntry type="module-library">
15
- <library name="rrx_dev (v0.1.0) [path][gem]" type="rubylib">
15
+ <library name="rrx_dev (v0.1.2) [path][gem]" type="rubylib">
16
16
  <properties>
17
17
  <option name="version" value="4" />
18
18
  </properties>
@@ -60,6 +60,7 @@
60
60
  <orderEntry type="library" scope="PROVIDED" name="aws-eventstream (v1.3.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
61
61
  <orderEntry type="library" scope="PROVIDED" name="aws-partitions (v1.877.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
62
62
  <orderEntry type="library" scope="PROVIDED" name="aws-sdk-core (v3.190.1, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
63
+ <orderEntry type="library" scope="PROVIDED" name="aws-sdk-rds (v1.213.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
63
64
  <orderEntry type="library" scope="PROVIDED" name="aws-sdk-secretsmanager (v1.88.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
64
65
  <orderEntry type="library" scope="PROVIDED" name="aws-sigv4 (v1.8.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
65
66
  <orderEntry type="library" scope="PROVIDED" name="base64 (v0.2.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
@@ -92,6 +93,7 @@
92
93
  <orderEntry type="library" scope="PROVIDED" name="minitest (v5.20.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
93
94
  <orderEntry type="library" scope="PROVIDED" name="msgpack (v1.7.2, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
94
95
  <orderEntry type="library" scope="PROVIDED" name="mutex_m (v0.2.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
96
+ <orderEntry type="library" scope="PROVIDED" name="mysql2 (v0.5.5, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
95
97
  <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.16.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
96
98
  <orderEntry type="library" scope="PROVIDED" name="parallel (v1.24.0, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
97
99
  <orderEntry type="library" scope="PROVIDED" name="parser (v3.2.2.4, Remote-asdf: ruby-3.2.2 (-p53) [gem]" level="application" />
data/Gemfile CHANGED
@@ -7,3 +7,5 @@ gem 'rrx_dev', path: '../rrx_dev'
7
7
 
8
8
  gem 'sqlite3'
9
9
  gem 'aws-sdk-secretsmanager'
10
+ gem 'aws-sdk-rds'
11
+ gem 'mysql2'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../rrx_dev
3
3
  specs:
4
- rrx_dev (0.1.1)
4
+ rrx_dev (0.1.2)
5
5
  active_record_query_trace
6
6
  activesupport (~> 7.1.0)
7
7
  bootsnap
@@ -22,7 +22,7 @@ PATH
22
22
  PATH
23
23
  remote: .
24
24
  specs:
25
- rrx_config (0.1.0)
25
+ rrx_config (0.1.1)
26
26
  railties
27
27
 
28
28
  GEM
@@ -72,6 +72,9 @@ GEM
72
72
  aws-partitions (~> 1, >= 1.651.0)
73
73
  aws-sigv4 (~> 1.8)
74
74
  jmespath (~> 1, >= 1.6.1)
75
+ aws-sdk-rds (1.213.0)
76
+ aws-sdk-core (~> 3, >= 3.188.0)
77
+ aws-sigv4 (~> 1.1)
75
78
  aws-sdk-secretsmanager (1.88.0)
76
79
  aws-sdk-core (~> 3, >= 3.188.0)
77
80
  aws-sigv4 (~> 1.1)
@@ -122,6 +125,7 @@ GEM
122
125
  minitest (5.20.0)
123
126
  msgpack (1.7.2)
124
127
  mutex_m (0.2.0)
128
+ mysql2 (0.5.5)
125
129
  nokogiri (1.16.0-x86_64-linux)
126
130
  racc (~> 1.4)
127
131
  parallel (1.24.0)
@@ -245,7 +249,9 @@ PLATFORMS
245
249
  x86_64-linux
246
250
 
247
251
  DEPENDENCIES
252
+ aws-sdk-rds
248
253
  aws-sdk-secretsmanager
254
+ mysql2
249
255
  rrx_config!
250
256
  rrx_dev!
251
257
  sqlite3
data/README.md CHANGED
@@ -1,9 +1,6 @@
1
1
  # RrxConfig
2
2
 
3
-
4
- TODO: Delete this and the text below, and describe your gem
5
-
6
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rrx_config`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Ruby on Rails application configuration support.
7
4
 
8
5
  ## Installation
9
6
 
@@ -17,7 +14,8 @@ If bundler is not being used to manage dependencies, install the gem by executin
17
14
 
18
15
  ## Usage
19
16
 
20
- This gem loads runtime application configuration from an external source
17
+ This gem loads runtime application configuration from JSON provided by an external source.
18
+ Configurations are stored as immutable Ruby `Data` objects.
21
19
 
22
20
  For example, with the JSON config
23
21
 
@@ -40,16 +38,20 @@ def my_code
40
38
  end
41
39
  ```
42
40
 
43
- Configurations are stored as immutable Ruby `Data` objects. You can test for optional values:
41
+ You can test for optional values using standard mechanisms:
44
42
 
45
43
  ```ruby
46
- optional_stuff if RrxConfig.members.include?(:optional_thing)
47
- deep_optional_stuff if RrxConfig.optional_thing.members.include?(:deep_thoughts)
44
+ optional_stuff if RrxConfig.respond_to?(:optional_thing)
45
+ deep_optional_stuff if RrxConfig.optional_thing.include?(:deep_thoughts)
46
+
47
+ optional_flag = RrxConfig.try(:optional).try(:flag) || DEFAULT_FLAG
48
48
 
49
49
  # Root-level configs can also be tested with the xxxx? syntax
50
50
  optional_stuff if RrxConfig.optional_thing?
51
51
  ```
52
52
 
53
+ ## Configuration Sources
54
+
53
55
  ### Environment
54
56
 
55
57
  Set the `RRX_CONFIG` environment variable to the required JSON configuration
@@ -59,11 +61,53 @@ Set the `RRX_CONFIG` environment variable to the required JSON configuration
59
61
  Loads configuration from an AWS secret that contains the required JSON configuration. Recommended when deploying on AWS.
60
62
  By default will use the implicit AWS context that is assigned by the instance role.
61
63
 
62
- Set the `RRX_CONFIG_AWS_SECRET` to the name of the secret to read.
64
+ Set the `RRX_CONFIG_AWS_SECRET` environment variable to the name of the secret to read.
63
65
 
64
- For local integration testing, set `RRX_AWS_PROFILE` to use local AWS credentials. The profile must have been
66
+ For local integration testing, set `RRX_AWS_PROFILE` to use local AWS credentials. The profile must be
65
67
  configured in the local AWS client (typically `~/.aws/credentials`).
66
68
 
69
+ ### Local File Configuration
70
+
71
+ For development purposes, the gem will also check for the following files:
72
+
73
+ * `{rails_root}/spec/spec_config.json` if `RAILS_ENV=test`
74
+ * `{rails_root}/local_config.json`
75
+
76
+ ## Database Support
77
+
78
+ If the loaded config contains a root-level `database` item then it will be used to configure the
79
+ application database instead of `database.yml`.
80
+
81
+ ### AWS RDS IAM Authentication
82
+
83
+ The gem also adds support for AWS RDS authentication using IAM to MySQL/MariaDB databases. If the RDS instance
84
+ and user account has been configured correctly, replace the `password` argument with `iam: true`. This is supported
85
+ using the `database` configuration or `database.yml`.
86
+
87
+ The gem will automatically download the required CA certificates and set the necessary client options.
88
+
89
+ Using JSON configuration:
90
+ ```json
91
+ {
92
+ "database": {
93
+ "adapter": "mysql2",
94
+ "host": "rds-db-address...rds.amazonaws.com",
95
+ "port": 3306,
96
+ "username": "my_app_user",
97
+ "iam": true
98
+ }
99
+ }
100
+ ```
101
+ Using `database.yml`:
102
+ ```yaml
103
+ production:
104
+ adapter: mysql2
105
+ host: rds-db-address...rds.amazonaws.com
106
+ port: 3306
107
+ username: my_app_user
108
+ iam: true
109
+ ```
110
+
67
111
  ## Development
68
112
 
69
113
  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.
@@ -72,7 +116,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
72
116
 
73
117
  ## Contributing
74
118
 
75
- Bug reports and pull requests are welcome on GitHub at https://github.com/rrx/rrx_config. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/rrx_config/blob/main/CODE_OF_CONDUCT.md).
119
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rails-rrx/rrx_config. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/rrx_config/blob/main/CODE_OF_CONDUCT.md).
76
120
 
77
121
  ## License
78
122
 
@@ -80,4 +124,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
80
124
 
81
125
  ## Code of Conduct
82
126
 
83
- Everyone interacting in the RrxConfig project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/rrx_config/blob/main/CODE_OF_CONDUCT.md).
127
+ Everyone interacting in the RrxConfig project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rails-rrc/rrx_config/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RrxConfig
4
+ module Aws
5
+ PROFILE_VARIABLE = 'RRX_AWS_PROFILE'
6
+ REGION_VARIABLE = 'RRX_AWS_REGION'
7
+ REGION_DEFAULT = 'us-west-2'
8
+ PROFILE_DEFAULT = 'default'
9
+
10
+ class << self
11
+ def profile?
12
+ ENV.include?(PROFILE_VARIABLE)
13
+ end
14
+
15
+ def profile
16
+ ENV.fetch(PROFILE_VARIABLE, PROFILE_DEFAULT) unless Rails.env.production?
17
+ end
18
+
19
+ def credentials
20
+ if profile
21
+ require 'aws-sdk-core/shared_credentials'
22
+ ::Aws::SharedCredentials.new(profile_name: profile)
23
+ else
24
+ require 'aws-sdk-core/instance_profile_credentials'
25
+ require 'aws-sdk-core/ecs_credentials'
26
+ ec2 = ::Aws::InstanceProfileCredentials.new
27
+ ecs = ::Aws::ECSCredentials.new
28
+ ec2.set? ? ec2 : ecs
29
+ end
30
+ end
31
+
32
+ def client_args
33
+ { region:, credentials: }
34
+ end
35
+
36
+ def region
37
+ ENV.fetch(REGION_VARIABLE, REGION_DEFAULT)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -25,9 +25,9 @@ module RrxConfig
25
25
 
26
26
  def sources
27
27
  [
28
- Sources::LocalSource,
28
+ Sources::EnvironmentSource,
29
29
  Sources::AwsSecretSource,
30
- Sources::EnvironmentSource
30
+ Sources::LocalSource
31
31
  ]
32
32
  end
33
33
 
@@ -2,13 +2,83 @@
2
2
 
3
3
  if defined?(ActiveRecord)
4
4
  require 'active_record/database_configurations'
5
- ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
6
- if url
7
- ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, name, url, config)
8
- elsif RrxConfig.database?
9
- ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, name, RrxConfig.database.to_h)
10
- else
11
- ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, name, config)
5
+
6
+ module RrxConfig
7
+ class IamHashConfig < ActiveRecord::DatabaseConfigurations::HashConfig
8
+ GLOBAL_PEM_URL='https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem'
9
+
10
+ alias raw_configuration_hash configuration_hash
11
+
12
+ # @param [Hash] configuration_hash
13
+ def initialize(env_name, name, configuration_hash)
14
+ config = configuration_hash.except(:iam)
15
+ case config[:adapter]
16
+ when 'mysql2'
17
+ config[:enable_cleartext_plugin] = true
18
+ end
19
+ super(env_name, name, config)
20
+ end
21
+
22
+ def configuration_hash
23
+ { password:, sslca:, ssl_mode: :required }.reverse_merge!(raw_configuration_hash).freeze
24
+ end
25
+
26
+ def password
27
+ generator.auth_token(endpoint:, region:, user_name:)
28
+ end
29
+
30
+ def endpoint
31
+ "#{raw_configuration_hash[:host]}:#{raw_configuration_hash[:port]}"
32
+ end
33
+
34
+ def region
35
+ raw_configuration_hash.fetch(:region, Aws.region)
36
+ end
37
+
38
+ def user_name
39
+ raw_configuration_hash[:username] || raw_configuration_hash[:user]
40
+ end
41
+
42
+ def generator
43
+ require 'aws-sdk-rds'
44
+ require_relative './aws'
45
+ @generator ||= ::Aws::RDS::AuthTokenGenerator.new(credentials: Aws.credentials)
46
+ end
47
+
48
+ def sslca
49
+ unless sslca_path.exist?
50
+ require 'open-uri'
51
+ download = URI.open(GLOBAL_PEM_URL)
52
+ IO.copy_stream download, sslca_path
53
+ end
54
+ sslca_path.to_s
55
+ end
56
+
57
+ def sslca_path
58
+ @sslca_path ||= Rails.root.join('tmp/aws-rds-ca.pem')
59
+ end
60
+ end
61
+
62
+ def self.db_config_handler(env_name, name, url, config)
63
+ case
64
+ when url
65
+ # Pass to default handler
66
+ nil
67
+ when RrxConfig.database?
68
+ # Use config from RrxConfig
69
+ if RrxConfig.database.try(:iam)
70
+ IamHashConfig.new(env_name, name, RrxConfig.database.to_h)
71
+ else
72
+ ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, name, RrxConfig.database.to_h)
73
+ end
74
+ when config.fetch(:iam, false)
75
+ # Use standard config with IAM support
76
+ IamHashConfig.new(env_name, name, config)
77
+ end
12
78
  end
13
79
  end
80
+
81
+ ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
82
+ RrxConfig.db_config_handler env_name, name, url, config
83
+ end
14
84
  end
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative './base'
4
+ require_relative '../aws'
4
5
 
5
6
  module RrxConfig
6
7
  module Sources
7
8
  class AwsSecretSource < Base
8
9
  SECRET_VARIABLE = 'RRX_AWS_CONFIG_SECRET_NAME'
9
- PROFILE_VARIABLE = 'RRX_AWS_PROFILE'
10
- REGION_VARIABLE = 'RRX_AWS_REGION'
11
- REGION_DEFAULT = 'us-west-2'
12
10
 
13
11
  def read
14
12
  read_secret if secret_id
@@ -45,20 +43,12 @@ module RrxConfig
45
43
  @secret_name == :- ? nil : @secret_name
46
44
  end
47
45
 
48
- def credentials_profile
49
- profile = Rails.env.production? ? nil : ENV.fetch(PROFILE_VARIABLE, nil)
50
- profile || 'default'
51
- end
52
-
53
46
  ##
54
47
  # @return [Aws::SecretsManager::Client]
55
48
  def client
56
49
  @client ||= begin
57
50
  require 'aws-sdk-secretsmanager'
58
- Aws::SecretsManager::Client.new(
59
- region: ENV.fetch(REGION_VARIABLE, REGION_DEFAULT),
60
- profile: credentials_profile
61
- )
51
+ ::Aws::SecretsManager::Client.new(**Aws.client_args)
62
52
  end
63
53
  end
64
54
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RrxConfig
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rrx_config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Drew
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-10 00:00:00.000000000 Z
11
+ date: 2024-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -46,6 +46,7 @@ files:
46
46
  - README.md
47
47
  - Rakefile
48
48
  - lib/rrx_config.rb
49
+ - lib/rrx_config/aws.rb
49
50
  - lib/rrx_config/configuration.rb
50
51
  - lib/rrx_config/database_config.rb
51
52
  - lib/rrx_config/environment.rb