secvault 2.5.0 → 2.7.0

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: 7aa65a706270754c5654d4ddac89114d5c6f59f80c2bd1480d11dc0b350a57d9
4
- data.tar.gz: 9ce9a4d9661505ba37a8c827d8f5811c8b9ff0b2fab8f8a8b89bb9f53fb62618
3
+ metadata.gz: 51dbcfd2c3b3073fb06223b681fb358cf8c74aae00c90663470edc19b3a40cd0
4
+ data.tar.gz: f78b9e5a1bdcb9148d58e31791738179b38a401ae0416920b4a6ee557e024ffd
5
5
  SHA512:
6
- metadata.gz: ebd99a7e5c479c1bf98f7180414bcf7b77b45f70a19d56b3b20d734da069ed5f4d18b6855356a89d47475c6955f8ce5a4edc161e2ee13c5d4ab1494a4be38855
7
- data.tar.gz: 888b561a34ff6be3798accb339d812d0456e3e10df0f4725c2c522e080ccef70c6dc23e54cae76878b5e4a67a44b4b63527b5bd0386133907b3df9a6bbec3df5
6
+ metadata.gz: 99d55935f3754ed807d306e94c530259ae34c82d43e1b2827ace62a2e33fd8bed291d8af358597aa68b71d78737af402273644e2b5d9475c5540be234b2d5985
7
+ data.tar.gz: d24dfa1e4613602a15ee7d40aeabedb089edf9e88ea136960ca039d6298252d8e7cd4e8a50d6f815cedcbde9d6192320814ccf6694797633225a29e98b993842
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
1
  --format documentation
2
2
  --color
3
- --require spec_helper
3
+ --require spec_helper
data/README.md CHANGED
@@ -1,21 +1,12 @@
1
1
  # Secvault
2
2
 
3
- Restores the classic Rails `secrets.yml` functionality that was removed in Rails 7.2. Uses simple, plain YAML files for environment-specific secrets management with powerful features like YAML defaults, ERB interpolation, and multi-file configurations.
3
+ Restores Rails `secrets.yml` functionality for environment-specific secrets management using YAML files with ERB templating.
4
4
 
5
- **Rails Version Support:**
6
- - **Rails 7.1 and older**: Manual setup (see Older Rails Integration below)
7
- - **Rails 7.2+**: Automatic setup
8
- - **Rails 8.0+**: Full compatibility
9
-
10
- ## ✨ Key Features
5
+ ## Rails Version Support
11
6
 
12
- - 🔗 **YAML Anchor/Alias Support**: Use `default: &default` for shared configuration
13
- - 🌍 **ERB Interpolation**: Environment variables with type conversion (`ENV['VAR'].to_i`, boolean logic)
14
- - 📁 **Multi-File Loading**: Merge multiple YAML files (e.g., base + OAuth + local overrides)
15
- - 🔄 **Environment Switching**: Load different environments dynamically
16
- - 🛠️ **Development Tools**: Hot-reload secrets without server restart
17
- - 🔍 **Utility Methods**: `Secvault.active?` to check integration status
18
- - 🏗️ **Flexible Organization**: Feature-based, environment-based, or namespace-based file structures
7
+ - **Rails 7.2+**: Automatic setup (drop-in replacement for removed functionality)
8
+ - **Rails 7.1**: Manual setup required
9
+ - **Rails 8.0+**: Full compatibility
19
10
 
20
11
  ## Installation
21
12
 
@@ -24,261 +15,87 @@ Restores the classic Rails `secrets.yml` functionality that was removed in Rails
24
15
  gem 'secvault'
25
16
  ```
26
17
 
27
- ```bash
28
- bundle install
29
- ```
30
-
31
- ## Quick Start (Rails 7.2+)
18
+ ## Quick Start
32
19
 
33
- ```bash
34
- # 1. Create secrets.yml
35
- touch config/secrets.yml
20
+ Create `config/secrets.yml`:
36
21
 
37
- # 2. Edit with your favorite editor
38
- $EDITOR config/secrets.yml
39
- ```
40
-
41
- **Usage in your app:**
42
- ```ruby
43
- Rails.application.secrets.api_key
44
- Rails.application.secrets.database_password
45
- ```
46
-
47
- **Example secrets.yml with YAML defaults and ERB:**
48
22
  ```yaml
49
- # YAML defaults - inherited by all environments
50
- default: &default
51
- app_name: "My Application"
52
- database:
53
- adapter: "postgresql"
54
- pool: 5
55
- timeout: 5000
56
- api:
57
- timeout: 30
58
- retries: 3
59
-
60
23
  development:
61
- <<: *default # Inherit defaults
62
- api_key: "dev_api_key_123"
63
- database:
64
- host: "localhost"
65
- name: "myapp_development"
66
- api:
67
- base_url: "http://localhost:3000" # Override default
24
+ api_key: "dev_key_123"
25
+ database_url: "postgresql://localhost/myapp_dev"
68
26
 
69
27
  production:
70
- <<: *default # Inherit defaults
71
28
  api_key: <%= ENV['API_KEY'] %>
72
- database:
73
- host: <%= ENV['DATABASE_HOST'] %>
74
- name: <%= ENV['DATABASE_NAME'] %>
75
- pool: <%= ENV.fetch('DATABASE_POOL', '10').to_i %> # Type conversion
76
- api:
77
- base_url: <%= ENV['API_BASE_URL'] %>
78
-
79
- # Boolean conversion
80
- features:
81
- new_ui: <%= ENV.fetch('FEATURE_NEW_UI', 'true') == 'true' %>
82
-
83
- # Array conversion
84
- oauth_scopes: <%= ENV.fetch('OAUTH_SCOPES', 'email,profile').split(',') %>
29
+ database_url: <%= ENV['DATABASE_URL'] %>
85
30
  ```
86
31
 
87
- ## Multi-File Configuration
88
-
89
- Organize secrets across multiple files with a **super clean API**:
32
+ Access secrets in your app:
90
33
 
91
34
  ```ruby
