secvault 2.6.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 +4 -4
- data/.rspec +1 -1
- data/README.md +45 -159
- data/lib/secvault/rails_secrets.rb +8 -8
- data/lib/secvault/railtie.rb +4 -5
- data/lib/secvault/secrets.rb +15 -19
- data/lib/secvault/version.rb +1 -1
- data/lib/secvault.rb +50 -52
- metadata +1 -8
- data/CHANGELOG.md +0 -185
- data/CODE_OF_CONDUCT.md +0 -132
- data/USAGE_EXAMPLES.md +0 -65
- data/lib/secvault/generators/secrets_generator.rb +0 -100
- data/lib/secvault/secrets_helper.rb +0 -44
- data/secvault-2.0.0.gem +0 -0
- data/sig/secvault.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51dbcfd2c3b3073fb06223b681fb358cf8c74aae00c90663470edc19b3a40cd0
|
4
|
+
data.tar.gz: f78b9e5a1bdcb9148d58e31791738179b38a401ae0416920b4a6ee557e024ffd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99d55935f3754ed807d306e94c530259ae34c82d43e1b2827ace62a2e33fd8bed291d8af358597aa68b71d78737af402273644e2b5d9475c5540be234b2d5985
|
7
|
+
data.tar.gz: d24dfa1e4613602a15ee7d40aeabedb089edf9e88ea136960ca039d6298252d8e7cd4e8a50d6f815cedcbde9d6192320814ccf6694797633225a29e98b993842
|
data/.rspec
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# Secvault
|
2
2
|
|
3
|
-
Restores
|
3
|
+
Restores Rails `secrets.yml` functionality for environment-specific secrets management using YAML files with ERB templating.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
- **Rails 7.2+**: Automatic setup
|
5
|
+
## Rails Version Support
|
6
|
+
|
7
|
+
- **Rails 7.2+**: Automatic setup (drop-in replacement for removed functionality)
|
8
|
+
- **Rails 7.1**: Manual setup required
|
8
9
|
- **Rails 8.0+**: Full compatibility
|
9
10
|
|
10
11
|
## Installation
|
@@ -14,202 +15,87 @@ Restores the classic Rails `secrets.yml` functionality that was removed in Rails
|
|
14
15
|
gem 'secvault'
|
15
16
|
```
|
16
17
|
|
17
|
-
|
18
|
-
bundle install
|
19
|
-
```
|
20
|
-
|
21
|
-
## Quick Start (Rails 7.2+)
|
22
|
-
|
23
|
-
```bash
|
24
|
-
# 1. Create secrets.yml
|
25
|
-
touch config/secrets.yml
|
18
|
+
## Quick Start
|
26
19
|
|
27
|
-
|
28
|
-
$EDITOR config/secrets.yml
|
29
|
-
```
|
30
|
-
|
31
|
-
**Usage in your app:**
|
32
|
-
```ruby
|
33
|
-
Rails.application.secrets.api_key
|
34
|
-
Rails.application.secrets.database_password
|
35
|
-
```
|
20
|
+
Create `config/secrets.yml`:
|
36
21
|
|
37
|
-
**Example secrets.yml with YAML defaults and ERB:**
|
38
22
|
```yaml
|
39
|
-
# YAML defaults - inherited by all environments
|
40
|
-
default: &default
|
41
|
-
app_name: "My Application"
|
42
|
-
database:
|
43
|
-
adapter: "postgresql"
|
44
|
-
pool: 5
|
45
|
-
timeout: 5000
|
46
|
-
api:
|
47
|
-
timeout: 30
|
48
|
-
retries: 3
|
49
|
-
|
50
23
|
development:
|
51
|
-
|
52
|
-
|
53
|
-
database:
|
54
|
-
host: "localhost"
|
55
|
-
name: "myapp_development"
|
56
|
-
api:
|
57
|
-
base_url: "http://localhost:3000" # Override default
|
24
|
+
api_key: "dev_key_123"
|
25
|
+
database_url: "postgresql://localhost/myapp_dev"
|
58
26
|
|
59
27
|
production:
|
60
|
-
<<: *default # Inherit defaults
|
61
28
|
api_key: <%= ENV['API_KEY'] %>
|
62
|
-
|
63
|
-
host: <%= ENV['DATABASE_HOST'] %>
|
64
|
-
name: <%= ENV['DATABASE_NAME'] %>
|
65
|
-
pool: <%= ENV.fetch('DATABASE_POOL', '10').to_i %> # Type conversion
|
66
|
-
api:
|
67
|
-
base_url: <%= ENV['API_BASE_URL'] %>
|
68
|
-
|
69
|
-
# Boolean conversion
|
70
|
-
features:
|
71
|
-
new_ui: <%= ENV.fetch('FEATURE_NEW_UI', 'true') == 'true' %>
|
72
|
-
|
73
|
-
# Array conversion
|
74
|
-
oauth_scopes: <%= ENV.fetch('OAUTH_SCOPES', 'email,profile').split(',') %>
|
29
|
+
database_url: <%= ENV['DATABASE_URL'] %>
|
75
30
|
```
|
76
31
|
|
77
|
-
|
78
|
-
|
79
|
-
Organize secrets across multiple files with a **super clean API**:
|
32
|
+
Access secrets in your app:
|
80
33
|
|
81
34
|
```ruby
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
# That's it! Just pass your files array
|
86
|
-
Secvault.setup_multi_file!([
|
87
|
-
'config/secrets.yml', # Base secrets
|
88
|
-
'config/secrets.oauth.yml', # OAuth & APIs
|
89
|
-
'config/secrets.local.yml' # Local overrides
|
90
|
-
])
|
35
|
+
Rails.application.secrets.api_key
|
36
|
+
Rails.application.secrets.database_url
|
91
37
|
```
|
92
38
|
|
93
|
-
|
94
|
-
- ✅ Loads and merges all files in order (later files override earlier ones)
|
95
|
-
- ✅ Handles missing files gracefully
|
96
|
-
- ✅ Creates Rails.application.secrets with merged configuration
|
97
|
-
|
98
|
-
**Advanced options:**
|
99
|
-
```ruby
|
100
|
-
# Disable reload helper or logging
|
101
|
-
Secvault.setup_multi_file!(files, reload_method: false, logger: false)
|
102
|
-
|
103
|
-
# Use Pathname objects if needed
|
104
|
-
Secvault.setup_multi_file!([
|
105
|
-
Rails.root.join('config', 'secrets.yml'),
|
106
|
-
Rails.root.join('config', 'secrets.oauth.yml')
|
107
|
-
])
|
108
|
-
```
|
39
|
+
## Multi-File Configuration
|
109
40
|
|
110
|
-
|
41
|
+
Load and merge multiple secrets files:
|
111
42
|
|
112
|
-
**Manual multi-file parsing:**
|
113
43
|
```ruby
|
114
|
-
#
|
115
|
-
|
44
|
+
# config/initializers/secvault.rb
|
45
|
+
Secvault.setup_multi_file!([
|
116
46
|
'config/secrets.yml',
|
117
47
|
'config/secrets.oauth.yml',
|
118
48
|
'config/secrets.local.yml'
|
119
|
-
]
|
49
|
+
])
|
120
50
|
```
|
121
51
|
|
122
|
-
|
123
|
-
```ruby
|
124
|
-
# Load production secrets in any environment
|
125
|
-
production_secrets = Rails::Secrets.load(env: 'production')
|
52
|
+
Files are merged in order with deep merge support for nested hashes.
|
126
53
|
|
127
|
-
|
128
|
-
dev_secrets = Rails::Secrets.load(env: 'development')
|
129
|
-
```
|
54
|
+
## Manual API
|
130
55
|
|
131
|
-
**Environment-specific loading:**
|
132
56
|
```ruby
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
# Load development secrets
|
137
|
-
dev_secrets = Rails::Secrets.load(env: 'development')
|
138
|
-
```
|
57
|
+
# Parse specific files
|
58
|
+
secrets = Rails::Secrets.parse(['config/secrets.yml'], env: Rails.env)
|
139
59
|
|
140
|
-
|
60
|
+
# Load default config/secrets.yml
|
61
|
+
secrets = Rails::Secrets.load(env: 'production')
|
141
62
|
|
142
|
-
|
143
|
-
|
144
|
-
```yaml
|
145
|
-
production:
|
146
|
-
# String interpolation
|
147
|
-
api_key: <%= ENV['API_KEY'] %>
|
148
|
-
|
149
|
-
# Integer conversion
|
150
|
-
database_pool: <%= ENV.fetch('DB_POOL', '10').to_i %>
|
151
|
-
|
152
|
-
# Boolean conversion
|
153
|
-
debug_enabled: <%= ENV.fetch('DEBUG', 'false') == 'true' %>
|
154
|
-
|
155
|
-
# Array conversion
|
156
|
-
allowed_hosts: <%= ENV.fetch('HOSTS', 'localhost,127.0.0.1').split(',') %>
|
157
|
-
|
158
|
-
# Fallback values
|
159
|
-
timeout: <%= ENV.fetch('TIMEOUT', '30').to_i %>
|
160
|
-
adapter: <%= ENV.fetch('DB_ADAPTER', 'postgresql') %>
|
63
|
+
# Check if active
|
64
|
+
Secvault.active? # => true/false
|
161
65
|
```
|
162
66
|
|
163
|
-
##
|
67
|
+
## Rails 7.1 Integration
|
164
68
|
|
165
|
-
|
166
|
-
```ruby
|
167
|
-
# In Rails console - automatically added by setup_multi_file!
|
168
|
-
reload_secrets! # Reloads all configured files without server restart
|
169
|
-
# 🔄 Reloaded secrets from 3 files
|
69
|
+
For Rails 7.1 with existing secrets functionality:
|
170
70
|
|
171
|
-
# Also available as:
|
172
|
-
Rails.application.reload_secrets!
|
173
|
-
```
|
174
|
-
|
175
|
-
**Check integration status:**
|
176
71
|
```ruby
|
177
|
-
|
72
|
+
# config/initializers/secvault.rb
|
73
|
+
Secvault.setup_backward_compatibility_with_older_rails!
|
178
74
|
```
|
179
75
|
|
180
|
-
##
|
76
|
+
## ERB Templating
|
181
77
|
|
182
|
-
|
78
|
+
Supports full ERB templating for environment variables:
|
183
79
|
|
184
|
-
```
|
185
|
-
|
186
|
-
|
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(',') %>
|
187
87
|
```
|
188
88
|
|
189
|
-
|
89
|
+
## Development Tools
|
190
90
|
|
191
|
-
|
192
|
-
Rails.application.secrets.api_key # ✅ Works
|
193
|
-
Rails.application.secrets.oauth_settings # ✅ Works
|
194
|
-
Rails::Secrets.load # ✅ Load default config/secrets.yml
|
195
|
-
Rails::Secrets.parse(['custom.yml'], env: Rails.env) # ✅ Parse custom files
|
196
|
-
```
|
91
|
+
Reload secrets in development:
|
197
92
|
|
198
|
-
**Check if Secvault is active:**
|
199
93
|
```ruby
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
puts "Using default Rails secrets functionality"
|
204
|
-
end
|
94
|
+
# Available after setup_multi_file!
|
95
|
+
reload_secrets!
|
96
|
+
Rails.application.reload_secrets!
|
205
97
|
```
|
206
98
|
|
207
|
-
## Security Best Practices
|
208
|
-
|
209
|
-
- **Never commit production secrets** to version control
|
210
|
-
- **Use environment variables** in production with ERB: `<%= ENV['SECRET'] %>`
|
211
|
-
- **Use ENV.fetch()** with fallbacks: `<%= ENV.fetch('SECRET', 'default') %>`
|
212
|
-
|
213
99
|
## License
|
214
100
|
|
215
|
-
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(
|
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
|
data/lib/secvault/railtie.rb
CHANGED
@@ -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[
|
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
|
data/lib/secvault/secrets.rb
CHANGED
@@ -13,16 +13,16 @@ module Secvault
|
|
13
13
|
def setup(app)
|
14
14
|
# Only auto-setup for Rails 7.2+ where secrets functionality was removed
|
15
15
|
return unless rails_7_2_or_later?
|
16
|
-
|
16
|
+
|
17
17
|
secrets_path = app.root.join("config/secrets.yml")
|
18
18
|
|
19
19
|
if secrets_path.exist?
|
20
20
|
# Use a more reliable approach that works in all environments
|
21
21
|
app.config.before_configuration do
|
22
|
-
current_env = ENV[
|
22
|
+
current_env = ENV["RAILS_ENV"] || Rails.env || "development"
|
23
23
|
setup_secrets_immediately(app, secrets_path, current_env)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Also try during to_prepare as a fallback
|
27
27
|
app.config.to_prepare do
|
28
28
|
current_env = Rails.env
|
@@ -32,14 +32,14 @@ module Secvault
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# Manual setup method for Rails 7.1 (opt-in)
|
37
37
|
def setup_for_rails_71!(app)
|
38
38
|
secrets_path = app.root.join("config/secrets.yml")
|
39
39
|
|
40
40
|
if secrets_path.exist?
|
41
41
|
app.config.before_configuration do
|
42
|
-
current_env = ENV[
|
42
|
+
current_env = ENV["RAILS_ENV"] || Rails.env || "development"
|
43
43
|
setup_secrets_immediately(app, secrets_path, current_env)
|
44
44
|
end
|
45
45
|
end
|
@@ -61,7 +61,7 @@ module Secvault
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
# If secrets accessor already exists, merge the secrets
|
66
66
|
if Rails.application.respond_to?(:secrets) && Rails.application.secrets.respond_to?(:merge!)
|
67
67
|
Rails.application.secrets.merge!(secrets)
|
@@ -72,24 +72,20 @@ module Secvault
|
|
72
72
|
# Classic Rails::Secrets.parse implementation
|
73
73
|
# Parses plain YAML secrets files and merges shared + environment-specific sections
|
74
74
|
def parse(paths, env:)
|
75
|
-
paths.each_with_object(
|
75
|
+
paths.each_with_object({}) do |path, all_secrets|
|
76
76
|
# Handle string paths by converting to Pathname
|
77
77
|
path = Pathname.new(path) unless path.respond_to?(:exist?)
|
78
78
|
next unless path.exist?
|
79
|
-
|
79
|
+
|
80
80
|
# Read and process the plain YAML file content
|
81
81
|
source = path.read
|
82
|
-
|
82
|
+
|
83
83
|
# Process ERB and parse YAML
|
84
84
|
erb_result = ERB.new(source).result
|
85
|
-
secrets =
|
86
|
-
|
87
|
-
else
|
88
|
-
YAML.load(erb_result)
|
89
|
-
end
|
90
|
-
|
85
|
+
secrets = YAML.safe_load(erb_result, aliases: true, permitted_classes: [])
|
86
|
+
|
91
87
|
secrets ||= {}
|
92
|
-
|
88
|
+
|
93
89
|
# Merge shared secrets first, then environment-specific (using deep merge)
|
94
90
|
all_secrets.deep_merge!(secrets["shared"].deep_symbolize_keys) if secrets["shared"]
|
95
91
|
all_secrets.deep_merge!(secrets[env].deep_symbolize_keys) if secrets[env]
|
@@ -100,7 +96,7 @@ module Secvault
|
|
100
96
|
if secrets_path.exist?
|
101
97
|
# Handle plain YAML secrets.yml only
|
102
98
|
all_secrets = YAML.safe_load(ERB.new(secrets_path.read).result, aliases: true)
|
103
|
-
|
99
|
+
|
104
100
|
env_secrets = all_secrets[env.to_s]
|
105
101
|
return env_secrets.deep_symbolize_keys if env_secrets
|
106
102
|
end
|
@@ -109,10 +105,10 @@ module Secvault
|
|
109
105
|
end
|
110
106
|
|
111
107
|
private
|
112
|
-
|
108
|
+
|
113
109
|
def rails_7_2_or_later?
|
114
110
|
rails_version = Rails.version
|
115
|
-
major, minor = rails_version.split(
|
111
|
+
major, minor = rails_version.split(".").map(&:to_i)
|
116
112
|
major > 7 || (major == 7 && minor >= 2)
|
117
113
|
end
|
118
114
|
end
|
data/lib/secvault/version.rb
CHANGED
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:
|
@@ -57,7 +57,7 @@ module Secvault
|
|
57
57
|
class Error < StandardError; end
|
58
58
|
|
59
59
|
extend self
|
60
|
-
|
60
|
+
|
61
61
|
# Internal storage for loaded secrets
|
62
62
|
@@loaded_secrets = nil
|
63
63
|
|
@@ -65,12 +65,12 @@ module Secvault
|
|
65
65
|
def secrets
|
66
66
|
@@loaded_secrets || ActiveSupport::OrderedOptions.new
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
# Check if Secvault is currently active (started)
|
70
70
|
def active?
|
71
71
|
@@loaded_secrets != nil
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
# Check if Secvault is integrated with Rails.application.secrets
|
75
75
|
def rails_integrated?
|
76
76
|
defined?(Rails) && Rails::Secrets == Secvault::RailsSecrets
|
@@ -82,7 +82,7 @@ module Secvault
|
|
82
82
|
require "secvault/railtie"
|
83
83
|
require "secvault/rails_secrets"
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# Helper method to set up Secvault for older Rails versions
|
87
87
|
# This provides an easy way to integrate Secvault into older Rails apps
|
88
88
|
# that still have native Rails::Secrets functionality (like Rails 7.1).
|
@@ -100,24 +100,24 @@ module Secvault
|
|
100
100
|
Rails.send(:remove_const, :Secrets)
|
101
101
|
end
|
102
102
|
Rails.const_set(:Secrets, Secvault::RailsSecrets)
|
103
|
-
|
103
|
+
|
104
104
|
# Set up Rails.application.secrets replacement
|
105
105
|
Rails.application.config.after_initialize do
|
106
106
|
secrets_path = Rails.root.join("config/secrets.yml")
|
107
|
-
|
107
|
+
|
108
108
|
if secrets_path.exist?
|
109
109
|
# Load secrets using Secvault
|
110
110
|
loaded_secrets = Rails::Secrets.parse([secrets_path], env: Rails.env)
|
111
|
-
|
111
|
+
|
112
112
|
# Create ActiveSupport::OrderedOptions object for compatibility
|
113
113
|
secrets_object = ActiveSupport::OrderedOptions.new
|
114
114
|
secrets_object.merge!(loaded_secrets)
|
115
|
-
|
115
|
+
|
116
116
|
# Replace Rails.application.secrets
|
117
117
|
Rails.application.define_singleton_method(:secrets) do
|
118
118
|
secrets_object
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
# Log integration success (except in production)
|
122
122
|
unless Rails.env.production?
|
123
123
|
Rails.logger&.info "[Secvault] Rails 7.1 integration complete. Loaded #{loaded_secrets.keys.size} secret keys."
|
@@ -127,14 +127,14 @@ module Secvault
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
# Set up multi-file secrets loading with a clean API
|
132
132
|
# Just pass an array of file paths and Secvault handles the rest
|
133
133
|
#
|
134
134
|
# Usage in an initializer:
|
135
135
|
# Secvault.setup_multi_file!([
|
136
136
|
# 'config/secrets.yml',
|
137
|
-
# 'config/secrets.oauth.yml',
|
137
|
+
# 'config/secrets.oauth.yml',
|
138
138
|
# 'config/secrets.local.yml'
|
139
139
|
# ])
|
140
140
|
#
|
@@ -145,47 +145,47 @@ module Secvault
|
|
145
145
|
def setup_multi_file!(files, reload_method: Rails.env.development?, logger: !Rails.env.production?)
|
146
146
|
# Ensure Secvault integration is active
|
147
147
|
setup_backward_compatibility_with_older_rails! unless active?
|
148
|
-
|
148
|
+
|
149
149
|
# Convert strings to Pathname objects and resolve relative to Rails.root
|
150
150
|
file_paths = Array(files).map do |file|
|
151
151
|
file.is_a?(Pathname) ? file : Rails.root.join(file)
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
# Set up the multi-file loading
|
155
155
|
Rails.application.config.after_initialize do
|
156
156
|
load_multi_file_secrets!(file_paths, logger: logger)
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
# Add reload helper in development
|
160
160
|
if reload_method
|
161
161
|
add_reload_helper!(file_paths)
|
162
162
|
end
|
163
163
|
end
|
164
|
-
|
164
|
+
|
165
165
|
# Load secrets into Secvault.secrets only (no Rails integration)
|
166
166
|
def load_secrets_only!(files, logger: !Rails.env.production?)
|
167
167
|
# Convert strings to Pathname objects and resolve relative to Rails.root
|
168
168
|
file_paths = Array(files).map do |file|
|
169
169
|
file.is_a?(Pathname) ? file : Rails.root.join(file)
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
existing_files = file_paths.select(&:exist?)
|
173
|
-
|
173
|
+
|
174
174
|
if existing_files.any?
|
175
175
|
# Load and merge all secrets files using Secvault's parser directly
|
176
176
|
merged_secrets = Secvault::Secrets.parse(existing_files, env: Rails.env)
|
177
|
-
|
177
|
+
|
178
178
|
# Store in Secvault.secrets (ActiveSupport::OrderedOptions for compatibility)
|
179
179
|
@@loaded_secrets = ActiveSupport::OrderedOptions.new
|
180
180
|
@@loaded_secrets.merge!(merged_secrets)
|
181
|
-
|
181
|
+
|
182
182
|
# Log successful loading
|
183
183
|
if logger
|
184
184
|
file_names = existing_files.map(&:basename)
|
185
|
-
Rails.logger&.info "[Secvault] Loaded #{existing_files.size} files: #{file_names.join(
|
185
|
+
Rails.logger&.info "[Secvault] Loaded #{existing_files.size} files: #{file_names.join(", ")}"
|
186
186
|
Rails.logger&.info "[Secvault] Parsed #{merged_secrets.keys.size} secret keys for #{Rails.env}"
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
true
|
190
190
|
else
|
191
191
|
Rails.logger&.warn "[Secvault] No secrets files found" if logger
|
@@ -193,36 +193,36 @@ module Secvault
|
|
193
193
|
false
|
194
194
|
end
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
# Load secrets from multiple files and merge them (with Rails integration)
|
198
198
|
def load_multi_file_secrets!(file_paths, logger: !Rails.env.production?)
|
199
199
|
existing_files = file_paths.select(&:exist?)
|
200
|
-
|
200
|
+
|
201
201
|
if existing_files.any?
|
202
202
|
# Load and merge all secrets files
|
203
203
|
merged_secrets = Rails::Secrets.parse(existing_files, env: Rails.env)
|
204
|
-
|
204
|
+
|
205
205
|
# Create ActiveSupport::OrderedOptions object for Rails compatibility
|
206
206
|
secrets_object = ActiveSupport::OrderedOptions.new
|
207
207
|
secrets_object.merge!(merged_secrets)
|
208
|
-
|
208
|
+
|
209
209
|
# Replace Rails.application.secrets
|
210
210
|
Rails.application.define_singleton_method(:secrets) { secrets_object }
|
211
|
-
|
211
|
+
|
212
212
|
# Log successful loading
|
213
213
|
if logger
|
214
214
|
file_names = existing_files.map(&:basename)
|
215
|
-
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(", ")}"
|
216
216
|
Rails.logger&.info "[Secvault Multi-File] Merged #{merged_secrets.keys.size} secret keys for #{Rails.env}"
|
217
217
|
end
|
218
|
-
|
218
|
+
|
219
219
|
merged_secrets
|
220
220
|
else
|
221
221
|
Rails.logger&.warn "[Secvault Multi-File] No secrets files found" if logger
|
222
222
|
{}
|
223
223
|
end
|
224
224
|
end
|
225
|
-
|
225
|
+
|
226
226
|
# Add reload helper method for development
|
227
227
|
def add_reload_helper!(file_paths)
|
228
228
|
# Define reload method on Rails.application
|
@@ -231,15 +231,15 @@ module Secvault
|
|
231
231
|
puts "🔄 Reloaded secrets from #{file_paths.size} files"
|
232
232
|
true
|
233
233
|
end
|
234
|
-
|
234
|
+
|
235
235
|
# Also make it available as a top-level method
|
236
236
|
Object.define_method(:reload_secrets!) do
|
237
237
|
Rails.application.reload_secrets!
|
238
238
|
end
|
239
239
|
end
|
240
|
-
|
240
|
+
|
241
241
|
# Start Secvault and load secrets (without Rails integration)
|
242
|
-
#
|
242
|
+
#
|
243
243
|
# Usage:
|
244
244
|
# Secvault.start! # Uses config/secrets.yml only
|
245
245
|
# Secvault.start!(files: []) # Same as above
|
@@ -253,24 +253,22 @@ module Secvault
|
|
253
253
|
# - files: Array of file paths (String or Pathname). Defaults to ['config/secrets.yml']
|
254
254
|
# - logger: Enable logging (default: true except production)
|
255
255
|
def start!(files: [], logger: !Rails.env.production?)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
false
|
267
|
-
end
|
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
|
268
266
|
end
|
269
|
-
|
267
|
+
|
270
268
|
# Integrate loaded secrets with Rails.application.secrets
|
271
269
|
def integrate_with_rails!
|
272
270
|
return false unless @@loaded_secrets
|
273
|
-
|
271
|
+
|
274
272
|
begin
|
275
273
|
# Set up Rails::Secrets to use Secvault's parser (only when integrating)
|
276
274
|
unless rails_integrated?
|
@@ -279,12 +277,12 @@ module Secvault
|
|
279
277
|
end
|
280
278
|
Rails.const_set(:Secrets, Secvault::RailsSecrets)
|
281
279
|
end
|
282
|
-
|
280
|
+
|
283
281
|
# Replace Rails.application.secrets with Secvault's loaded secrets
|
284
282
|
Rails.application.define_singleton_method(:secrets) do
|
285
283
|
Secvault.secrets
|
286
284
|
end
|
287
|
-
|
285
|
+
|
288
286
|
Rails.logger&.info "[Secvault] Integrated with Rails.application.secrets" unless Rails.env.production?
|
289
287
|
true
|
290
288
|
rescue => e
|
@@ -292,7 +290,7 @@ module Secvault
|
|
292
290
|
false
|
293
291
|
end
|
294
292
|
end
|
295
|
-
|
293
|
+
|
296
294
|
# Backward compatibility aliases
|
297
295
|
alias_method :setup_rails_71_integration!, :setup_backward_compatibility_with_older_rails!
|
298
296
|
alias_method :setup_multi_files!, :setup_multi_file! # Alternative name
|
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.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unnikrishnan KP
|
@@ -49,21 +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
|
-
- USAGE_EXAMPLES.md
|
58
55
|
- lib/secvault.rb
|
59
|
-
- lib/secvault/generators/secrets_generator.rb
|
60
56
|
- lib/secvault/rails_secrets.rb
|
61
57
|
- lib/secvault/railtie.rb
|
62
58
|
- lib/secvault/secrets.rb
|
63
|
-
- lib/secvault/secrets_helper.rb
|
64
59
|
- lib/secvault/version.rb
|
65
|
-
- secvault-2.0.0.gem
|
66
|
-
- sig/secvault.rbs
|
67
60
|
homepage: https://github.com/unnitallman/secvault
|
68
61
|
licenses:
|
69
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
|
data/USAGE_EXAMPLES.md
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# Secvault API
|
2
|
-
|
3
|
-
Secvault provides separate control over secrets loading and Rails integration.
|
4
|
-
|
5
|
-
## Core Methods
|
6
|
-
|
7
|
-
### `Secvault.start!(files: [])`
|
8
|
-
|
9
|
-
Loads secrets from YAML files. Returns `true`/`false`.
|
10
|
-
|
11
|
-
- **Default**: Uses `config/secrets.yml` if `files` is empty
|
12
|
-
- **Access**: Secrets available via `Secvault.secrets`
|
13
|
-
- **Non-invasive**: Does not modify `Rails.application.secrets`
|
14
|
-
|
15
|
-
### `Secvault.integrate_with_rails!`
|
16
|
-
|
17
|
-
Replaces `Rails.application.secrets` with Secvault's loaded secrets. Returns `true`/`false`.
|
18
|
-
|
19
|
-
### `Secvault.secrets`
|
20
|
-
|
21
|
-
Access to loaded secrets as `ActiveSupport::OrderedOptions`.
|
22
|
-
|
23
|
-
### Status Methods
|
24
|
-
|
25
|
-
- `Secvault.active?` - Returns `true` if secrets have been loaded
|
26
|
-
- `Secvault.rails_integrated?` - Returns `true` if Rails integration is active
|
27
|
-
|
28
|
-
## Usage
|
29
|
-
|
30
|
-
### Standalone
|
31
|
-
|
32
|
-
```ruby
|
33
|
-
# Load secrets independently
|
34
|
-
Secvault.start!
|
35
|
-
api_key = Secvault.secrets.api_key
|
36
|
-
```
|
37
|
-
|
38
|
-
### With Rails Integration
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
# Load and integrate with Rails
|
42
|
-
Secvault.start!
|
43
|
-
Secvault.integrate_with_rails!
|
44
|
-
api_key = Rails.application.secrets.api_key
|
45
|
-
```
|
46
|
-
|
47
|
-
### Multiple Files
|
48
|
-
|
49
|
-
```ruby
|
50
|
-
# Files are deep-merged in order
|
51
|
-
Secvault.start!(files: [
|
52
|
-
'config/shared_secrets.yml',
|
53
|
-
'config/secrets.yml'
|
54
|
-
])
|
55
|
-
```
|
56
|
-
|
57
|
-
### Error Handling
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
if Secvault.start!(files: ['config/secrets.yml'])
|
61
|
-
if Secvault.integrate_with_rails!
|
62
|
-
# Both operations successful
|
63
|
-
end
|
64
|
-
end
|
65
|
-
```
|
@@ -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