secvault 1.0.3 → 2.0.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: 1feb00404603d98e5aa714c5d3eeeab9821c16922da68196b394166c96180869
4
- data.tar.gz: 1d1b3c9db92ab5eae322e3803294eb689f81064a8625f16ea2d24d78bbdafc9d
3
+ metadata.gz: 99d7d1404f42246f62cbc8349ab689b43e8f24fa0ea52dd0e10910dee9615dcc
4
+ data.tar.gz: 4453d7ebce5a81e9e5fe0ed1dcd0df410a442ff669dd8dde02c15c3db3209a2e
5
5
  SHA512:
6
- metadata.gz: f74172837da3d461a3022574678b79ff322afb0cfa87bab3f5c09ddac4d5eff508fa573b67fe15571122c93ec62611f23405117ec2e33092fe1d61a1ad615ab1
7
- data.tar.gz: 353b087160697768744a51a1404bf30f2c8b1e7ca22e9d95c833088b003a44fb0e897f03f57dd1df780c193e2f8c81b0a5b41323a23d2ea10730de1599cad817
6
+ metadata.gz: c11facd4f7abd26f8ecc9bbccabf0ede865210e220a944aee8e4640cd7851237db2c3bebeba2bc9ddee96a5fe52fa70c324f9b3f5aee4e9a09378ebf2703c91a
7
+ data.tar.gz: f01237875bb61dac4a8e145adeb05c36813937f72a9d4af85c3ae6e5069c02e0df9efd4df7e1f30dee9263fc69543eb04ebbb2a6998b29a30fbced84702ada90
data/CHANGELOG.md CHANGED
@@ -1,5 +1,88 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.0.0] - 2025-09-22
4
+
5
+ ### BREAKING CHANGES
6
+
7
+ - **Removed all encryption functionality** - Secvault now focuses purely on plain YAML secrets management
8
+ - Removed ActiveSupport::EncryptedFile dependencies
9
+ - Removed MissingKeyError and InvalidKeyError exceptions
10
+ - Removed `encrypted?`, `decrypt`, `decrypt_secrets` methods
11
+ - Simplified rake tasks to work with plain YAML only
12
+
13
+ ### Added
14
+
15
+ - Simplified `rake secvault:setup` that creates plain YAML files with helpful comments
16
+ - Better error messages and user guidance in rake tasks
17
+ - Cleaner, more focused codebase without encryption complexity
18
+
19
+ ### Changed
20
+
21
+ - **Major simplification**: All secrets are now stored in plain YAML files
22
+ - Updated README to reflect plain YAML approach
23
+ - Updated module documentation and gemspec descriptions
24
+ - Rake tasks now use emojis and better user experience
25
+ - Production secrets should use ERB syntax with environment variables
26
+
27
+ ### Benefits
28
+
29
+ - Much simpler gem with single focus: plain YAML secrets management
30
+ - No encryption keys to manage or lose
31
+ - Easy to understand, edit, and debug secrets files
32
+ - Perfect for development and test environments
33
+ - Production secrets via environment variables (recommended best practice)
34
+
35
+ ## [1.0.4] - 2025-09-22
36
+
37
+ ### Added
38
+
39
+ - Comprehensive Rails 7.1 integration support
40
+ - New `Secvault.setup_rails_71_integration!` helper method for easy Rails 7.1 setup
41
+ - Enhanced documentation with Rails 7.1 integration guide
42
+ - Module-level documentation with usage examples and version compatibility
43
+
44
+ ### Improved
45
+
46
+ - Better Rails 7.1 compatibility with automatic detection and setup
47
+ - Enhanced README with Rails 7.1 integration section
48
+ - Improved error handling and logging for Rails 7.1 integration
49
+ - More comprehensive inline documentation
50
+
51
+ ### Changed
52
+
53
+ - Refined automatic setup logic to avoid conflicts with Rails 7.1 native functionality
54
+ - Updated gemspec description to include Rails 7.1+ support
55
+
56
+ ## [1.0.3] - 2025-09-22
57
+
58
+ ### Fixed
59
+
60
+ - Rails 7.1 compatibility issues with native Rails::Secrets conflicts
61
+ - String path handling in parse method
62
+ - Zeitwerk constant name mismatch resolution
63
+
64
+ ### Added
65
+
66
+ - Manual setup method for Rails 7.1 (opt-in)
67
+ - Rails version detection for automatic setup decisions
68
+ - Only create Rails::Secrets alias for Rails 7.2+ to avoid conflicts
69
+
70
+ ## [1.0.2] - 2025-09-22
71
+
72
+ ### Changed
73
+
74
+ - Updated Rails dependency from >= 7.2.0 to >= 7.1.0 for broader compatibility
75
+ - Updated gem description to include Rails 7.1+ support
76
+
77
+ ## [1.0.1] - 2025-09-22
78
+
79
+ ### Fixed
80
+
81
+ - Zeitwerk constant name mismatch in rails_secrets.rb
82
+ - Changed module definition from Rails::Secrets to Secvault::RailsSecrets
83
+ - Added Rails::Secrets alias for backward compatibility
84
+ - Resolved Zeitwerk::NameError when loading Rails applications
85
+
3
86
  ## [1.0.0] - 2025-09-22