92
- # config/initializers/secvault.rb
93
- require "secvault"
94
-
95
- # That's it! Just pass your files array
96
- Secvault.setup_multi_file!([
97
- 'config/secrets.yml', # Base secrets
98
- 'config/secrets.oauth.yml', # OAuth & APIs
99
- 'config/secrets.local.yml' # Local overrides
100
- ])
35
+ Rails.application.secrets.api_key
36
+ Rails.application.secrets.database_url
101
37
  ```
102
38
 
103
- **What this does automatically:**
104
- - ✅ Sets up Rails 7.1 compatibility (calls `setup_backward_compatibility_with_older_rails!`)
105
- - ✅ Loads and merges all files in order (later files override earlier ones)
106
- - ✅ Handles missing files gracefully
107
- - ✅ Adds `reload_secrets!` method in development
108
- - ✅ Provides logging (except in production)
109
- - ✅ Creates Rails.application.secrets with merged configuration
39
+ ## Multi-File Configuration
110
40
 
111
- **File organization example:**
112
- ```
113
- config/
114
- ├── secrets.yml # Base application secrets
115
- ├── secrets.oauth.yml # OAuth providers & external APIs
116
- ├── secrets.local.yml # Local development overrides (gitignored)
117
- ```
41
+ Load and merge multiple secrets files:
118
42
 
119
- **Advanced options:**
120
43
  ```ruby
121
- # Disable reload helper or logging
122
- Secvault.setup_multi_file!(files, reload_method: false, logger: false)
123
-
124
- # Use Pathname objects if needed
44
+ # config/initializers/secvault.rb
125
45
  Secvault.setup_multi_file!([
126
- Rails.root.join('config', 'secrets.yml'),
127
- Rails.root.join('config', 'secrets.oauth.yml')
128
- ])
129
- ```
130
-
131
- ## Advanced Usage
132
-
133
- **Manual multi-file parsing:**
134
- ```ruby
135
- # Parse multiple files - later files override earlier ones
136
- secrets = Rails::Secrets.parse([
137
46
  'config/secrets.yml',
138
47
  'config/secrets.oauth.yml',
139
48
  'config/secrets.local.yml'
140
- ], env: Rails.env)
141
- ```
142
-
143
- **Load specific environment:**
144
- ```ruby
145
- # Load production secrets in any environment
146
- production_secrets = Rails::Secrets.load(env: 'production')
147
-
148
- # Load development secrets
149
- dev_secrets = Rails::Secrets.load(env: 'development')
150
- ```
151
-
152
- **Environment-specific loading:**
153
- ```ruby
154
- # Load production secrets in any environment
155
- production_secrets = Rails::Secrets.load(env: 'production')
156
-
157
- # Load development secrets
158
- dev_secrets = Rails::Secrets.load(env: 'development')
49
+ ])
159
50
  ```
160
51
 
161
- ## ERB Features & Type Conversion
162
-
163
- Secvault supports powerful ERB templating with automatic type conversion:
52
+ Files are merged in order with deep merge support for nested hashes.
164
53
 
165
- ```yaml
166
- production:
167
- # String interpolation
168
- api_key: <%= ENV['API_KEY'] %>
169
-
170
- # Integer conversion
171
- database_pool: <%= ENV.fetch('DB_POOL', '10').to_i %>
172
-
173
- # Boolean conversion
174
- debug_enabled: <%= ENV.fetch('DEBUG', 'false') == 'true' %>
175
-
176
- # Array conversion
177
- allowed_hosts: <%= ENV.fetch('HOSTS', 'localhost,127.0.0.1').split(',') %>
178
-
179
- # Fallback values
180
- timeout: <%= ENV.fetch('TIMEOUT', '30').to_i %>
181
- adapter: <%= ENV.fetch('DB_ADAPTER', 'postgresql') %>
182
- ```
183
-
184
- ## Development Tools
54
+ ## Manual API
185
55
 
186
- **Hot-reload secrets (automatically available in development):**
187
56
  ```ruby
188
- # In Rails console - automatically added by setup_multi_file!
189
- reload_secrets! # Reloads all configured files without server restart
190
- # 🔄 Reloaded secrets from 3 files
57
+ # Parse specific files
58
+ secrets = Rails::Secrets.parse(['config/secrets.yml'], env: Rails.env)
191
59
 
192
- # Also available as:
193
- Rails.application.reload_secrets!
194
- ```
60
+ # Load default config/secrets.yml
61
+ secrets = Rails::Secrets.load(env: 'production')
195
62
 
196
- **Check integration status:**
197
- ```ruby
198
- Secvault.active? # Returns true if Secvault is managing secrets
63
+ # Check if active
64
+ Secvault.active? # => true/false
199
65
  ```
200
66
 
201
- ## Older Rails Integration
67
+ ## Rails 7.1 Integration
202
68
 
203
- For Rails versions with existing secrets functionality (like Rails 7.1), use Secvault to test before upgrading:
69
+ For Rails 7.1 with existing secrets functionality:
204
70
 
205
71
  ```ruby
206
72
  # config/initializers/secvault.rb
207
73
  Secvault.setup_backward_compatibility_with_older_rails!
208
74
  ```
209
75
 
210
- This replaces Rails.application.secrets with Secvault functionality. Your existing Rails 7.1 code works unchanged:
76
+ ## ERB Templating
211
77
 
212
- ```ruby
213
- Rails.application.secrets.api_key # ✅ Works
214
- Rails.application.secrets.oauth_settings # ✅ Works
215
- Rails::Secrets.load # ✅ Load default config/secrets.yml
216
- Rails::Secrets.parse(['custom.yml'], env: Rails.env) # ✅ Parse custom files
217
- ```
78
+ Supports full ERB templating for environment variables:
218
79
 
219
- **Check if Secvault is active:**
220
- ```ruby
221
- if Secvault.active?
222
- puts "Using Secvault for secrets management"
223
- else
224
- puts "Using default Rails secrets functionality"
225
- end
80
+ ```yaml
81
+ production:
82
+ api_key: <%= ENV['API_KEY'] %>
83
+ pool_size: <%= ENV.fetch('DB_POOL', '5').to_i %>
84
+ features:
85
+ enabled: <%= ENV.fetch('FEATURES_ON', 'false') == 'true' %>
86
+ hosts: <%= ENV.fetch('ALLOWED_HOSTS', 'localhost').split(',') %>
226
87
  ```
227
88
 
228
- ## Usage Examples
89
+ ## Development Tools
229
90
 
