vault_env_secrets 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a239afd0a1d9d133166b8c3f88f15162d9b4537437b5eee5ac602f99246ba196
4
+ data.tar.gz: 07ad320f88de1b735c9f5be34a95be6b6897fe71ae8943e5e36cd8e141c685ee
5
+ SHA512:
6
+ metadata.gz: 10feaf9ceffbb1892c20702623cbcec3c07b62bfbdcef60e216d4b1b9063ce3e68e70afbe1ec28710d0640be1f412b59ab9025322c841fd149c4c625770916dc
7
+ data.tar.gz: 475a66ab45ef7e558a1c7c09f919af52207695ec1d9691918df9087b4efb3388d0c35e1e45b0a4d47fc52488bae233f45c4425b6a71d33afac1e9088f7ff7aa1
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
3
+ ruby_version: 2.6
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # VaultEnvSecrets Change Log
2
+
3
+ ## [1.0.0] - 2023-08-19
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in vault_env_secrets.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
11
+
12
+ gem "standard", "~> 1.3"
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ vault_env_secrets (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ base64 (0.1.1)
11
+ json (2.6.3)
12
+ language_server-protocol (3.17.0.3)
13
+ lint_roller (1.1.0)
14
+ minitest (5.19.0)
15
+ parallel (1.23.0)
16
+ parser (3.2.2.3)
17
+ ast (~> 2.4.1)
18
+ racc
19
+ racc (1.7.1)
20
+ rainbow (3.1.1)
21
+ rake (13.0.6)
22
+ regexp_parser (2.8.1)
23
+ rexml (3.2.6)
24
+ rubocop (1.56.0)
25
+ base64 (~> 0.1.1)
26
+ json (~> 2.3)
27
+ language_server-protocol (>= 3.17.0)
28
+ parallel (~> 1.10)
29
+ parser (>= 3.2.2.3)
30
+ rainbow (>= 2.2.2, < 4.0)
31
+ regexp_parser (>= 1.8, < 3.0)
32
+ rexml (>= 3.2.5, < 4.0)
33
+ rubocop-ast (>= 1.28.1, < 2.0)
34
+ ruby-progressbar (~> 1.7)
35
+ unicode-display_width (>= 2.4.0, < 3.0)
36
+ rubocop-ast (1.29.0)
37
+ parser (>= 3.2.1.0)
38
+ rubocop-performance (1.19.0)
39
+ rubocop (>= 1.7.0, < 2.0)
40
+ rubocop-ast (>= 0.4.0)
41
+ ruby-progressbar (1.13.0)
42
+ standard (1.31.0)
43
+ language_server-protocol (~> 3.17.0.2)
44
+ lint_roller (~> 1.0)
45
+ rubocop (~> 1.56.0)
46
+ standard-custom (~> 1.0.0)
47
+ standard-performance (~> 1.2)
48
+ standard-custom (1.0.2)
49
+ lint_roller (~> 1.0)
50
+ rubocop (~> 1.50)
51
+ standard-performance (1.2.0)
52
+ lint_roller (~> 1.1)
53
+ rubocop-performance (~> 1.19.0)
54
+ unicode-display_width (2.4.2)
55
+
56
+ PLATFORMS
57
+ arm64-darwin-21
58
+ ruby
59
+ x86_64-linux
60
+
61
+ DEPENDENCIES
62
+ minitest (~> 5.0)
63
+ rake (~> 13.0)
64
+ standard (~> 1.3)
65
+ vault_env_secrets!
66
+
67
+ BUNDLED WITH
68
+ 2.4.10
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Nick Muerdter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # VaultEnvSecrets
2
+
3
+ A small gem to load secrets from [Vault](https://www.vaultproject.io) into environment variables by way of a [consul-template](https://github.com/hashicorp/consul-template) YAML template. Automatic integration with Rails is supported.
4
+
5
+ ## Requirements/Assumptions
6
+
7
+ - By default, a `consul-template` config file needs to be present in `config/vault.hcl` that defines a `template` that will render secrets in a YAML output file to `tmp/vault/secrets.yml`.
8
+ - You must be authenticate to Vault in some fashion outside of this library (eg, `vault login` is used before startup and `~/.vault-token` is present, or `VAULT_TOKEN` is set, etc).
9
+ - For Rails integration, secrets will only be read once on application startup (so to pick up changes in development, you must restart the Rails server).
10
+
11
+ ## Installation
12
+
13
+ Install the gem and add to the application's Gemfile by executing:
14
+
15
+ ```sh
16
+ bundle add vault_env_secrets
17
+ ```
18
+
19
+ If bundler is not being used to manage dependencies, install the gem by executing:
20
+
21
+ ```sh
22
+ gem install vault_env_secrets
23
+ ```
24
+
25
+ ## Example Usage
26
+
27
+ This gem mostly defers to to [`consul-template`](https://github.com/hashicorp/consul-template), with the assumption that there will be a YAML output file that can be read in. There are a variety of ways to use this, but as an example:
28
+
29
+ 1. Authenticate against Vault:
30
+
31
+ ```sh
32
+ vault login
33
+ ```
34
+
35
+ 2. Define a `consul-template` [configuration file](https://github.com/hashicorp/consul-template/blob/main/docs/configuration.md#configuration-file) in the default `config/vault.hcl` location:
36
+
37
+ ```hcl
38
+ vault {
39
+ address = "https://vault.example.com/"
40
+ renew_token = true
41
+
42
+ retry {
43
+ enabled = false
44
+ }
45
+ }
46
+
47
+ template {
48
+ source = "./config/vault/secrets.yml.ctmpl"
49
+ destination = "./tmp/vault/secrets.yml"
50
+ error_on_missing_key = true
51
+ perms = 0600
52
+ }
53
+ ```
54
+
55
+ 3. Define the template that the `config/vault.hcl` config file references (which should be configured to output to `tmp/vault/secrets.yml` by default). In this example the secret key base and database credentials are fetched from a `secret/my-app/<rails_env>/web` item:
56
+
57
+ ```ctmpl
58
+ {{ $rails_env := (envOrDefault "RAILS_ENV" "development") }}
59
+
60
+ {{ with secret (printf "secret/my-app/%s/web" $deploy_env) }}
61
+ {{ scratch.MapSet "secrets" "SECRET_KEY_BASE" .Data.data.secret_key_base }}
62
+ {{ scratch.MapSet "secrets" "SECRET_DB_HOST" .Data.data.db_host }}
63
+ {{ scratch.MapSet "secrets" "SECRET_DB_NAME" .Data.data.db_name }}
64
+ {{ scratch.MapSet "secrets" "SECRET_DB_USERNAME" .Data.data.db_username }}
65
+ {{ scratch.MapSet "secrets" "SECRET_DB_PASSWORD" .Data.data.db_password }}
66
+ {{ end }}
67
+
68
+ {{ scratch.Get "secrets" | toYAML }}
69
+ ```
70
+
71
+ 4. With the gem installed, any variables defined in the output YAML from the `consul-template` template will be set as environment variables on Rails startup. The environment variable names will depend on the names in the YAML output. So in the above example, `ENV["SECRET_KEY_BASE"]`, `ENV["SECRET_DB_HOST"]`, `ENV["SECRET_DB_PASSWORD"]`, etc would all be available to the app.
72
+
73
+ ## Configuration
74
+
75
+ You may adjust VaultEnvSecrets configuration by adding a `config/initializers/vault_env_secrets.rb` file with setting changes. Note that the initializer must exist at this path and filename to be properly loaded (this ensures that VaultEnvSecrets is available early on in the Rails load process, so other parts of Rails and other gems can integrate with it).
76
+
77
+ #### `VaultEnvSecrets.enabled`
78
+
79
+ Optionally disable loading VaultEnvSecrets (for example, if this gem only needs to be active in certain Rails environments).
80
+
81
+ ```ruby
82
+ VaultEnvSecrets.enabled = false # Defaults to `true`
83
+ ```
84
+
85
+ #### `VaultEnvSecrets.consul_template_config`
86
+
87
+ Set a custom path to the `consul-template` config file.
88
+
89
+ ```ruby
90
+ VaultEnvSecrets.consul_template_config = "config/my_config.hcl" # Defaults to `config/vault.hcl`
91
+ ```
92
+
93
+ #### `VaultEnvSecrets.consul_template_output`
94
+
95
+ Set a custom path to the YAML output file generated from the `consul-template` template.
96
+
97
+ ```ruby
98
+ VaultEnvSecrets.consul_template_output = "tmp/my_secrets.yml" # Defaults to `tmp/vault/secrets.yml`
99
+ ```
100
+
101
+ ## Development
102
+
103
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
104
+
105
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
106
+
107
+ ## Contributing
108
+
109
+ Bug reports and pull requests are welcome on GitHub at https://github.com/GUI/vault_env_secrets.
110
+
111
+ ## License
112
+
113
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/test_*.rb"]
10
+ end
11
+
12
+ require "standard/rake"
13
+
14
+ task default: %i[test standard]
@@ -0,0 +1,3 @@
1
+ module VaultEnvSecrets
2
+ class Error < StandardError; end
3
+ end
@@ -0,0 +1,26 @@
1
+ require "rails/railtie"
2
+
3
+ module VaultEnvSecrets
4
+ class Railtie < ::Rails::Railtie
5
+ # Load the secret keys as early as possible, so it can be used in other
6
+ # parts of the Rails configuration, like database.yml files.
7
+ config.before_configuration do
8
+ # Load the optional initializer manually (since this before_configuration
9
+ # phase is before when initializers are usually loaded), so that any
10
+ # customizations can be read in.
11
+ initializer = ::Rails.root.join("config", "initializers", "vault_env_secrets.rb")
12
+ require initializer if File.exist?(initializer)
13
+
14
+ VaultEnvSecrets.load
15
+ end
16
+
17
+ # Try to ensure our own "before_configuration" hook gets loaded before any
18
+ # others that have already been loaded, so that these secrets can be used
19
+ # as part of other gem's own before_configuration hooks (eg, in the
20
+ # "config" gem's settings.yml files).
21
+ load_hooks = ActiveSupport.instance_variable_get(:@load_hooks)
22
+ if load_hooks && load_hooks[:before_configuration]
23
+ load_hooks[:before_configuration] = load_hooks[:before_configuration].rotate(-1)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VaultEnvSecrets
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "yaml"
5
+
6
+ require_relative "vault_env_secrets/errors"
7
+ require_relative "vault_env_secrets/version"
8
+
9
+ module VaultEnvSecrets
10
+ @enabled = true
11
+ @consul_template_config = "config/vault.hcl"
12
+ @consul_template_output = "tmp/vault/secrets.yml"
13
+
14
+ class << self
15
+ attr_accessor :enabled
16
+ attr_accessor :consul_template_config
17
+ attr_accessor :consul_template_output
18
+
19
+ def load(env: {})
20
+ if enabled
21
+ # Check that the expected consul-template config file exists.
22
+ config_path = Pathname.new(consul_template_config)
23
+ if defined?(::Rails) && config_path.relative?
24
+ config_path = Rails.root.join(consul_template_config)
25
+ end
26
+ unless config_path.exist?
27
+ raise Error.new("consul-template config path (#{config_path.to_s.inspect}) does not exist")
28
+ end
29
+
30
+ # Run consul-template to render any template files.
31
+ system(env, "consul-template", "-config", config_path.to_s, "-once", exception: true)
32
+
33
+ # Check that the expected output file exists.
34
+ output_path = Pathname.new(consul_template_output)
35
+ if defined?(::Rails) && output_path.relative?
36
+ output_path = Rails.root.join(consul_template_output)
37
+ end
38
+ unless output_path.exist?
39
+ raise Error.new("consul-template rendered output path (#{output_path.to_s.inspect}) does not exist")
40
+ end
41
+
42
+ # Read the output YAML file and set any of the variables as environment
43
+ # variables.
44
+ secrets = YAML.safe_load_file(output_path)
45
+ if secrets
46
+ # Make sure the YAML output is an expected hash.
47
+ unless secrets.is_a?(Hash)
48
+ raise Error.new("YAML in consul-template output file does not of expected Hash type (#{output_path.to_s.inspect})")
49
+ end
50
+
51
+ secrets.each do |key, value|
52
+ # Reject nested values that can't be set as simple string values
53
+ # for environment variable purposes.
54
+ if value.is_a?(Array) || value.is_a?(Hash)
55
+ raise Error.new("YAML in consul-template output file has nested data that cannot be set as environment variables (#{output_path.to_s.inspect}: #{key.inspect} type #{value.class.name})")
56
+ end
57
+
58
+ ENV[key] = value.to_s
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ if defined?(::Rails)
67
+ require_relative "vault_env_secrets/railtie"
68
+ end
@@ -0,0 +1,4 @@
1
+ module VaultEnvSecrets
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vault_env_secrets
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nick Muerdter
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-08-19 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - 12112+GUI@users.noreply.github.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".standard.yml"
21
+ - CHANGELOG.md
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - lib/vault_env_secrets.rb
28
+ - lib/vault_env_secrets/errors.rb
29
+ - lib/vault_env_secrets/railtie.rb
30
+ - lib/vault_env_secrets/version.rb
31
+ - sig/vault_env_secrets.rbs
32
+ homepage: https://github.com/GUI/vault_env_secrets
33
+ licenses:
34
+ - MIT
35
+ metadata:
36
+ homepage_uri: https://github.com/GUI/vault_env_secrets
37
+ source_code_uri: https://github.com/GUI/vault_env_secrets/tree/v1.0.0
38
+ changelog_uri: https://github.com/GUI/vault_env_secrets/blob/v1.0.0/CHANGELOG.md
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.6.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.4.10
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Load secrets from Vault into environment variables (via consul-template config
58
+ and with Rails integration)
59
+ test_files: []