4
87
 
5
88
  ### Added
data/README.md CHANGED
@@ -1,209 +1,87 @@
1
1
  # Secvault
2
2
 
3
- **Secvault** restores the classic Rails `secrets.yml` functionality that was removed in Rails 7.2, allowing you to manage encrypted secrets using the familiar YAML-based approach.
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.
4
4
 
5
- ## Why Secvault?
6
-
7
- Rails 7.2 removed the `secrets.yml` functionality completely in favor of credentials. However, many teams prefer the simplicity and familiarity of `secrets.yml` for managing environment-specific secrets. Secvault brings this functionality back with modern encryption support.
8
-
9
- ## Features
10
-
11
- - 🔐 **Encrypted secrets.yml** - Uses Rails' built-in encryption system
12
- - 🔑 **Key management** - Secure key generation and management
13
- - 🌍 **Environment-specific** - Different secrets for development, test, and production
14
- - 📝 **ERB support** - Use ERB templates in your secrets files
15
- - 🛠️ **Rake tasks** - Easy management with built-in rake tasks
16
- - 🚀 **Rails 7.2+ compatible** - Works seamlessly with modern Rails
5
+ **Rails Version Support:**
6
+ - **Rails 7.1**: Manual setup (see Rails 7.1 Integration below)
7
+ - **Rails 7.2+**: Automatic setup
8
+ - **Rails 8.0+**: Full compatibility
17
9
 
18
10
  ## Installation
19
11
 
20
- Add this line to your application's Gemfile:
21
-
22
12
  ```ruby
13
+ # Gemfile
23
14
  gem 'secvault'
24
15
  ```
25
16
 
26
- And then execute:
27
-
28
- ```bash
29
- $ bundle install
30
- ```
31
-
32
- ## Setup
33
-
34
- ### 1. Generate secrets file
35
-
36
- Run the setup task to create your encrypted `secrets.yml`:
37
-
38
- ```bash
39
- $ rake secvault:setup
40
- ```
41
-
42
- This will:
43
- - Generate `config/secrets.yml.key` (keep this secure!)
44
- - Create an encrypted `config/secrets.yml` with default content
45
- - Remind you to add the key file to `.gitignore`
46
-
47
- Alternatively, use the Rails generator:
48
-
49
- ```bash
50
- $ rails generate secvault:secrets
51
- ```
52
-
53
- ### 2. Add key to .gitignore
54
-
55
- Ensure your encryption key is not committed to version control:
56
-
57
17
  ```bash
58
- echo "/config/secrets.yml.key" >> .gitignore
18
+ bundle install
59
19
  ```
60
20
 
61
- ## Usage
62
-
63
- ### Editing secrets
64
-
65
- Edit your encrypted secrets file:
21
+ ## Quick Start (Rails 7.2+)
66
22
 
67
23
  ```bash
68
- $ rake secvault:edit
69
- ```
70
-
71
- This opens the decrypted file in your `$EDITOR`.
72
-
73
- ### Viewing secrets
74
-
75
- View the decrypted content:
24
+ # 1. Create secrets.yml with rake task
25
+ rake secvault:setup
76
26
 
77
- ```bash
78
- $ rake secvault:show
27
+ # 2. Edit secrets
28
+ rake secvault:edit
79
29
  ```
80
30
 