230
- **Basic usage:**
231
- ```ruby
232
- # Access secrets
233
- Rails.application.secrets.api_key
234
- Rails.application.secrets.database.host
235
- Rails.application.secrets.oauth.google.client_id
91
+ Reload secrets in development:
236
92
 
237
- # With YAML defaults, you get deep merging:
238
- Rails.application.secrets.database.adapter # "postgresql" (from default)
239
- Rails.application.secrets.database.host # "localhost" (from environment)
240
- ```
241
-
242
- **Multi-file merging:**
243
93
  ```ruby
244
- # Files loaded in order: base → oauth → local
245
- # Later files override earlier ones for the same keys
246
- # Hash values are deep merged, scalars are replaced
247
-
248
- Rails.application.secrets.api_key # Could be from base or local file
249
- Rails.application.secrets.oauth.google # From oauth file
250
- Rails.application.secrets.features.debug # From local file override
251
- ```
252
-
253
- ## Security Best Practices
254
-
255
- ### ⚠️ Production Security
256
- - **Never commit production secrets** to version control
257
- - **Use environment variables** in production with ERB: `<%= ENV['SECRET'] %>`
258
- - **Use ENV.fetch()** with fallbacks: `<%= ENV.fetch('SECRET', 'default') %>`
259
-
260
- ### 📝 File Management
261
- - **Add sensitive files** to `.gitignore`:
262
- ```gitignore
263
- config/secrets.yml # If contains sensitive data
264
- config/secrets.local.yml # Local development overrides
265
- config/secrets.production.yml # If used
266
- ```
267
-
268
- ### 🔑 Recommended Structure
269
- ```yaml
270
- # ✅ GOOD: Base file with safe defaults
271
- development:
272
- api_key: "safe_dev_key_for_team"
273
-
274
- production:
275
- api_key: <%= ENV['API_KEY'] %> # ✅ From environment
276
-
277
- # ❌ BAD: Secrets hardcoded in base file
278
- production:
279
- api_key: "super_secret_production_key" # ❌ Never do this
94
+ # Available after setup_multi_file!
95
+ reload_secrets!
96
+ Rails.application.reload_secrets!
280
97
  ```
281
98
 
282
99
  ## License
283
100
 
