secvault 2.3.0 → 2.4.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: 441940b63b8d897f1ad3b84bf43168d20dcbf62017a604e201538cee0315a7ca
4
- data.tar.gz: fdd75a75105b0c34efb26096499ec6ffeac7340a170d4f8fcb7188c3f0d4e3db
3
+ metadata.gz: 18d7c81d380aa63a8092f4bd91a438ee3e02282695b6fcbe6841ffbb81a30a9b
4
+ data.tar.gz: 2dbe018b171e0840e9a6047027fcf8e60ef73ec60867e4f6f4f97240df74f126
5
5
  SHA512:
6
- metadata.gz: 14fc56f53ff8729262cb5fa07bf2de96e908d7c4f6b00a1134ea2c86b3a433b220a24b3399ad43e97846cadd0bc79546780a4e0fce5318448497b62d5fba0714
7
- data.tar.gz: 3e4c8387fa38263e3bf99436211b3eaadf6b3d7d2aa5ec483cc6b19fc9dcbcb9bd402b9099e800fcc8c6fb9fc09b8281875415fdd90570fbee6625d324706032
6
+ metadata.gz: c864336bbb71f184bf09e9f3bc0c191cbd7f7d750ee5a9c541cc3711b0ddc0cc608103e574dffd940b64dc814b4d5b5f433940ef0adf6235e3d17caf9f5784ce
7
+ data.tar.gz: 6c62bb91d5a9a0ca1ac0a984f94c92d11c9815d8832e371b7b362d2d6142e1a5f6ea5b058ce8d7762708c271c4cfe848b753d8ea2c6c1dbf47ace950c6df16fd
data/README.md CHANGED
@@ -1,12 +1,22 @@
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.
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.
4
4
 
5
5
  **Rails Version Support:**
6
6
  - **Rails 7.1 and older**: Manual setup (see Older Rails Integration below)
7
7
  - **Rails 7.2+**: Automatic setup
8
8
  - **Rails 8.0+**: Full compatibility
9
9
 
10
+ ## ✨ Key Features
11
+
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
19
+
10
20
  ## Installation
11
21
 
12
22
  ```ruby
@@ -34,32 +44,91 @@ Rails.application.secrets.api_key
34
44
  Rails.application.secrets.database_password
35
45
  ```
36
46
 
37
- **Example secrets.yml:**
47
+ **Example secrets.yml with YAML defaults and ERB:**
38
48
  ```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
+
39
60
  development:
40
- api_key: dev_key
41
- database_password: dev_password
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
42
68
 
43
69
  production:
70
+ <<: *default # Inherit defaults
44
71
  api_key: <%= ENV['API_KEY'] %>
45
- database_password: <%= ENV['DATABASE_PASSWORD'] %>
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(',') %>
46
85
  ```
47
86
 
48
- **Production:** Use environment variables in your YAML:
49
- ```yaml
50
- production:
51
- api_key: <%= ENV['API_KEY'] %>
87
+ ## Multi-File Configuration
88
+
89
+ Organize secrets across multiple files for better maintainability:
90
+
91
+ ```ruby
92
+ # config/initializers/secvault.rb
93
+ require "secvault"
94
+ Secvault.setup_backward_compatibility_with_older_rails!
95
+
96
+ Rails.application.config.after_initialize do
97
+ # Load multiple files in order (later files override earlier ones)
98
+ secrets_files = [
99
+ Rails.root.join('config', 'secrets.yml'), # Base secrets
100
+ Rails.root.join('config', 'secrets.oauth.yml'), # OAuth & APIs
101
+ Rails.root.join('config', 'secrets.local.yml') # Local overrides
102
+ ]
103
+
104
+ existing_files = secrets_files.select(&:exist?)
105
+
106
+ if existing_files.any?
107
+ merged_secrets = Rails::Secrets.parse(existing_files, env: Rails.env)
108
+ secrets_object = ActiveSupport::OrderedOptions.new
109
+ secrets_object.merge!(merged_secrets)
110
+ Rails.application.define_singleton_method(:secrets) { secrets_object }
111
+ end
112
+ end
113
+ ```
114
+
115
+ **File organization example:**
116
+ ```
117
+ config/
118
+ ├── secrets.yml # Base application secrets
119
+ ├── secrets.oauth.yml # OAuth providers & external APIs
120
+ ├── secrets.local.yml # Local development overrides (gitignored)
52
121
  ```
53
122
 
54
123
  ## Advanced Usage
55
124
 
56
- **Multiple secrets files (merged in order):**
125
+ **Manual multi-file parsing:**
57
126
  ```ruby
58
127
  # Parse multiple files - later files override earlier ones
59
128
  secrets = Rails::Secrets.parse([
60
129
  'config/secrets.yml',
61
- 'config/secrets.local.yml',
62
- 'config/secrets.production.yml'
130
+ 'config/secrets.oauth.yml',
131
+ 'config/secrets.local.yml'
63
132
  ], env: Rails.env)
64
133
  ```
65
134
 
@@ -72,16 +141,49 @@ production_secrets = Rails::Secrets.load(env: 'production')
72
141
  dev_secrets = Rails::Secrets.load(env: 'development')
73
142
  ```
74
143
 