81
- ### Accessing secrets in your application
82
-
83
- Secrets are automatically loaded into `Rails.application.secrets`:
84
-
31
+ **Usage in your app:**
85
32
  ```ruby
86
- # In your Rails application
87
- Rails.application.secrets.secret_key_base
88
33
  Rails.application.secrets.api_key
89
34
  Rails.application.secrets.database_password
90
35
  ```
91
36
 
92
- ### Example secrets.yml structure
93
-
37
+ **Example secrets.yml:**
94
38
  ```yaml
95
- # config/secrets.yml (encrypted)
96
39
  development:
97
- secret_key_base: your_development_secret
98
- api_key: dev_api_key
40
+ api_key: dev_key
99
41
  database_password: dev_password
100
42
 
101
- test:
102
- secret_key_base: your_test_secret
103
- api_key: test_api_key
104
- database_password: test_password
105
-
106
43
  production:
107
- secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
108
44
  api_key: <%= ENV['API_KEY'] %>
109
45
  database_password: <%= ENV['DATABASE_PASSWORD'] %>
110
46
  ```
111
47
 
112
- ### Environment variable fallback
113
-
114
- You can set the encryption key via environment variable:
115
-
116
- ```bash
117
- export RAILS_SECRETS_KEY=your_encryption_key
118
- ```
119
-
120
- ## Production Deployment
121
-
122
- ### Option 1: Environment Variable
123
-
124
- Set the encryption key as an environment variable:
125
-
126
- ```bash
127
- export RAILS_SECRETS_KEY=your_encryption_key
128
- ```
129
-
130
- ### Option 2: Key File
131
-
132
- Securely copy `config/secrets.yml.key` to your production server.
133
-
134
- ### Docker
135
-
136
- For Docker deployments, you can pass the key as an environment variable:
137
-
138
- ```dockerfile
139
- ENV RAILS_SECRETS_KEY=your_encryption_key
48
+ **Production:** Use environment variables in your YAML:
49
+ ```yaml
50
+ production:
51
+ api_key: <%= ENV['API_KEY'] %>
140
52
  ```
141
53
 
142
- ## Rake Tasks
143
-
144
- | Task | Description |
145
- |------|-------------|
146
- | `rake secvault:setup` | Create encrypted secrets.yml and key |
147
- | `rake secvault:edit` | Edit the encrypted secrets file |
148
- | `rake secvault:show` | Display decrypted secrets content |
149
-
150
- ## Migration from Rails < 7.2
151
-
152
- If you're upgrading from an older Rails version that had `secrets.yml`:
153
-
154
- 1. Install secvault: `bundle add secvault`
155
- 2. Encrypt existing secrets: `rake secvault:setup`
156
- 3. Copy your existing secrets content using `rake secvault:edit`
157
- 4. Remove the old plain-text `config/secrets.yml`
54
+ ## Rails 7.1 Integration
158
55
 
159
- ## Security Best Practices
56
+ Test Secvault in Rails 7.1 before upgrading to 7.2+:
160
57
 
161
- - ✅ **Never commit** `config/secrets.yml.key` to version control
162
- - ✅ **Use environment variables** for production secrets when possible
163
- - ✅ **Rotate keys** periodically
164
- - ✅ **Use strong, unique keys** for each environment
165
- - ✅ **Limit access** to key files in production
166
-
167
- ## Troubleshooting
168
-
169
- ### Missing Key Error
170
-
171
- ```
172
- Missing encryption key to decrypt secrets.yml
58
+ ```ruby
59
+ # config/initializers/secvault.rb
60
+ Secvault.setup_rails_71_integration!
173
61
  ```
174
62
 
175
- **Solution**: Ensure `config/secrets.yml.key` exists or set `RAILS_SECRETS_KEY` environment variable.
63
+ This replaces Rails.application.secrets with Secvault functionality. Your existing Rails 7.1 code works unchanged:
176
64
 
177
- ### Invalid Key Error
178
-
179
- ```
180
- Invalid encryption key for secrets.yml
65
+ ```ruby
66
+ Rails.application.secrets.api_key # ✅ Works
67
+ Rails.application.secrets.oauth_settings # ✅ Works
68
+ Rails::Secrets.parse_default # Enhanced functionality
181
69
  ```
182
70
 
183
- **Solution**: The key doesn't match the encrypted file. Verify you're using the correct key.
184
-
185
- ### File Not Found
71
+ ## Available Commands
186
72
 
73
+ ```bash
74
+ rake secvault:setup # Create plain secrets.yml file
75
+ rake secvault:edit # Edit secrets.yml file
76
+ rake secvault:show # Display secrets.yml content
187
77
  ```
188
- Secrets file doesn't exist
189
- ```
190
-
191
- **Solution**: Run `rake secvault:setup` to create the secrets file.
192
-
193
- ## Development
194
78
 
