on_container 0.0.11 → 0.0.12

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: 819d1f5a057f277e3b816eedd99435c9816b6d1ec6ff2e79e2d90798b5b74648
4
- data.tar.gz: 163f0552ec15c2b0199934ec81313d8708877339e20504c427f270e228ecc94b
3
+ metadata.gz: cc7ffb417b7d418f2415df1cd5c6cbd0325d78e576e71a701010bd44ead098f6
4
+ data.tar.gz: 260e06a5fa81789bc977cac9b02c8e092100a0896d9eccc4c4f88423592a1f9d
5
5
  SHA512:
6
- metadata.gz: 16c10e11aa18e20cd8fb02ee53018f5477c1ec661ef6c43329b6c0a74814d0bb7b00f785c9966f2006670e0c73858c36d719ff5177ece9b35fb54fbc33743808
7
- data.tar.gz: 900379b6246d9d44f301a81213e965feec8cb1235bd514fc9235b3e5fd5dc97b5f91399f25b18ac7efd0596e9a15e878766f85726e98040b30a688e80f0519db
6
+ metadata.gz: 9e54869d4ec1c390a555731ac199ece8b804098eece937321123e48884d0b7fa0dff418147f97e811b4e05fb23517f433bf622b08fc4f4941d04801fa31f8570
7
+ data.tar.gz: 410eb4b5c14a632600ecccade83dcca9764965085dfa95177976365bc762516ac36e8d6ec70cdd51925d9204c19652afe80c50887774b67ffbe0990c9edeb18b
@@ -1,58 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Reads the specified secret paths (i.e. Docker Secrets) into environment
4
- # variables:
5
-
6
- require 'active_support'
7
- require 'active_support/core_ext/object'
8
-
9
- # Load secrets from Google Cloud Secret Manager to ENV, if any:
10
- require 'on_container/secrets/google_cloud/env_loader'
11
- OnContainer::Secrets::GoogleCloud::EnvLoader.perform!
12
-
13
- # Process only a known list of env vars that can filled by reading a file (i.e.
14
- # a docker secret):
15
- Dir["#{ENV.fetch('SECRETS_PATH', '/run/secrets')}/**/*"].map do |path|
16
- Pathname.new(path)
17
- end.select(&:file?).each do |secret_filepath|
18
- secret_envvarname = secret_filepath.basename('.*').to_s.upcase
19
-
20
- # Skip if variable is already set - already-set variables have precedence over
21
- # the secret files:
22
- next if ENV.key?(secret_envvarname) && ENV[secret_envvarname].present?
23
-
24
- ENV[secret_envvarname] = File.read(secret_filepath).strip
25
- end
26
-
27
- # For each *_URL environment variable where there's also a *_(USER|USERNAME) or
28
- # *_(PASS|PASSWORD), update the URL environment variable with the given
29
- # credentials. For example:
3
+ # This script achieves a list of secret loading & processing:
30
4
  #
31
- # DATABASE_URL: postgres://postgres:5432/demo_production
32
- # DATABASE_USERNAME: lalito
33
- # DATABASE_PASSWORD: lepass
5
+ # 1. Loads secrets from Google Cloud Secret Manager to ENV, if configured.
6
+ # 2. Reads files in a configured Folder, and loads them into ENV variables.
7
+ # 3. Processes "*_URL" env vars, adding their respective "*_USER" and "*_PASS".
34
8
  #
35
- # Results in the following updated DATABASE_URL:
36
- # DATABASE_URL = postgres://lalito:lepass@postgres:5432/demo_production
37
- require 'uri' if (url_keys = ENV.keys.select { |key| key =~ /_URL/ }).any?
38
-
39
- url_keys.each do |url_key|
40
- credential_pattern_string = url_key.gsub('_URL', '_(USER(NAME)?|PASS(WORD)?)')
41
- credential_pattern = Regexp.new "\\A#{credential_pattern_string}\\z"
42
- credential_keys = ENV.keys.select { |key| key =~ credential_pattern }
43
- next unless credential_keys.any?
44
-
45
- uri = URI(ENV[url_key])
46
-
47
- credential_keys.each do |credential_key|
48
- credential_value = URI.encode_www_form_component ENV[credential_key]
49
- case credential_key
50
- when /USER/ then uri.user = credential_value
51
- when /PASS/ then uri.password = credential_value
52
- end
53
- end
54
-
55
- ENV[url_key] = uri.to_s
56
- end
9
+ # - See https://github.com/IcaliaLabs/on-container-for-ruby#loading-secrets-into-environment-variables
57
10
 