284
- MIT License - see [LICENSE](https://opensource.org/licenses/MIT)
101
+ MIT
@@ -6,9 +6,9 @@ module Secvault
6
6
  # This replicates the Rails < 7.2 Rails::Secrets module functionality
7
7
  module RailsSecrets
8
8
  extend self
9
-
9
+
10
10
  # Parse secrets from one or more YAML files
11
- #
11
+ #
12
12
  # Supports:
13
13
  # - ERB templating for environment variables
14
14
  # - Shared sections that apply to all environments
@@ -19,26 +19,26 @@ module Secvault
19
19
  # Examples:
20
20
  # # Single file
21
21
  # Rails::Secrets.parse(['config/secrets.yml'], env: 'development')
22
- #
22
+ #
23
23
  # # Multiple files (merged in order)
24
24
  # Rails::Secrets.parse([
25
25
  # 'config/secrets.yml',
26
26
  # 'config/secrets.local.yml'
27
27
  # ], env: 'development')
28
- #
28
+ #
29
29
  # # Load default config/secrets.yml
30
30
  # Rails::Secrets.load # uses current Rails.env
31
31
  # Rails::Secrets.load(env: 'production')
32
32
  def parse(paths, env:)
33
33
  Secvault::Secrets.parse(paths, env: env.to_s)
34
34
  end
35
-
35
+
36
36
  # Load secrets from the default config/secrets.yml file
37
37
  def load(env: Rails.env)
38
38
  secrets_path = Rails.root.join("config/secrets.yml")
39
39
  parse([secrets_path], env: env)
40
40
  end
41
-
41
+
42
42
  # Backward compatibility aliases (deprecated)
43
43
  alias_method :parse_default, :load
44
44
  alias_method :read, :load
@@ -49,8 +49,8 @@ end
49
49
  # Only for Rails 7.2+ where Rails::Secrets was removed
50
50
  if defined?(Rails) && Rails.respond_to?(:version)
51
51
  rails_version = Rails.version
52
- major, minor = rails_version.split('.').map(&:to_i)
53
-
52
+ major, minor = rails_version.split(".").map(&:to_i)
53
+
54
54
  # Only alias for Rails 7.2+ to avoid conflicts with native Rails::Secrets in 7.1
55
55
  if major > 7 || (major == 7 && minor >= 2)
56
56
  module Rails
@@ -9,16 +9,16 @@ module Secvault
9
9
  initializer "secvault.initialize", before: :load_environment_hook do |app|
10
10
  Secvault::Secrets.setup(app)
11
11
  end
12
-
12
+
13
13
  # Ensure initialization happens early in all environments
14
14
  config.before_configuration do |app|
15
15
  secrets_path = app.root.join("config/secrets.yml")
16
-
16
+
17
17
  if secrets_path.exist? && !Rails.application.respond_to?(:secrets)
18
18
  # Early initialization for test environment compatibility
19
- current_env = ENV['RAILS_ENV'] || 'development'
19
+ current_env = ENV["RAILS_ENV"] || "development"
20
20
  secrets = Secvault::Secrets.read_secrets(secrets_path, current_env)
21
-
21
+
22
22
  if secrets
23
23
  Rails.application.define_singleton_method(:secrets) do
24
24
  @secrets ||= begin
@@ -31,6 +31,5 @@ module Secvault
31
31
  end
32
32
  end
33
33
  end
34
-
35
34
  end
36
35
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/hash/keys"
4
+ require "active_support/core_ext/hash/deep_merge"
4
5
  require "active_support/ordered_options"
5
6
  require "pathname"
6
7
  require "erb"
@@ -12,16 +13,16 @@ module Secvault
12
13
  def setup(app)
13
14
  # Only auto-setup for Rails 7.2+ where secrets functionality was removed
14
15
  return unless rails_7_2_or_later?
15
-
16
+
16
17
  secrets_path = app.root.join("config/secrets.yml")
17
18
 
18
19
  if secrets_path.exist?
19
20
  # Use a more reliable approach that works in all environments
20
21
  app.config.before_configuration do
21
- current_env = ENV['RAILS_ENV'] || Rails.env || 'development'
22
+ current_env = ENV["RAILS_ENV"] || Rails.env || "development"
22
23
  setup_secrets_immediately(app, secrets_path, current_env)
23
24
  end
24
-
25
+
25
26
  # Also try during to_prepare as a fallback
26
27
  app.config.to_prepare do
27
28
  current_env = Rails.env
@@ -31,14 +32,14 @@ module Secvault
31
32
  end
32
33
  end
33
34
  end
34
-
35
+
35
36
  # Manual setup method for Rails 7.1 (opt-in)
36
37
  def setup_for_rails_71!(app)
37
38
  secrets_path = app.root.join("config/secrets.yml")
38
39
 
39
40
  if secrets_path.exist?
40
41
  app.config.before_configuration do
41
- current_env = ENV['RAILS_ENV'] || Rails.env || 'development'
42
+ current_env = ENV["RAILS_ENV"] || Rails.env || "development"
42
43
  setup_secrets_immediately(app, secrets_path, current_env)
43
44
  end
44
45
  end
@@ -60,7 +61,7 @@ module Secvault
60
61
  end
61
62
  end
62
63
  end
63
-
64
+
64
65
  # If secrets accessor already exists, merge the secrets
65
66
  if Rails.application.respond_to?(:secrets) && Rails.application.secrets.respond_to?(:merge!)
66
67
  Rails.application.secrets.merge!(secrets)
@@ -71,27 +72,23 @@ module Secvault
71
72
  # Classic Rails::Secrets.parse implementation
72
73
  # Parses plain YAML secrets files and merges shared + environment-specific sections
73
74
  def parse(paths, env:)
74
- paths.each_with_object(Hash.new) do |path, all_secrets|
75
+ paths.each_with_object({}) do |path, all_secrets|
75
76
  # Handle string paths by converting to Pathname
76
77
  path = Pathname.new(path) unless path.respond_to?(:exist?)
77
78
  next unless path.exist?
78
-
79
+
79
80
  # Read and process the plain YAML file content
80
81
  source = path.read
81
-
82
+
82
83
  # Process ERB and parse YAML
83
84
  erb_result = ERB.new(source).result
84
- secrets = if YAML.respond_to?(:unsafe_load)
85
- YAML.unsafe_load(erb_result)
86
- else
87
- YAML.load(erb_result)
88
- end
89
-
85
+ secrets = YAML.safe_load(erb_result, aliases: true, permitted_classes: [])
86
+
90
87
  secrets ||= {}
91
-
92
- # Merge shared secrets first, then environment-specific
93
- all_secrets.merge!(secrets["shared"].deep_symbolize_keys) if secrets["shared"]
94
- all_secrets.merge!(secrets[env].deep_symbolize_keys) if secrets[env]
88
+
89
+ # Merge shared secrets first, then environment-specific (using deep merge)
90
+ all_secrets.deep_merge!(secrets["shared"].deep_symbolize_keys) if secrets["shared"]
91
+ all_secrets.deep_merge!(secrets[env].deep_symbolize_keys) if secrets[env]
95
92
  end
96
93
  end
97
94
 
@@ -99,7 +96,7 @@ module Secvault
99
96
  if secrets_path.exist?
100
97
  # Handle plain YAML secrets.yml only
101
98
  all_secrets = YAML.safe_load(ERB.new(secrets_path.read).result, aliases: true)
102
-
99
+
103
100
  env_secrets = all_secrets[env.to_s]
104
101
  return env_secrets.deep_symbolize_keys if env_secrets
105
102
  end
@@ -108,10 +105,10 @@ module Secvault
108
105
  end
109
106
 
110
107
  private
111
-
108
+
112
109
  def rails_7_2_or_later?
113
110
  rails_version = Rails.version
114
- major, minor = rails_version.split('.').map(&:to_i)
111
+ major, minor = rails_version.split(".").map(&:to_i)
115
112
  major > 7 || (major == 7 && minor >= 2)
116
113
  end
117
114
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Secvault
4
- VERSION = "2.5.0"
4
+ VERSION = "2.7.0"
5
5
  end
data/lib/secvault.rb CHANGED
@@ -12,9 +12,9 @@ loader = Zeitwerk::Loader.for_gem
12
12
  loader.setup
13
13
 
14
14
  # Secvault - Simple secrets management for Rails
15
- #
16
- # Secvault restores the classic Rails secrets.yml functionality that was removed
17
- # in Rails 7.2, using simple, plain YAML files for environment-specific secrets
15
+ #
16
+ # Secvault restores the classic Rails secrets.yml functionality that was removed
17
+ # in Rails 7.2, using simple, plain YAML files for environment-specific secrets
18
18
  # management.
19
19
  #
20
20
  # ## Rails Version Support:
@@ -58,8 +58,21 @@ module Secvault
58
58
 
59
59
  extend self
60
60
 
61
- # Check if Secvault is currently active in the Rails application
61
+ # Internal storage for loaded secrets
62
+ @@loaded_secrets = nil
63
+
64
+ # Access to loaded secrets without Rails integration
65
+ def secrets
66
+ @@loaded_secrets || ActiveSupport::OrderedOptions.new
67
+ end
68
+
69
+ # Check if Secvault is currently active (started)
62
70
  def active?
71
+ @@loaded_secrets != nil
72
+ end
73
+
74
+ # Check if Secvault is integrated with Rails.application.secrets
75
+ def rails_integrated?
63
76
  defined?(Rails) && Rails::Secrets == Secvault::RailsSecrets
64
77
  end
65
78
 
@@ -69,7 +82,7 @@ module Secvault
69
82
  require "secvault/railtie"
70
83
  require "secvault/rails_secrets"
71
84
  end
72
-
85
+
73
86
  # Helper method to set up Secvault for older Rails versions
74
87
  # This provides an easy way to integrate Secvault into older Rails apps
75
88
  # that still have native Rails::Secrets functionality (like Rails 7.1).
@@ -87,24 +100,24 @@ module Secvault
87
100
  Rails.send(:remove_const, :Secrets)
88
101
  end
89
102
  Rails.const_set(:Secrets, Secvault::RailsSecrets)
90
-
103
+
91
104
  # Set up Rails.application.secrets replacement
92
105
  Rails.application.config.after_initialize do
93
106
  secrets_path = Rails.root.join("config/secrets.yml")
94
-
107
+
95
108
  if secrets_path.exist?
96
109
  # Load secrets using Secvault
97
110
  loaded_secrets = Rails::Secrets.parse([secrets_path], env: Rails.env)
98
-
111
+
99
112
  # Create ActiveSupport::OrderedOptions object for compatibility
100
113
  secrets_object = ActiveSupport::OrderedOptions.new
101
114
  secrets_object.merge!(loaded_secrets)
102
-
115
+
103
116
  # Replace Rails.application.secrets
104
117
  Rails.application.define_singleton_method(:secrets) do
105
118
  secrets_object
106
119
  end
107
-
120
+
108
121
  # Log integration success (except in production)
109
122
  unless Rails.env.production?
110
123
  Rails.logger&.info "[Secvault] Rails 7.1 integration complete. Loaded #{loaded_secrets.keys.size} secret keys."
@@ -114,14 +127,14 @@ module Secvault
114
127
  end
115
128
  end
116
129
  end
117
-
130
+
118
131
  # Set up multi-file secrets loading with a clean API
119
132
  # Just pass an array of file paths and Secvault handles the rest
120
133
  #
121
134
  # Usage in an initializer:
122
135
  # Secvault.setup_multi_file!([
123
136
  # 'config/secrets.yml',
124
- # 'config/secrets.oauth.yml',
137
+ # 'config/secrets.oauth.yml',
125
138
  # 'config/secrets.local.yml'
126
139
  # ])
127
140
  #
@@ -132,52 +145,84 @@ module Secvault
132
145
  def setup_multi_file!(files, reload_method: Rails.env.development?, logger: !Rails.env.production?)
133
146
  # Ensure Secvault integration is active
134
147
  setup_backward_compatibility_with_older_rails! unless active?
135
-
148
+
136
149
  # Convert strings to Pathname objects and resolve relative to Rails.root
137
150
  file_paths = Array(files).map do |file|
138
151
  file.is_a?(Pathname) ? file : Rails.root.join(file)
139
152
  end
140
-
153
+
141
154
  # Set up the multi-file loading
142
155
  Rails.application.config.after_initialize do
143
156
  load_multi_file_secrets!(file_paths, logger: logger)
144
157
  end
145
-
158
+
146
159
  # Add reload helper in development
147
160
  if reload_method
148
161
  add_reload_helper!(file_paths)
149
162
  end
150
163
  end
151
-
152
- # Load secrets from multiple files and merge them
164
+
165
+ # Load secrets into Secvault.secrets only (no Rails integration)
166
+ def load_secrets_only!(files, logger: !Rails.env.production?)
167
+ # Convert strings to Pathname objects and resolve relative to Rails.root
168
+ file_paths = Array(files).map do |file|
169
+ file.is_a?(Pathname) ? file : Rails.root.join(file)
170
+ end
171
+
172
+ existing_files = file_paths.select(&:exist?)
173
+
174
+ if existing_files.any?
175
+ # Load and merge all secrets files using Secvault's parser directly
176
+ merged_secrets = Secvault::Secrets.parse(existing_files, env: Rails.env)
177
+
178
+ # Store in Secvault.secrets (ActiveSupport::OrderedOptions for compatibility)
179
+ @@loaded_secrets = ActiveSupport::OrderedOptions.new
180
+ @@loaded_secrets.merge!(merged_secrets)
181
+
182
+ # Log successful loading
183
+ if logger
184
+ file_names = existing_files.map(&:basename)
185
+ Rails.logger&.info "[Secvault] Loaded #{existing_files.size} files: #{file_names.join(", ")}"
186
+ Rails.logger&.info "[Secvault] Parsed #{merged_secrets.keys.size} secret keys for #{Rails.env}"
187
+ end
188
+
189
+ true
190
+ else
191
+ Rails.logger&.warn "[Secvault] No secrets files found" if logger
192
+ @@loaded_secrets = ActiveSupport::OrderedOptions.new
193
+ false
194
+ end
195
+ end
196
+
197
+ # Load secrets from multiple files and merge them (with Rails integration)
153
198
  def load_multi_file_secrets!(file_paths, logger: !Rails.env.production?)
154
199
  existing_files = file_paths.select(&:exist?)
155
-
200
+
156
201
  if existing_files.any?
157
202
  # Load and merge all secrets files
158
203
  merged_secrets = Rails::Secrets.parse(existing_files, env: Rails.env)
159
-
204
+
160
205
  # Create ActiveSupport::OrderedOptions object for Rails compatibility
161
206
  secrets_object = ActiveSupport::OrderedOptions.new
162
207
  secrets_object.merge!(merged_secrets)
163
-
208
+
164
209
  # Replace Rails.application.secrets
165
210
  Rails.application.define_singleton_method(:secrets) { secrets_object }
166
-
211
+
167
212
  # Log successful loading
168
213
  if logger
169
214
  file_names = existing_files.map(&:basename)
170
- Rails.logger&.info "[Secvault Multi-File] Loaded #{existing_files.size} files: #{file_names.join(', ')}"
215
+ Rails.logger&.info "[Secvault Multi-File] Loaded #{existing_files.size} files: #{file_names.join(", ")}"
171
216
  Rails.logger&.info "[Secvault Multi-File] Merged #{merged_secrets.keys.size} secret keys for #{Rails.env}"
172
217
  end
173
-
218
+
174
219
  merged_secrets
175
220
  else
176
221
  Rails.logger&.warn "[Secvault Multi-File] No secrets files found" if logger
177
222
  {}
178
223
  end
179
224
  end
180
-
225
+
181
226
  # Add reload helper method for development
182
227
  def add_reload_helper!(file_paths)
183
228
  # Define reload method on Rails.application
@@ -186,13 +231,66 @@ module Secvault
186
231
  puts "🔄 Reloaded secrets from #{file_paths.size} files"
187
232
  true
188
233
  end
189
-
234
+
190
235
  # Also make it available as a top-level method
191
236
  Object.define_method(:reload_secrets!) do
192
237
  Rails.application.reload_secrets!
193
238
  end
194
239
  end
195
-
240
+
241
+ # Start Secvault and load secrets (without Rails integration)
242
+ #
243
+ # Usage:
244
+ # Secvault.start! # Uses config/secrets.yml only
245
+ # Secvault.start!(files: []) # Same as above
246
+ # Secvault.start!(files: ['path/to/secrets.yml']) # Custom single file
247
+ # Secvault.start!(files: ['gem.yml', 'app.yml']) # Multiple files
248
+ #
249
+ # Access loaded secrets via: Secvault.secrets.your_key
250
+ # To integrate with Rails.application.secrets, call: Secvault.integrate_with_rails!
251
+ #
252
+ # Options:
253
+ # - files: Array of file paths (String or Pathname). Defaults to ['config/secrets.yml']
254
+ # - logger: Enable logging (default: true except production)
255
+ def start!(files: [], logger: !Rails.env.production?)
256
+ # Default to host app's config/secrets.yml if no files specified
257
+ files_to_load = files.empty? ? ["config/secrets.yml"] : files
258
+
259
+ # Load secrets into Secvault.secrets (completely independent of Rails)
260
+ load_secrets_only!(files_to_load, logger: logger)
261
+
262
+ true
263
+ rescue => e
264
+ Rails.logger&.error "[Secvault] Failed to start: #{e.message}" if defined?(Rails)
265
+ false
266
+ end
267
+
268
+ # Integrate loaded secrets with Rails.application.secrets
269
+ def integrate_with_rails!
270
+ return false unless @@loaded_secrets
271
+
272
+ begin
273
+ # Set up Rails::Secrets to use Secvault's parser (only when integrating)
274
+ unless rails_integrated?
275
+ if defined?(Rails::Secrets)
276
+ Rails.send(:remove_const, :Secrets)
277
+ end
278
+ Rails.const_set(:Secrets, Secvault::RailsSecrets)
279
+ end
280
+
281
+ # Replace Rails.application.secrets with Secvault's loaded secrets
282
+ Rails.application.define_singleton_method(:secrets) do
283
+ Secvault.secrets
284
+ end
285
+
286
+ Rails.logger&.info "[Secvault] Integrated with Rails.application.secrets" unless Rails.env.production?
287
+ true
288
+ rescue => e
289
+ Rails.logger&.error "[Secvault] Failed to integrate with Rails: #{e.message}" if defined?(Rails)
290
+ false
291
+ end
292
+ end
293
+
196
294
  # Backward compatibility aliases
197
295
  alias_method :setup_rails_71_integration!, :setup_backward_compatibility_with_older_rails!
198
296
  alias_method :setup_multi_files!, :setup_multi_file! # Alternative name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secvault
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Unnikrishnan KP
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-22 00:00:00.000000000 Z
11
+ date: 2025-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -49,20 +49,14 @@ extra_rdoc_files: []
49
49
  files:
50
50
  - ".rspec"
51
51
  - ".standard.yml"
52
- - CHANGELOG.md
53
- - CODE_OF_CONDUCT.md
54
52
  - LICENSE.txt
55
53
  - README.md
56
54
  - Rakefile
57
55
  - lib/secvault.rb
58
- - lib/secvault/generators/secrets_generator.rb
59
56
  - lib/secvault/rails_secrets.rb
60
57
  - lib/secvault/railtie.rb
61
58
  - lib/secvault/secrets.rb
62
- - lib/secvault/secrets_helper.rb
63
59
  - lib/secvault/version.rb
64
- - secvault-2.0.0.gem
65
- - sig/secvault.rbs
66
60
  homepage: https://github.com/unnitallman/secvault
67
61
  licenses:
68
62
  - MIT
data/CHANGELOG.md DELETED
@@ -1,185 +0,0 @@
1
- ## [Unreleased]
2
-
3
- ## [2.3.0] - 2025-09-22
4
-
5
- ### Changed
6
-
7
- - **Better method naming**: Renamed `setup_rails_71_integration!` to `setup_backward_compatibility_with_older_rails!`
8
- - **More generic approach**: New method name works for any older Rails version, not just 7.1
9
- - **Updated documentation**: README now uses "Older Rails Integration" instead of "Rails 7.1 Integration"
10
- - **Clearer version support**: Documentation now shows "Rails 7.1 and older" for better clarity
11
-
12
- ### Backward Compatibility
13
-
14
- - ✅ **Old method name still works**: `setup_rails_71_integration!` is aliased to the new method
15
- - ✅ **No breaking changes**: All existing code continues to work
16
- - ✅ **Updated test apps**: Rails 7.1 test app uses the new, cleaner method name
17
-
18
- ### Benefits
19
-
20
- - **Future-proof naming**: Works for Rails 7.1, 7.0, 6.x, or any version with native secrets
21
- - **Clearer intent**: Method name clearly indicates it's for backward compatibility
22
- - **Better documentation**: More generic approach in README and code comments
23
- - **Maintained compatibility**: Existing users don't need to change anything
24
-
25
- ## [2.2.0] - 2025-09-22
26
-
27
- ### Added
28
-
29
- - **New simplified API**: `Rails::Secrets.load()` - cleaner method to load default config/secrets.yml
30
- - **Enhanced README** with comprehensive examples for multiple files usage
31
- - **Better documentation** showing how to parse custom files and multiple file merging
32
- - **Backward compatibility aliases** - `parse_default` and `read` still work
33
-
34
- ### Changed
35
-
36
- - **Improved method naming**: `Rails::Secrets.load()` is now the preferred method over `parse_default()`
37
- - **Enhanced documentation** in code with clear examples for single file, multiple files, and custom paths
38
- - **Better README examples** showing advanced usage patterns
39
-
40
- ### Examples Added
41
-
42
- - Multiple secrets files merging: `Rails::Secrets.parse(['secrets.yml', 'secrets.local.yml'], env: Rails.env)`
43
- - Environment-specific loading: `Rails::Secrets.load(env: 'production')`
44
- - Custom file parsing: `Rails::Secrets.parse(['config/custom.yml'], env: Rails.env)`
45
- - Multiple path support: `Rails::Secrets.parse([Rails.root.join('config', 'secrets.yml')], env: Rails.env)`
46
-
47
- ### Backward Compatibility
48
-
49
- - ✅ All existing methods still work
50
- - ✅ `parse_default` → `load` (alias maintained)
51
- - ✅ `read` → `load` (alias maintained)
52
- - ✅ No breaking changes
53
-
54
- ## [2.1.0] - 2025-09-22
55
-
56
- ### Removed
57
-
58
- - **Removed all rake tasks** - Ultimate simplicity! No more `rake secvault:setup`, `rake secvault:edit`, or `rake secvault:show`
59
- - Removed `lib/secvault/tasks.rake` file entirely
60
- - Removed rake task loading from railtie
61
-
62
- ### Changed
63
-
64
- - **Ultra-simple setup**: Just create `config/secrets.yml` with any text editor
65
- - Updated README to reflect manual file creation instead of rake tasks
66
- - Updated module documentation to show simple 3-step process
67
- - Cleaner railtie without task loading complexity
68
-
69
- ### Benefits
70
-
71
- - **Zero dependencies on rake tasks** - works with just plain YAML files
72
- - **Even simpler** - no commands to remember, just edit YAML files
73
- - **More intuitive** - developers already know how to create and edit YAML files
74
- - **Less code** - removed unnecessary complexity
75
-
76
- ### Tested
77
-
78
- - ✅ Rails 7.1 integration works perfectly
79
- - ✅ Rails 8.0 automatic setup works perfectly
80
- - ✅ No rake task conflicts or errors
81
-
82
- ## [2.0.0] - 2025-09-22
83
-
84
- ### BREAKING CHANGES
85
-
86
- - **Removed all encryption functionality** - Secvault now focuses purely on plain YAML secrets management
87
- - Removed ActiveSupport::EncryptedFile dependencies
88
- - Removed MissingKeyError and InvalidKeyError exceptions
89
- - Removed `encrypted?`, `decrypt`, `decrypt_secrets` methods
90
- - Simplified rake tasks to work with plain YAML only
91
-
92
- ### Added
93
-
94
- - Simplified `rake secvault:setup` that creates plain YAML files with helpful comments
95
- - Better error messages and user guidance in rake tasks
96
- - Cleaner, more focused codebase without encryption complexity
97
-
98
- ### Changed
99
-
100
- - **Major simplification**: All secrets are now stored in plain YAML files
101
- - Updated README to reflect plain YAML approach
102
- - Updated module documentation and gemspec descriptions
103
- - Rake tasks now use emojis and better user experience
104
- - Production secrets should use ERB syntax with environment variables
105
-
106
- ### Benefits
107
-
108
- - Much simpler gem with single focus: plain YAML secrets management
109
- - No encryption keys to manage or lose
110
- - Easy to understand, edit, and debug secrets files
111
- - Perfect for development and test environments
112
- - Production secrets via environment variables (recommended best practice)
113
-
114
- ## [1.0.4] - 2025-09-22
115
-
116
- ### Added
117
-
118
- - Comprehensive Rails 7.1 integration support
119
- - New `Secvault.setup_rails_71_integration!` helper method for easy Rails 7.1 setup
120
- - Enhanced documentation with Rails 7.1 integration guide
121
- - Module-level documentation with usage examples and version compatibility
122
-
123
- ### Improved
124
-
125
- - Better Rails 7.1 compatibility with automatic detection and setup
126
- - Enhanced README with Rails 7.1 integration section
127
- - Improved error handling and logging for Rails 7.1 integration
128
- - More comprehensive inline documentation
129
-
130
- ### Changed
131
-
132
- - Refined automatic setup logic to avoid conflicts with Rails 7.1 native functionality
133
- - Updated gemspec description to include Rails 7.1+ support
134
-
135
- ## [1.0.3] - 2025-09-22
136
-
137
- ### Fixed
138
-
139
- - Rails 7.1 compatibility issues with native Rails::Secrets conflicts
140
- - String path handling in parse method
141
- - Zeitwerk constant name mismatch resolution
142
-
143
- ### Added
144
-
145
- - Manual setup method for Rails 7.1 (opt-in)
146
- - Rails version detection for automatic setup decisions
147
- - Only create Rails::Secrets alias for Rails 7.2+ to avoid conflicts
148
-
149
- ## [1.0.2] - 2025-09-22
150
-
151
- ### Changed
152
-
153
- - Updated Rails dependency from >= 7.2.0 to >= 7.1.0 for broader compatibility
154
- - Updated gem description to include Rails 7.1+ support
155
-
156
- ## [1.0.1] - 2025-09-22
157
-
158
- ### Fixed
159
-
160
- - Zeitwerk constant name mismatch in rails_secrets.rb
161
- - Changed module definition from Rails::Secrets to Secvault::RailsSecrets
162
- - Added Rails::Secrets alias for backward compatibility
163
- - Resolved Zeitwerk::NameError when loading Rails applications
164
-
165
- ## [1.0.0] - 2025-09-22
166
-
167
- ### Added
168
-
169
- - Initial release of Secvault gem
170
- - Rails secrets.yml functionality for Rails 7.2+
171
- - Encrypted secrets.yml support using Rails' built-in encryption
172
- - Environment-specific secrets management
173
- - ERB template support in secrets files
174
- - Rake tasks for secrets management:
175
- - `rake secvault:setup` - Create encrypted secrets file
176
- - `rake secvault:edit` - Edit encrypted secrets
177
- - `rake secvault:show` - Display decrypted secrets
178
- - Rails generator for creating secrets files
179
- - Automatic integration with Rails.application.secrets
180
- - Support for both encrypted and plain YAML secrets files
181
- - Key management with config/secrets.yml.key
182
- - Environment variable fallback for encryption key
183
- - Comprehensive error handling for missing/invalid keys
184
- - Full test coverage with RSpec
185
- - Detailed documentation and usage examples
data/CODE_OF_CONDUCT.md DELETED
@@ -1,132 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- We as members, contributors, and leaders pledge to make participation in our
6
- community a harassment-free experience for everyone, regardless of age, body
7
- size, visible or invisible disability, ethnicity, sex characteristics, gender
8
- identity and expression, level of experience, education, socio-economic status,
9
- nationality, personal appearance, race, caste, color, religion, or sexual
10
- identity and orientation.
11
-
12
- We pledge to act and interact in ways that contribute to an open, welcoming,
13
- diverse, inclusive, and healthy community.
14
-
15
- ## Our Standards
16
-
17
- Examples of behavior that contributes to a positive environment for our
18
- community include:
19
-
20
- * Demonstrating empathy and kindness toward other people
21
- * Being respectful of differing opinions, viewpoints, and experiences
22
- * Giving and gracefully accepting constructive feedback
23
- * Accepting responsibility and apologizing to those affected by our mistakes,
24
- and learning from the experience
25
- * Focusing on what is best not just for us as individuals, but for the overall
26
- community
27
-
28
- Examples of unacceptable behavior include:
29
-
30
- * The use of sexualized language or imagery, and sexual attention or advances of
31
- any kind
32
- * Trolling, insulting or derogatory comments, and personal or political attacks
33
- * Public or private harassment
34
- * Publishing others' private information, such as a physical or email address,
35
- without their explicit permission
36
- * Other conduct which could reasonably be considered inappropriate in a
37
- professional setting
38
-
39
- ## Enforcement Responsibilities
40
-
41
- Community leaders are responsible for clarifying and enforcing our standards of
42
- acceptable behavior and will take appropriate and fair corrective action in
43
- response to any behavior that they deem inappropriate, threatening, offensive,
44
- or harmful.
45
-
46
- Community leaders have the right and responsibility to remove, edit, or reject
47
- comments, commits, code, wiki edits, issues, and other contributions that are
48
- not aligned to this Code of Conduct, and will communicate reasons for moderation
49
- decisions when appropriate.
50
-
51
- ## Scope
52
-
53
- This Code of Conduct applies within all community spaces, and also applies when
54
- an individual is officially representing the community in public spaces.
55
- Examples of representing our community include using an official email address,
56
- posting via an official social media account, or acting as an appointed
57
- representative at an online or offline event.
58
-
59
- ## Enforcement
60
-
61
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
- reported to the community leaders responsible for enforcement at
63
- [INSERT CONTACT METHOD].
64
- All complaints will be reviewed and investigated promptly and fairly.
65
-
66
- All community leaders are obligated to respect the privacy and security of the
67
- reporter of any incident.
68
-
69
- ## Enforcement Guidelines
70
-
71
- Community leaders will follow these Community Impact Guidelines in determining
72
- the consequences for any action they deem in violation of this Code of Conduct:
73
-
74
- ### 1. Correction
75
-
76
- **Community Impact**: Use of inappropriate language or other behavior deemed
77
- unprofessional or unwelcome in the community.
78
-
79
- **Consequence**: A private, written warning from community leaders, providing
80
- clarity around the nature of the violation and an explanation of why the
81
- behavior was inappropriate. A public apology may be requested.
82
-
83
- ### 2. Warning
84
-
85
- **Community Impact**: A violation through a single incident or series of
86
- actions.
87
-
88
- **Consequence**: A warning with consequences for continued behavior. No
89
- interaction with the people involved, including unsolicited interaction with
90
- those enforcing the Code of Conduct, for a specified period of time. This
91
- includes avoiding interactions in community spaces as well as external channels
92
- like social media. Violating these terms may lead to a temporary or permanent
93
- ban.
94
-
95
- ### 3. Temporary Ban
96
-
97
- **Community Impact**: A serious violation of community standards, including
98
- sustained inappropriate behavior.
99
-
100
- **Consequence**: A temporary ban from any sort of interaction or public
101
- communication with the community for a specified period of time. No public or
102
- private interaction with the people involved, including unsolicited interaction
103
- with those enforcing the Code of Conduct, is allowed during this period.
104
- Violating these terms may lead to a permanent ban.
105
-
106
- ### 4. Permanent Ban
107
-
108
- **Community Impact**: Demonstrating a pattern of violation of community
109
- standards, including sustained inappropriate behavior, harassment of an
110
- individual, or aggression toward or disparagement of classes of individuals.
111
-
112
- **Consequence**: A permanent ban from any sort of public interaction within the
113
- community.
114
-
115
- ## Attribution
116
-
117
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
- version 2.1, available at
119
- [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
-
121
- Community Impact Guidelines were inspired by
122
- [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
-
124
- For answers to common questions about this code of conduct, see the FAQ at
125
- [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
- [https://www.contributor-covenant.org/translations][translations].
127
-
128
- [homepage]: https://www.contributor-covenant.org
129
- [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
- [Mozilla CoC]: https://github.com/mozilla/diversity
131
- [FAQ]: https://www.contributor-covenant.org/faq
132
- [translations]: https://www.contributor-covenant.org/translations
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/base"
4
- require "active_support/encrypted_file"
5
- require "securerandom"
6
-
7
- module Secvault
8
- module Generators
9
- class SecretsGenerator < Rails::Generators::Base
10
- source_root File.expand_path("templates", __dir__)
11
-
12
- desc "Creates a secrets.yml file for secrets management"
13
-
14
- class_option :force, type: :boolean, default: false, desc: "Overwrite existing secrets.yml"
15
- class_option :encrypted, type: :boolean, default: false, desc: "Create encrypted secrets.yml (default: plain YAML)"
16
-
17
- def create_secrets_file
18
- secrets_path = Rails.root.join("config/secrets.yml")
19
- key_path = Rails.root.join("config/secrets.yml.key")
20
-
21
- if secrets_path.exist? && !options[:force]
22
- say "Secrets file already exists at config/secrets.yml", :yellow
23
- return
24
- end
25
-
26
- default_content = generate_default_secrets
27
-
28
- if options[:encrypted]
29
- # Create encrypted secrets file
30
- unless key_path.exist?
31
- key = ActiveSupport::EncryptedFile.generate_key
32
- File.write(key_path, key)
33
- say "Generated encryption key in config/secrets.yml.key", :green
34
- end
35
-
36
- encrypted_file = ActiveSupport::EncryptedFile.new(
37
- content_path: secrets_path,
38
- key_path: key_path,
39
- env_key: "RAILS_SECRETS_KEY",
40
- raise_if_missing_key: true
41
- )
42
-
43
- encrypted_file.write(default_content)
44
- say "Created encrypted secrets.yml file", :green
45
- say "Add config/secrets.yml.key to your .gitignore file", :yellow
46
- else
47
- # Create plain YAML secrets file
48
- File.write(secrets_path, default_content)
49
- say "Created plain secrets.yml file", :green
50
- say "Remember to add config/secrets.yml to your .gitignore if it contains sensitive data", :yellow
51
- end
52
- end
53
-
54
- def add_to_gitignore
55
- gitignore_path = Rails.root.join(".gitignore")
56
- key_entry = "/config/secrets.yml.key"
57
-
58
- if gitignore_path.exist?
59
- gitignore_content = File.read(gitignore_path)
60
- unless gitignore_content.include?(key_entry)
61
- File.open(gitignore_path, "a") do |f|
62
- f.puts "\n# Ignore encrypted secrets key"
63
- f.puts key_entry
64
- end
65
- say "Added secrets key to .gitignore", :green
66
- end
67
- end
68
- end
69
-
70
- private
71
-
72
- def generate_default_secrets
73
- <<~YAML
74
- # Be sure to restart your server when you modify this file.
75
-
76
- # Your secret key is used for verifying the integrity of signed cookies.
77
- # If you change this key, all old signed cookies will become invalid!
78
-
79
- # Make sure the secret is at least 30 characters and all random,
80
- # no regular words or you'll be exposed to dictionary attacks.
81
- # You can use `rails secret` to generate a secure secret key.
82
-
83
- # Make sure the secrets in this file are kept private
84
- # if you're sharing your code publicly.
85
-
86
- development:
87
- secret_key_base: #{SecureRandom.hex(64)}
88
-
89
- test:
90
- secret_key_base: #{SecureRandom.hex(64)}
91
-
92
- # Do not keep production secrets in the repository,
93
- # instead read values from the environment.
94
- production:
95
- secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
96
- YAML
97
- end
98
- end
99
- end
100
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Secvault
4
- class SecretsHelper
5
- def initialize(app)
6
- @app = app
7
- @secrets_path = app.root.join("config/secrets.yml")
8
- @key_path = app.root.join("config/secrets.yml.key")
9
- end
10
-
11
- def secrets
12
- @secrets ||= load_secrets
13
- end
14
-
15
- def [](key)
16
- secrets[key.to_sym]
17
- end
18
-
19
- def fetch(key, default = nil)
20
- secrets.fetch(key.to_sym, default)
21
- end
22
-
23
- def key?(key)
24
- secrets.key?(key.to_sym)
25
- end
26
-
27
- def empty?
28
- secrets.empty?
29
- end
30
-
31
- def to_h
32
- secrets.dup
33
- end
34
-
35
- private
36
-
37
- def load_secrets
38
- return {} unless @secrets_path.exist?
39
-
40
- env_secrets = Secvault::Secrets.read_secrets(@secrets_path, @key_path, Rails.env)
41
- env_secrets || {}
42
- end
43
- end
44
- end
data/secvault-2.0.0.gem DELETED
Binary file
data/sig/secvault.rbs DELETED
@@ -1,4 +0,0 @@
1
- module Secvault
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end