75
- **Custom files:**
144
+ **Environment-specific loading:**
76
145
  ```ruby
77
- # Parse a custom secrets file
78
- custom_secrets = Rails::Secrets.parse(['config/custom.yml'], env: Rails.env)
146
+ # Load production secrets in any environment
147
+ production_secrets = Rails::Secrets.load(env: 'production')
79
148
 
80
- # Parse from different paths
81
- all_secrets = Rails::Secrets.parse([
82
- Rails.root.join('config', 'secrets.yml'),
83
- Rails.root.join('config', 'deploy', 'secrets.yml')
84
- ], env: Rails.env)
149
+ # Load development secrets
150
+ dev_secrets = Rails::Secrets.load(env: 'development')
151
+ ```
152
+
153
+ ## ERB Features & Type Conversion
154
+
155
+ Secvault supports powerful ERB templating with automatic type conversion:
156
+
157
+ ```yaml
158
+ production:
159
+ # String interpolation
160
+ api_key: <%= ENV['API_KEY'] %>
161
+
162
+ # Integer conversion
163
+ database_pool: <%= ENV.fetch('DB_POOL', '10').to_i %>
164
+
165
+ # Boolean conversion
166
+ debug_enabled: <%= ENV.fetch('DEBUG', 'false') == 'true' %>
167
+
168
+ # Array conversion
169
+ allowed_hosts: <%= ENV.fetch('HOSTS', 'localhost,127.0.0.1').split(',') %>
170
+
171
+ # Fallback values
172
+ timeout: <%= ENV.fetch('TIMEOUT', '30').to_i %>
173
+ adapter: <%= ENV.fetch('DB_ADAPTER', 'postgresql') %>
174
+ ```
175
+
176
+ ## Development Tools
177
+
178
+ **Hot-reload secrets (development only):**
179
+ ```ruby
180
+ # In Rails console or code
181
+ reload_secrets! # Reloads all secrets files without server restart
182
+ ```
183
+
184
+ **Check integration status:**
185
+ ```ruby
186
+ Secvault.active? # Returns true if Secvault is managing secrets
85
187
  ```
86
188
 
87
189
  ## Older Rails Integration
@@ -102,12 +204,68 @@ Rails::Secrets.load # ✅ Load default config/secrets.yml
102
204
  Rails::Secrets.parse(['custom.yml'], env: Rails.env) # ✅ Parse custom files
103
205
  ```
104
206
 
207
+ **Check if Secvault is active:**
208
+ ```ruby
209
+ if Secvault.active?
210
+ puts "Using Secvault for secrets management"
211
+ else
212
+ puts "Using default Rails secrets functionality"
213
+ end
214
+ ```
105
215
 
106
- ## Security
216
+ ## Usage Examples
217
+
218
+ **Basic usage:**
219
+ ```ruby
220
+ # Access secrets
221
+ Rails.application.secrets.api_key
222
+ Rails.application.secrets.database.host
223
+ Rails.application.secrets.oauth.google.client_id
224
+
225
+ # With YAML defaults, you get deep merging:
226
+ Rails.application.secrets.database.adapter # "postgresql" (from default)
227
+ Rails.application.secrets.database.host # "localhost" (from environment)
228
+ ```
107
229
 
108
- ⚠️ Never commit production secrets to version control
109
- ✅ Use environment variables for production secrets with ERB syntax: `<%= ENV['SECRET'] %>`
110
- Add `config/secrets.yml` to `.gitignore` if it contains sensitive data
230
+ **Multi-file merging:**
231
+ ```ruby
232
+ # Files loaded in order: base oauth local
233
+ # Later files override earlier ones for the same keys
234
+ # Hash values are deep merged, scalars are replaced
235
+
236
+ Rails.application.secrets.api_key # Could be from base or local file
237
+ Rails.application.secrets.oauth.google # From oauth file
238
+ Rails.application.secrets.features.debug # From local file override
239
+ ```
240
+
241
+ ## Security Best Practices
242
+
243
+ ### ⚠️ Production Security
244
+ - **Never commit production secrets** to version control
245
+ - **Use environment variables** in production with ERB: `<%= ENV['SECRET'] %>`
246
+ - **Use ENV.fetch()** with fallbacks: `<%= ENV.fetch('SECRET', 'default') %>`
247
+
248
+ ### 📝 File Management
249
+ - **Add sensitive files** to `.gitignore`:
250
+ ```gitignore
251
+ config/secrets.yml # If contains sensitive data
252
+ config/secrets.local.yml # Local development overrides
253
+ config/secrets.production.yml # If used
254
+ ```
255
+
256
+ ### 🔑 Recommended Structure
257
+ ```yaml
258
+ # ✅ GOOD: Base file with safe defaults
259
+ development:
260
+ api_key: "safe_dev_key_for_team"
261
+
262
+ production:
263
+ api_key: <%= ENV['API_KEY'] %> # ✅ From environment
264
+
265
+ # ❌ BAD: Secrets hardcoded in base file
266
+ production:
267
+ api_key: "super_secret_production_key" # ❌ Never do this
268
+ ```
111
269
 
112
270
  ## License
113
271
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Secvault
4
- VERSION = "2.3.0"
4
+ VERSION = "2.4.0"
5
5
  end
data/lib/secvault.rb CHANGED
@@ -58,6 +58,11 @@ module Secvault
58
58
 
59
59
  extend self
60
60
 
61
+ # Check if Secvault is currently active in the Rails application
62
+ def active?
63
+ defined?(Rails) && Rails::Secrets == Secvault::RailsSecrets
64
+ end
65
+
61
66
  def install!
62
67
  return if defined?(Rails::Railtie).nil?
63
68
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secvault
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Unnikrishnan KP