58
- # STDERR.puts ENV.inspect
11
+ require 'on_container/secrets/env_loader'
12
+ OnContainer::Secrets::EnvLoader.perform!
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'on_container/common/safe_performable'
4
+ require 'on_container/secrets/google_cloud/env_loader'
5
+ require 'on_container/secrets/mounted_files/env_loader'
6
+ require 'on_container/secrets/url_variable_processor'
7
+
8
+ module OnContainer
9
+ module Secrets
10
+ #= EnvLoader
11
+ #
12
+ # Reads the specified secret paths (i.e. Docker Secrets) into environment
13
+ # variables:
14
+ class EnvLoader
15
+ include OnContainer::Common::SafePerformable
16
+
17
+ def perform!
18
+ load_secrets_from_google_cloud if google_cloud_secrets?
19
+ load_secrets_from_mounted_files
20
+ process_url_variables
21
+ true
22
+ end
23
+
24
+ private
25
+
26
+ def google_cloud_secrets?
27
+ OnContainer::Secrets::GoogleCloud::EnvLoader.secret_manager?
28
+ end
29
+
30
+ def load_secrets_from_google_cloud
31
+ OnContainer::Secrets::GoogleCloud::EnvLoader.perform!
32
+ end
33
+
34
+ def load_secrets_from_mounted_files
35
+ OnContainer::Secrets::MountedFiles::EnvLoader.perform!
36
+ end
37
+
38
+ def process_url_variables
39
+ OnContainer::Secrets::UrlVariableProcessor.perform!
40
+ end
41
+ end
42
+ end
43
+ end
@@ -17,9 +17,13 @@ module OnContainer
17
17
  def env_keys?
18
18
  env_keys.any?
19
19
  end
20
+
21
+ def self.secret_manager?
22
+ defined?(Google::Cloud::SecretManager) == 'constant'
23
+ end
20
24
 
21
25
  def secret_manager?
22
- defined?(Google::Cloud::SecretManager) == 'constant'
26
+ self.class.secret_manager?
23
27
  end
24
28
 
25
29
  def perform!
@@ -34,4 +38,4 @@ module OnContainer
34
38
  end
35
39
  end
36
40
  end
