on_container 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
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