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 +4 -4
- data/README.md +182 -24
- data/lib/secvault/version.rb +1 -1
- data/lib/secvault.rb +5 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18d7c81d380aa63a8092f4bd91a438ee3e02282695b6fcbe6841ffbb81a30a9b
|
4
|
+
data.tar.gz: 2dbe018b171e0840e9a6047027fcf8e60ef73ec60867e4f6f4f97240df74f126
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
41
|
-
|
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
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
**
|
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.
|
62
|
-
'config/secrets.
|
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
|
-
**
|
144
|
+
**Environment-specific loading:**
|
76
145
|
```ruby
|
77
|
-
#
|
78
|
-
|
146
|
+
# Load production secrets in any environment
|
147
|
+
production_secrets = Rails::Secrets.load(env: 'production')
|
79
148
|
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
##
|
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
|
-
|
109
|
-
|
110
|
-
|
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
|
|
data/lib/secvault/version.rb
CHANGED
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
|
|