37
- end
41
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/core_ext/object'
5
+ require 'on_container/common/safe_performable'
6
+
7
+ module OnContainer
8
+ module Secrets
9
+ module MountedFiles
10
+ class EnvLoader
11
+ include OnContainer::Common::SafePerformable
12
+
13
+ def perform!
14
+ setup_secrets_path
15
+ scan_secrets_path_for_files
16
+ load_secret_files_to_env_vars
17
+ end
18
+
19
+ def secrets_path
20
+ @secrets_path ||= ENV.fetch('SECRETS_PATH', '/run/secrets')
21
+ end
22
+
23
+ def secret_mounted_file_paths
24
+ @secret_mounted_file_paths ||= Dir["#{secrets_path}/**/*"]
25
+ .map { |path| Pathname.new(path) }
26
+ .select(&:file?)
27
+ end
28
+
29
+ private
30
+
31
+ alias setup_secrets_path secrets_path
32
+ alias scan_secrets_path_for_files secret_mounted_file_paths
33
+
34
+ def load_secret_files_to_env_vars
35
+ return if @already_loaded
36
+
37
+ secret_mounted_file_paths
38
+ .each { |file_path| load_secret_file_to_env_var(file_path) }
39
+
40
+ @already_loaded = true
41
+ end
42
+
43
+ def load_secret_file_to_env_var(file_path)
44
+ env_var_name = file_path.basename('.*').to_s.upcase
45
+
46
+ # Skip if variable is already set - already-set variables have
47
+ # precedence over the secret files:
48
+ return if ENV.key?(env_var_name) && ENV[env_var_name].present?
49
+
50
+ contents = file_path.read.strip
51
+
52
+ # TODO: Do not load if content has null bytes
53
+ ENV[env_var_name] = file_path.read.strip
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'on_container/common/safe_performable'
4
+
5
+ module OnContainer
6
+ module Secrets
7
+ #= UrlVariableProcessor
8
+ #
9
+ # For each *_URL environment variable where there's also a *_(USER|USERNAME)
10
+ # or *_(PASS|PASSWORD), updates the URL environment variable with the given
11
+ # credentials. For example:
12
+ #
13
+ # DATABASE_URL: postgres://postgres:5432/demo_production
14
+ # DATABASE_USERNAME: lalito
15
+ # DATABASE_PASSWORD: lepass
16
+ #
17
+ # Results in the following updated DATABASE_URL:
18
+ # DATABASE_URL = postgres://lalito:lepass@postgres:5432/demo_production
19
+ class UrlVariableProcessor
20
+ include OnContainer::Common::SafePerformable
21
+
22
+ def perform!
23
+ require_uri_module if url_keys?
24
+ process_credential_keys
25
+ end
26
+
27
+ def url_keys
28
+ @url_keys ||= ENV.keys.select { |key| key =~ /_URL/ }
29
+ end
30
+
31
+ def url_keys?
32
+ url_keys.any?
33
+ end
34
+
35
+ private
36
+
37
+ def process_credential_keys
38
+ url_keys.each { |url_key| process_credential_keys_for(url_key) }
39
+ end
40
+
41
+ def require_uri_module
42
+ require 'uri'
43
+ end
44
+
45
+ def credential_keys_for(url_key)
46
+ credential_pattern_string = url_key
47
+ .gsub('_URL', '_(USER(NAME)?|PASS(WORD)?)')
48
+
49
+ credential_pattern = Regexp.new "\\A#{credential_pattern_string}\\z"
50
+ ENV.keys.select { |key| key =~ credential_pattern }
51
+ end
52
+
53
+ def process_credential_keys_for(url_key)
54
+ return unless (credential_keys = credential_keys_for(url_key)).any?
55
+
56
+ uri = URI(ENV[url_key])
57
+
58
+ # Reverse sorting will place "*_USER" before "*_PASS":
59
+ credential_keys.sort.reverse.each do |credential_key|
60
+ credential_value = URI.encode_www_form_component ENV[credential_key]
61
+ case credential_key
62
+ when /USER/ then uri.user = credential_value
63
+ when /PASS/ then uri.password = credential_value
64
+ end
65
+ end
66
+
67
+ ENV[url_key] = uri.to_s
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OnContainer
4
- VERSION = '0.0.11'
4
+ VERSION = '0.0.12'
5
5
  end
data/on_container.gemspec CHANGED
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.bindir = 'exe'
25
25
  spec.require_paths = ['lib']
26
26
 
27
+ spec.add_runtime_dependency 'activesupport', '>= 4'
27
28
  spec.add_development_dependency 'bundler', '~> 2.1'
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: on_container
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Quintanilla
@@ -10,6 +10,20 @@ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2021-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -49,9 +63,12 @@ files:
49
63
  - lib/on_container/dev/setup_ops.rb
50
64
  - lib/on_container/load_env_secrets.rb
51
65
  - lib/on_container/ops/service_connection_checks.rb
66
+ - lib/on_container/secrets/env_loader.rb
52
67
  - lib/on_container/secrets/google_cloud/env_loader.rb
53
68
  - lib/on_container/secrets/google_cloud/fetcher.rb
54
69
  - lib/on_container/secrets/google_cloud/service_base.rb
70
+ - lib/on_container/secrets/mounted_files/env_loader.rb
71
+ - lib/on_container/secrets/url_variable_processor.rb
55
72
  - lib/on_container/version.rb
56
73
  - on_container.gemspec
57
74
  homepage: https://github.com/IcaliaLabs/on-container-for-ruby