195
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
79
+ ## Security
196
80
 
197
- To install this gem onto your local machine, run `bundle exec rake install`.
198
-
199
- ## Contributing
200
-
201
- Bug reports and pull requests are welcome on GitHub at https://github.com/unnitallman/secvault.
81
+ ⚠️ Never commit production secrets to version control
82
+ ✅ Use environment variables for production secrets with ERB syntax: `<%= ENV['SECRET'] %>`
83
+ Add `config/secrets.yml` to `.gitignore` if it contains sensitive data
202
84
 
203
85
  ## License
204
86
 
205
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
206
-
207
- ## Code of Conduct
208
-
209
- Everyone interacting in the Secvault project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/secvault/blob/main/CODE_OF_CONDUCT.md).
87
+ MIT License - see [LICENSE](https://opensource.org/licenses/MIT)
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/encrypted_file"
4
3
  require "active_support/core_ext/hash/keys"
5
- require "active_support/core_ext/object/blank"
6
4
  require "active_support/ordered_options"
7
5
  require "pathname"
8
6
  require "erb"
@@ -16,20 +14,19 @@ module Secvault
16
14
  return unless rails_7_2_or_later?
17
15
 
18
16
  secrets_path = app.root.join("config/secrets.yml")
19
- key_path = app.root.join("config/secrets.yml.key")
20
17
 
21
18
  if secrets_path.exist?
22
19
  # Use a more reliable approach that works in all environments
23
20
  app.config.before_configuration do
24
21
  current_env = ENV['RAILS_ENV'] || Rails.env || 'development'
25
- setup_secrets_immediately(app, secrets_path, key_path, current_env)
22
+ setup_secrets_immediately(app, secrets_path, current_env)
26
23
  end
27
24
 
28
25
  # Also try during to_prepare as a fallback
29
26
  app.config.to_prepare do
30
27
  current_env = Rails.env
31
28
  unless Rails.application.respond_to?(:secrets) && !Rails.application.secrets.empty?
32
- setup_secrets_immediately(app, secrets_path, key_path, current_env)
29
+ setup_secrets_immediately(app, secrets_path, current_env)
33
30
  end
34
31
  end
35
32
  end
@@ -38,19 +35,18 @@ module Secvault
38
35
  # Manual setup method for Rails 7.1 (opt-in)
39
36
  def setup_for_rails_71!(app)
40
37
  secrets_path = app.root.join("config/secrets.yml")
41
- key_path = app.root.join("config/secrets.yml.key")
42
38
 
43
39
  if secrets_path.exist?
44
40
  app.config.before_configuration do
45
41
  current_env = ENV['RAILS_ENV'] || Rails.env || 'development'
46
- setup_secrets_immediately(app, secrets_path, key_path, current_env)
42
+ setup_secrets_immediately(app, secrets_path, current_env)
47
43
  end
48
44
  end
49
45
  end
50
46
 
51
- def setup_secrets_immediately(app, secrets_path, key_path, env)
47
+ def setup_secrets_immediately(app, secrets_path, env)
52
48
  # Set up secrets if they exist
53
- secrets = read_secrets(secrets_path, key_path, env)
49
+ secrets = read_secrets(secrets_path, env)
54
50
  if secrets
55
51
  # Rails 8.0+ compatibility: Add secrets accessor that initializes on first access
56
52
  unless Rails.application.respond_to?(:secrets)
@@ -58,7 +54,7 @@ module Secvault
58
54
  @secrets ||= begin
59
55
  current_secrets = ActiveSupport::OrderedOptions.new
60
56
  # Re-read secrets to ensure we have the right environment
61
- env_secrets = Secvault::Secrets.read_secrets(secrets_path, key_path, Rails.env)
57
+ env_secrets = Secvault::Secrets.read_secrets(secrets_path, Rails.env)
62
58
  current_secrets.merge!(env_secrets) if env_secrets
63
59
  current_secrets
64
60
  end
@@ -73,19 +69,15 @@ module Secvault
73
69
  end
74
70
 
75
71
  # Classic Rails::Secrets.parse implementation
76
- # Parses secrets files and merges shared + environment-specific sections
72
+ # Parses plain YAML secrets files and merges shared + environment-specific sections
77
73
  def parse(paths, env:)
78
74
  paths.each_with_object(Hash.new) do |path, all_secrets|
79
75
  # Handle string paths by converting to Pathname
80
76
  path = Pathname.new(path) unless path.respond_to?(:exist?)
81
77
  next unless path.exist?
82
78
 
83
- # Read and process the file content (handle both encrypted and plain)
84
- source = if encrypted?(path)
85
- decrypt(path)
86
- else
87
- preprocess(path)
88
- end
79
+ # Read and process the plain YAML file content
80
+ source = path.read
89
81
 
90
82
  # Process ERB and parse YAML
91
83
  erb_result = ERB.new(source).result
@@ -102,22 +94,12 @@ module Secvault
102
94
  all_secrets.merge!(secrets[env].deep_symbolize_keys) if secrets[env]
103
95
  end
104
96
  end
105
-
106
- # Helper method to preprocess plain YAML files (for ERB)
107
- def preprocess(path)
108
- path.read
109
- end
110
97
 
111
- def read_secrets(secrets_path, key_path, env)
98
+ def read_secrets(secrets_path, env)
112
99
  if secrets_path.exist?
113
- all_secrets = if key_path.exist? || encrypted?(secrets_path)
114
- # Handle encrypted secrets.yml
115
- decrypt_secrets(secrets_path, key_path)
116
- else
117
- # Handle plain YAML secrets.yml
118
- YAML.safe_load(ERB.new(secrets_path.read).result, aliases: true)
119
- end
120
-
100
+ # Handle plain YAML secrets.yml only
101
+ all_secrets = YAML.safe_load(ERB.new(secrets_path.read).result, aliases: true)
102
+
121
103
  env_secrets = all_secrets[env.to_s]
122
104
  return env_secrets.deep_symbolize_keys if env_secrets
123
105
  end
@@ -125,46 +107,7 @@ module Secvault
125
107
  {}
126
108
  end
127
109
 
128
- def encrypted?(path)
129
- # Simple heuristic to detect if file is encrypted
130
- content = path.read
131
- # Encrypted files typically contain non-printable characters
132
- !content.valid_encoding? || content.bytes.any? { |b| b < 32 && b != 10 && b != 13 }
133
- rescue
134
- false
135
- end
136
-
137
110
  private
138
-
139
- def decrypt_secrets(secrets_path, key_path)
140
- encrypted_file = ActiveSupport::EncryptedFile.new(
141
- content_path: secrets_path,
142
- key_path: key_path,
143
- env_key: "RAILS_SECRETS_KEY",
144
- raise_if_missing_key: true
145
- )
146
-
147
- content = encrypted_file.read
148
- YAML.safe_load(ERB.new(content).result, aliases: true) if content.present?
149
- rescue ActiveSupport::EncryptedFile::MissingKeyError
150
- raise MissingKeyError,
151
- "Missing encryption key to decrypt secrets.yml. " \
152
- "Ask your team for your secrets key and put it in config/secrets.yml.key"
153
- rescue ActiveSupport::EncryptedFile::InvalidMessage
154
- raise InvalidKeyError,
155
- "Invalid encryption key for secrets.yml."
156
- end
157
-
158
- def decrypt(path)
159
- key_path = Pathname.new("#{path}.key")
160
- encrypted_file = ActiveSupport::EncryptedFile.new(
161
- content_path: path,
162
- key_path: key_path,
163
- env_key: "RAILS_SECRETS_KEY",
164
- raise_if_missing_key: true
165
- )
166
- encrypted_file.read
167
- end
168
111
 
169
112
  def rails_7_2_or_later?
170
113
  rails_version = Rails.version
@@ -1,135 +1,75 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/encrypted_file"
4
3
  require "securerandom"
5
4
 
6
5
  namespace :secvault do
7
- desc "Setup secrets.yml file (plain YAML by default)"
6
+ desc "Create a plain YAML secrets.yml file"
8
7
  task setup: :environment do
9
8
  secrets_path = Rails.root.join("config/secrets.yml")
10
- key_path = Rails.root.join("config/secrets.yml.key")
11
- encrypted = ENV["ENCRYPTED"] == "true"
12
9
 
13
10
  if secrets_path.exist?
14
11
  puts "Secrets file already exists at #{secrets_path}"
15
12
  else
16
13
  default_content = <<~YAML
17
- # Be sure to restart your server when you modify this file.
14
+ # Plain YAML secrets file
15
+ # Environment-specific secrets for your Rails application
18
16
  #
19
- # Your secret key is used for verifying the integrity of signed cookies.
20
- # If you change this key, all old signed cookies will become invalid!
21
- #
22
- # Make sure the secret is at least 30 characters and all random,
23
- # no regular words or you'll be exposed to dictionary attacks.
24
- # You can use `rails secret` to generate a secure secret key.
17
+ # For production, use environment variables with ERB syntax:
18
+ # production:
19
+ # api_key: <%= ENV['API_KEY'] %>
25
20
 
26
21
  development:
27
22
  secret_key_base: #{SecureRandom.hex(64)}
23
+ # Add your development secrets here
24
+ # api_key: dev_key
25
+ # database_password: dev_password
28
26
 
29
27
  test:
30
28
  secret_key_base: #{SecureRandom.hex(64)}
29
+ # Add your test secrets here
30
+ # api_key: test_key
31
31
 
32
- # Do not keep production secrets in the repository,
33
- # instead read values from the environment.
34
32
  production:
35
33
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
34
+ # Use environment variables for production secrets
35
+ # api_key: <%= ENV["API_KEY"] %>
36
+ # database_password: <%= ENV["DATABASE_PASSWORD"] %>
36
37
  YAML
37
38
 
38
- if encrypted
39
- # Create encrypted file
40
- unless key_path.exist?
41
- key = ActiveSupport::EncryptedFile.generate_key
42
- File.write(key_path, key)
43
- puts "Generated encryption key in #{key_path}"
44
- end
45
-
46
- encrypted_file = ActiveSupport::EncryptedFile.new(
47
- content_path: secrets_path,
48
- key_path: key_path,
49
- env_key: "RAILS_SECRETS_KEY",
50
- raise_if_missing_key: true
51
- )
52
- encrypted_file.write(default_content)
53
- puts "Created encrypted secrets.yml file"
54
- puts "Add #{key_path} to your .gitignore file"
55
- else
56
- # Create plain YAML file
57
- File.write(secrets_path, default_content)
58
- puts "Created plain secrets.yml file"
59
- puts "Remember to add #{secrets_path} to your .gitignore if it contains sensitive data"
60
- end
39
+ File.write(secrets_path, default_content)
40
+ puts "✅ Created plain secrets.yml file at #{secrets_path}"
41
+ puts "⚠️ Remember to add production secrets as environment variables"
42
+ puts "⚠️ Never commit production secrets to version control"
61
43
  end
62
44
  end
63
45
 
64
- desc "Edit secrets.yml file"
46
+ desc "Edit the plain YAML secrets.yml file"
65
47
  task edit: :environment do
66
48
  secrets_path = Rails.root.join("config/secrets.yml")
67
- key_path = Rails.root.join("config/secrets.yml.key")
68
49
 
69
50
  unless secrets_path.exist?
70
51
  puts "Secrets file doesn't exist. Run 'rake secvault:setup' first."
71
52
  exit 1
72
53
  end
73
54
 
74
- # Check if file is encrypted
75
- is_encrypted = Secvault::Secrets.encrypted?(secrets_path)
76
-
77
- if is_encrypted && key_path.exist?
78
- # Handle encrypted file
79
- encrypted_file = ActiveSupport::EncryptedFile.new(
80
- content_path: secrets_path,
81
- key_path: key_path,
82
- env_key: "RAILS_SECRETS_KEY",
83
- raise_if_missing_key: true
84
- )
85
-
86
- encrypted_file.change do |tmp_path|
87
- system("#{ENV["EDITOR"] || "vi"} #{tmp_path}")
88
- end
89
-
90
- puts "Updated encrypted #{secrets_path}"
91
- else
92
- # Handle plain YAML file
93
- system("#{ENV["EDITOR"] || "vi"} #{secrets_path}")
94
- puts "Updated plain #{secrets_path}"
95
- end
96
- rescue ActiveSupport::EncryptedFile::MissingKeyError
97
- puts "Missing encryption key to decrypt secrets.yml."
98
- puts "Ask your team for your secrets key and put it in #{key_path}"
99
- rescue ActiveSupport::EncryptedFile::InvalidMessage
100
- puts "Invalid encryption key for secrets.yml."
55
+ # Open the plain YAML file in editor
56
+ editor = ENV["EDITOR"] || "vi"
57
+ system("#{editor} #{secrets_path}")
58
+ puts "📝 Updated #{secrets_path}"
101
59
  end
102
60
 
103
- desc "Show secrets.yml content"
61
+ desc "Show the plain YAML secrets.yml content"
104
62
  task show: :environment do
105
63
  secrets_path = Rails.root.join("config/secrets.yml")
106
- key_path = Rails.root.join("config/secrets.yml.key")
107
64
 
108
65
  unless secrets_path.exist?
109
66
  puts "Secrets file doesn't exist. Run 'rake secvault:setup' first."
110
67
  exit 1
111
68
  end
112
69
 
113
- # Check if file is encrypted
114
- is_encrypted = Secvault::Secrets.encrypted?(secrets_path)
115
-
116
- if is_encrypted && key_path.exist?
117
- # Handle encrypted file
118
- encrypted_file = ActiveSupport::EncryptedFile.new(
119
- content_path: secrets_path,
120
- key_path: key_path,
121
- env_key: "RAILS_SECRETS_KEY",
122
- raise_if_missing_key: true
123
- )
124
- puts encrypted_file.read
125
- else
126
- # Handle plain YAML file
127
- puts File.read(secrets_path)
128
- end
129
- rescue ActiveSupport::EncryptedFile::MissingKeyError
130
- puts "Missing encryption key to decrypt secrets.yml."
131
- puts "Ask your team for your secrets key and put it in #{key_path}"
132
- rescue ActiveSupport::EncryptedFile::InvalidMessage
133
- puts "Invalid encryption key for secrets.yml."
70
+ puts "📄 Contents of #{secrets_path}:"
71
+ puts "#{'=' * 50}"
72
+ puts File.read(secrets_path)
73
+ puts "#{'=' * 50}"
134
74
  end
135
75
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Secvault
4
- VERSION = "1.0.3"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/secvault.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require "rails"
4
4
  require "yaml"
5
5
  require "erb"
6
- require "active_support/encrypted_file"
7
6
  require "active_support/core_ext/hash/keys"
8
7
  require "zeitwerk"
9
8
 
@@ -12,10 +11,49 @@ require_relative "secvault/version"
12
11
  loader = Zeitwerk::Loader.for_gem
13
12
  loader.setup
14
13
 
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
18
+ # management.
19
+ #
20
+ # ## Rails Version Support:
21
+ # - Rails 7.1: Requires manual setup (see Rails 7.1 integration guide)
22
+ # - Rails 7.2+: Automatic setup, drop-in replacement for removed functionality
23
+ # - Rails 8.0+: Full compatibility
24
+ #
25
+ # ## Rails 7.1 Integration:
26
+ # For Rails 7.1 apps, add this initializer to override native Rails::Secrets:
27
+ #
28
+ # # config/initializers/secvault.rb
29
+ # module Rails
30
+ # remove_const(:Secrets) if defined?(Secrets)
31
+ # Secrets = Secvault::RailsSecrets
32
+ # end
33
+ #
34
+ # Rails.application.config.after_initialize do
35
+ # secrets_path = Rails.root.join("config/secrets.yml")
36
+ # if secrets_path.exist?
37
+ # loaded_secrets = Rails::Secrets.parse([secrets_path], env: Rails.env)
38
+ # secrets_object = ActiveSupport::OrderedOptions.new
39
+ # secrets_object.merge!(loaded_secrets)
40
+ # Rails.application.define_singleton_method(:secrets) { secrets_object }
41
+ # end
42
+ # end
43
+ #
44
+ # ## Usage:
45
+ # Rails.application.secrets.api_key
46
+ # Rails.application.secrets.oauth_settings[:google_client_id]
47
+ # Rails::Secrets.parse_default(env: 'development')
48
+ #
49
+ # ## Rake Tasks:
50
+ # rake secvault:setup # Create plain secrets.yml file
51
+ # rake secvault:edit # Edit secrets.yml file
52
+ # rake secvault:show # Display secrets.yml content
53
+ #
54
+ # @see https://github.com/unnitallman/secvault
15
55
  module Secvault
16
56
  class Error < StandardError; end
17
- class MissingKeyError < Error; end
18
- class InvalidKeyError < Error; end
19
57
 
20
58
  extend self
21
59
 
@@ -25,6 +63,51 @@ module Secvault
25
63
  require "secvault/railtie"
26
64
  require "secvault/rails_secrets"
27
65
  end
66
+
67
+ # Helper method to set up Secvault for Rails 7.1 applications
68
+ # This provides an easy way to integrate Secvault into Rails 7.1 apps
69
+ # that still have native Rails::Secrets functionality.
70
+ #
71
+ # Usage in an initializer:
72
+ # Secvault.setup_rails_71_integration!
73
+ #
74
+ # This will:
75
+ # 1. Override native Rails::Secrets with Secvault implementation
76
+ # 2. Replace Rails.application.secrets with Secvault-powered functionality
77
+ # 3. Load secrets from config/secrets.yml automatically
78
+ def setup_rails_71_integration!
79
+ # Override native Rails::Secrets
80
+ if defined?(Rails::Secrets)
81
+ Rails.send(:remove_const, :Secrets)
82
+ end
83
+ Rails.const_set(:Secrets, Secvault::RailsSecrets)
84
+
85
+ # Set up Rails.application.secrets replacement
86
+ Rails.application.config.after_initialize do
87
+ secrets_path = Rails.root.join("config/secrets.yml")
88
+
89
+ if secrets_path.exist?
90
+ # Load secrets using Secvault
91
+ loaded_secrets = Rails::Secrets.parse([secrets_path], env: Rails.env)
92
+
93
+ # Create ActiveSupport::OrderedOptions object for compatibility
94
+ secrets_object = ActiveSupport::OrderedOptions.new
95
+ secrets_object.merge!(loaded_secrets)
96
+
97
+ # Replace Rails.application.secrets
98
+ Rails.application.define_singleton_method(:secrets) do
99
+ secrets_object
100
+ end
101
+
102
+ # Log integration success (except in production)
103
+ unless Rails.env.production?
104
+ Rails.logger&.info "[Secvault] Rails 7.1 integration complete. Loaded #{loaded_secrets.keys.size} secret keys."
105
+ end
106
+ else
107
+ Rails.logger&.warn "[Secvault] No secrets.yml file found at #{secrets_path}"
108
+ end
109
+ end
110
+ end
28
111
  end
29
112
 
30
113
  Secvault.install! if defined?(Rails)
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: 1.0.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Unnikrishnan KP
@@ -39,8 +39,8 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.6'
41
41
  description: Secvault restores the classic Rails secrets.yml functionality that was
42
- removed in Rails 7.2, allowing you to manage encrypted secrets using the familiar
43
- YAML-based approach. Compatible with Rails 7.1+, 7.2+ and 8.0+.
42
+ removed in Rails 7.2, using simple, plain YAML files for environment-specific secrets
43
+ management. Compatible with Rails 7.1+, 7.2+ and 8.0+.
44
44
  email:
45
45
  - unnikrishnan.kp@bigbinary.com
46
46
  executables: []
@@ -62,8 +62,6 @@ files:
62
62
  - lib/secvault/secrets_helper.rb
63
63
  - lib/secvault/tasks.rake
64
64
  - lib/secvault/version.rb
65
- - secvault-1.0.1.gem
66
- - secvault-1.0.2.gem
67
65
  - sig/secvault.rbs
68
66
  homepage: https://github.com/unnitallman/secvault
69
67
  licenses:
@@ -91,5 +89,5 @@ requirements: []
91
89
  rubygems_version: 3.5.10
92
90
  signing_key:
93
91
  specification_version: 4
94
- summary: Rails secrets.yml functionality for Rails 7.1+, 7.2+ and Rails 8.0+
92
+ summary: Simple Rails secrets.yml functionality for Rails 7.1+, 7.2+ and Rails 8.0+
95
93
  test_files: []
data/secvault-1.0.1.gem DELETED
Binary file
data/secvault-1.0.2.gem DELETED
Binary file