configuration_service 2.2.0 → 2.3.1

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
  SHA1:
3
- metadata.gz: d695abf3843bb642d1bfed73e61ad6be4675007f
4
- data.tar.gz: 23ff9de0ec5d4911aa5f83a96919527ed53f115a
3
+ metadata.gz: 5547c75cb69883e74a7327fe86914d6b9294b3db
4
+ data.tar.gz: b53686e2e3557309781fa691081fbbde1682b2c7
5
5
  SHA512:
6
- metadata.gz: 958979a72b6b19483a5983b8da46e1e6c01ce9febd67c0fac74c0a42128117d7218bcfd178a443fcadd3b214b4dc4d34e059e5f5183ffc23ee14b6632be28132
7
- data.tar.gz: dec28262702b779b8ec85b453f1441dcb006475e68b859182772074f92ebbc6d2d0e47229659f7b17cccb9f706570ca229d649935b0b625b4e7dc05c5a76e4f5
6
+ metadata.gz: f925edffb72981b4d10ebfb4330d89ff4065361a9091bf41f8aa05107a25c602c7ef22a2598cae704c2d40c55e9aedf06d7ce94e606b4ca98fe91ce6d3549425
7
+ data.tar.gz: bd35e4fdf79ea9cfe602c51b74a3fa24dca6318fd9975b2e61a2728bd8441ea13df555fd47ce1d3b2d91bf212265d985cc9cf747af57067239e4abc4d29c01a3
data/.gemspec CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.required_ruby_version = '>= 2.1'
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.7"
22
24
  spec.add_development_dependency "rake", "~> 11.1"
23
25
  spec.add_development_dependency "cucumber", "~> 2.0"
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
- - 1.9.3
5
- - 2.0.0
6
- - 2.2.3
4
+ - 2.1.5
5
+ - 2.3.0
@@ -69,12 +69,24 @@ module ConfigurationService
69
69
  end
70
70
 
71
71
  ##
72
- # Does nothing
72
+ # Deletes the internal copy of the +source+
73
73
  #
74
- # The source is assumed to be secure. Sources such as the process +ENV+ and (on JRuby) system properties
74
+ # Called by the {ConfigurationService::Factory} after the client is created,
75
+ # to prevent in-process compromise of the context (e.g. by an exception handler
76
+ # that dumps the environment in a web application).
77
+ #
78
+ # The original +source+ remains untouched. It is assumed to be secure. However, subclasses such as
79
+ # {ConfigurationService::Factory::EnvironmentContext} should scrub sources as well.
80
+ #
81
+ # Sources such as the process +ENV+ and (on JRuby) system properties
75
82
  # should not be used with this class; instead, they should be accessed through {ConfigurationService::Factory::EnvironmentContext}.
83
+ # Temporary YAML file sources should be accessed through {ConfigurationService::Factory::YamlFileContext}.
84
+ #
85
+ # Attempts to read context properties after scrubbing will raise a +SecurityError+.
76
86
  #
77
87
  def scrub!
88
+ @env = Hash.new { raise SecurityError, "can't access scrubbed environment context" }
89
+ nil
78
90
  end
79
91
 
80
92
  end
@@ -1,4 +1,5 @@
1
- require_relative "environment_context/backward_compatibility"
1
+ require "configuration_service/factory/context"
2
+ require "configuration_service/factory/environment_context_backward_compatibility"
2
3
 
3
4
  module ConfigurationService
4
5
 
@@ -13,12 +14,12 @@ module ConfigurationService
13
14
  #
14
15
  # Prior to version 2.2.0, this class provided factory functionality.
15
16
  # Use of this class as a factory is deprecated, supported through the
16
- # {ConfigurationService::Factory::EnvironmentContext::BackwardCompatibility} module.
17
+ # {ConfigurationService::Factory::EnvironmentContextBackwardCompatibility} module.
17
18
  # Consumers should use {ConfigurationService::Factory} instead.
18
19
  #
19
- class EnvironmentContext
20
+ class EnvironmentContext < Context
20
21
 
21
- include BackwardCompatibility
22
+ include EnvironmentContextBackwardCompatibility
22
23
 
23
24
  attr_reader :prefix
24
25
 
@@ -51,44 +52,40 @@ module ConfigurationService
51
52
  # the environment variable is preferred.
52
53
  #
53
54
  def initialize(sources = default_sources, prefix = DEFAULT_PREFIX)
54
- @env = EnvDict.new(sources, prefix)
55
- end
56
-
57
- ##
58
- # @see ConfigurationService::Factory::Context#identifier
59
- def identifier
60
- @env[:identifier]
61
- end
62
-
63
- ##
64
- # @see ConfigurationService::Factory::Context#token
65
- def token
66
- @env[:token]
67
- end
68
-
69
- ##
70
- # @see ConfigurationService::Factory::Context#provider_id
71
- def provider_id
72
- @env[:provider]
73
- end
74
-
75
- ##
76
- # @see ConfigurationService::Factory::Context#provider_config
77
- def provider_config
78
- @env.subslice(:provider)
55
+ @sources = [sources].flatten
56
+ @prefix = prefix
57
+ @scrub_keys = []
58
+ env = Hash.new { |_, k| raise KeyError, "missing environment variable #{k}" }
59
+
60
+ merged_sources = @sources.inject { |m, e| m.merge(e) }
61
+ {
62
+ to_envvar("IDENTIFIER") => :identifier,
63
+ to_envvar("TOKEN") => :token,
64
+ to_envvar("PROVIDER") => :provider_id
65
+ }.each do |envvar, key|
66
+ env[key] = merged_sources[envvar]
67
+ @scrub_keys << envvar
68
+ end
69
+ config_prefix = to_envvar("PROVIDER_")
70
+ env[:provider_config] = merged_sources
71
+ .select { |envvar| envvar.start_with?(config_prefix) && @scrub_keys << envvar }
72
+ .map { |envvar, value| [envvar.sub(config_prefix, "").downcase.intern, value] }
73
+ .to_h
74
+ @env = SymbolicAccessWrapper.new(env)
79
75
  end
80
76
 
81
77
  ##
82
- # Scrub sources
83
- #
84
- # Called by the {ConfigurationService::Factory} after the client is created,
85
- # to prevent in-process compromise of the context (e.g. by an exception handler
86
- # that dumps the environment in a web application).
78
+ # Scrub +sources+
87
79
  #
88
80
  # Every property that matches the prefix is removed from all sources.
89
81
  #
82
+ # @see ConfigurationService::Factory::Context#scrub!
83
+ #
90
84
  def scrub!
91
- @env.scrub!
85
+ @scrub_keys.each do |k|
86
+ @sources.each { |s| s.delete(k) }
87
+ end
88
+ super
92
89
  end
93
90
 
94
91
  private
@@ -97,6 +94,12 @@ module ConfigurationService
97
94
  (RUBY_PLATFORM == "java" ? [java.lang.System.properties, ENV] : ENV)
98
95
  end
99
96
 
97
+ def to_envvar(k = "")
98
+ s = k.to_s.upcase
99
+ (@prefix and @prefix.size > 0) ? "#{@prefix}_#{s}" : s
100
+ end
101
+
102
+
100
103
  end
101
104
 
102
105
  end
@@ -0,0 +1,75 @@
1
+ module ConfigurationService
2
+
3
+ module Factory
4
+
5
+ ##
6
+ # Support {ConfigurationService::Factory::EnvironmentContext}'s deprecated use as a factory
7
+ #
8
+ # New code should use {ConfigurationService::Factory} instead.
9
+ #
10
+ module EnvironmentContextBackwardCompatibility
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ ##
17
+ # Create a configuration service bootstrapped with environmental configuration
18
+ #
19
+ # The environment is scanned for {EnvironmentContext#prefix} matches, within which the following variables are used:
20
+ #
21
+ # [IDENTIFIER] the unique identity of the configuration data
22
+ # (see {ConfigurationService::Base#initialize})
23
+ # [TOKEN] authorization token for the identified configuration data
24
+ # (see {ConfigurationService::Base#initialize})
25
+ # [PROVIDER] the unique identity of the service provider
26
+ # (see {ConfigurationService::ProviderRegistry})
27
+ # [PROVIDER_*] configuration options for the service provider
28
+ # (see service provider documentation)
29
+ #
30
+ # On JRuby, system properties are also scanned. Where a system property and environment variable of the
31
+ # same name exist, the environment variable is preferred.
32
+ #
33
+ # The service provider class is fetched from the {ConfigurationService::ProviderRegistry} using +PROVIDER+.
34
+ # A service provider instance is then constructed with a dictionary of the +PROVIDER_*+ variables,
35
+ # in which the keys are the name of the variable without +PROVIDER_+, downcased and intern'd.
36
+ #
37
+ # Then a service {ConfigurationService::Base} is constructed with the +IDENTIFIER+, +TOKEN+ and service provider instance.
38
+ #
39
+ # And finally, the environment is scrubbed of the variables used, to protect them from accidental exposure
40
+ # (e.g. in an exception handler that prints the environment). On JRuby, system properties are scrubbed of variables used as well,
41
+ # regardless of whether they were overridden by environment variables.
42
+ #
43
+ # @return [ConfigurationService::Base] the configuration service instance created
44
+ # @raise [ProviderNotFoundError] if no service provider has been registered with the name given by +PROVIDER+
45
+ #
46
+ # @deprecated Use {ConfigurationService::Factory} instead.
47
+ #
48
+ def create
49
+ $stderr.puts "warning: ConfigurationService::Factory::EnvironmentContext#create is deprecated: use ConfigurationService::Factory instead"
50
+ ConfigurationService::Factory.create_client(self)
51
+ end
52
+
53
+ module ClassMethods
54
+
55
+ ##
56
+ # Return a configuration service bootstrapped with environmental configuration
57
+ #
58
+ # Instantiates a new factory with the process +ENV+ and the {EnvironmentContext::DEFAULT_PREFIX}
59
+ # and uses it to create a configuration service.
60
+ #
61
+ # @see ConfigurationService::Factory::EnvironmentContextBackwardCompatibility#create
62
+ #
63
+ # @deprecated Use {ConfigurationService::Factory} instead.
64
+ #
65
+ def create
66
+ new.create
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,39 @@
1
+ require "yaml"
2
+
3
+ require "configuration_service/factory/context"
4
+
5
+ module ConfigurationService
6
+
7
+ module Factory
8
+
9
+ class YamlFileContext < Context
10
+
11
+ ##
12
+ # A factory context for a YAML file
13
+ #
14
+ # Note that {#scrub!} deletes the file. This context is intended to be used with
15
+ # a temporary file created by a bootstrapper.
16
+ #
17
+ # For a context for the process +ENV+ and (on JRuby) system properties,
18
+ # see {ConfigurationService::Factory::EnvironmentContext}.
19
+ #
20
+ def initialize(filename)
21
+ @filename = File.expand_path(filename)
22
+ @env = SymbolicAccessWrapper.new(YAML.load_file(@filename))
23
+ end
24
+
25
+ ##
26
+ # Delete +filename+
27
+ #
28
+ # @see ConfigurationService::Factory::Context#scrub!
29
+ #
30
+ def scrub!
31
+ File.unlink(@filename) if File.exist?(@filename)
32
+ super
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -1,5 +1,5 @@
1
1
  module ConfigurationService
2
2
 
3
- VERSION = "2.2.0"
3
+ VERSION = "2.3.1"
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configuration_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sheldon Hearn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-13 00:00:00.000000000 Z
11
+ date: 2016-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,8 +115,8 @@ files:
115
115
  - lib/configuration_service/factory/context.rb
116
116
  - lib/configuration_service/factory/context/symbolic_access_wrapper.rb
117
117
  - lib/configuration_service/factory/environment_context.rb
118
- - lib/configuration_service/factory/environment_context/backward_compatibility.rb
119
- - lib/configuration_service/factory/environment_context/env_dict.rb
118
+ - lib/configuration_service/factory/environment_context_backward_compatibility.rb
119
+ - lib/configuration_service/factory/yaml_file_context.rb
120
120
  - lib/configuration_service/provider.rb
121
121
  - lib/configuration_service/provider/broken.rb
122
122
  - lib/configuration_service/provider/stub.rb
@@ -142,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - ">="
144
144
  - !ruby/object:Gem::Version
145
- version: '0'
145
+ version: '2.1'
146
146
  required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  requirements:
148
148
  - - ">="
@@ -155,3 +155,4 @@ signing_key:
155
155
  specification_version: 4
156
156
  summary: Configuration service
157
157
  test_files: []
158
+ has_rdoc:
@@ -1,89 +0,0 @@
1
- module ConfigurationService
2
-
3
- module Factory
4
-
5
- class EnvironmentContext
6
-
7
- ##
8
- # Support {ConfigurationService::Factory::EnvironmentContext}'s deprecated use as a factory
9
- #
10
- # New code should use {ConfigurationService::Factory} instead.
11
- #
12
- module BackwardCompatibility
13
-
14
- def self.included(base)
15
- base.extend(ClassMethods)
16
- end
17
-
18
- ##
19
- # Create a configuration service bootstrapped with environmental configuration
20
- #
21
- # The environment is scanned for {#prefix} matches, within which the following variables are used:
22
- #
23
- # [IDENTIFIER] the unique identity of the configuration data
24
- # (see {ConfigurationService::Base#initialize})
25
- # [TOKEN] authorization token for the identified configuration data
26
- # (see {ConfigurationService::Base#initialize})
27
- # [PROVIDER] the unique identity of the service provider
28
- # (see {ConfigurationService::ProviderRegistry})
29
- # [PROVIDER_*] configuration options for the service provider
30
- # (see service provider documentation)
31
- #
32
- # On JRuby, system properties are also scanned. Where a system property and environment variable of the
33
- # same name exist, the environment variable is preferred.
34
- #
35
- # The service provider class is fetched from the {ConfigurationService::ProviderRegistry} using +PROVIDER+.
36
- # A service provider instance is then constructed with a dictionary of the +PROVIDER_*+ variables,
37
- # in which the keys are the name of the variable without +PROVIDER_+, downcased and intern'd.
38
- #
39
- # Then a service {ConfigurationService::Base} is constructed with the +IDENTIFIER+, +TOKEN+ and service provider instance.
40
- #
41
- # And finally, the environment is scrubbed of the variables used, to protect them from accidental exposure
42
- # (e.g. in an exception handler that prints the environment). On JRuby, system properties are scrubbed of variables used as well,
43
- # regardless of whether they were overridden by environment variables.
44
- #
45
- # @return [ConfigurationService::Base] the configuration service instance created
46
- # @raise [ProviderNotFoundError] if no service provider has been registered with the name given by +PROVIDER+
47
- #
48
- # @deprecated Use {ConfigurationService::Factory} instead.
49
- #
50
- def create
51
- ConfigurationService.new(@env[:identifier], @env[:token], provider).tap do
52
- scrub!
53
- end
54
- end
55
-
56
- module ClassMethods
57
-
58
- ##
59
- # Return a configuration service bootstrapped with environmental configuration
60
- #
61
- # Instantiates a new factory with the process +ENV+ and the {DEFAULT_PREFIX} and uses it to create a configuration service.
62
- #
63
- # @see ConfigurationService::Factory::EnvironmentContext::BackwardCompatibility#create
64
- #
65
- # @deprecated Use {ConfigurationService::Factory} instead.
66
- #
67
- def create
68
- new.create
69
- end
70
-
71
- end
72
-
73
- private
74
-
75
- def provider
76
- provider_id = @env[:provider]
77
- provider_config = @env.subslice(:provider)
78
- provider_class = ConfigurationService::ProviderRegistry.instance.lookup(provider_id)
79
- provider_class or raise ProviderNotFoundError, "provider not registered: #{provider_id}"
80
- provider_class.new(provider_config)
81
- end
82
-
83
- end
84
-
85
- end
86
-
87
- end
88
-
89
- end
@@ -1,108 +0,0 @@
1
- module ConfigurationService
2
-
3
- module Factory
4
-
5
- class EnvironmentContext
6
-
7
- class EnvDict < Hash
8
-
9
- def initialize(sources, *path)
10
- @sources = sources.is_a?(Array) ? sources : [ sources ]
11
- @env = @sources.inject { |m, e| m.merge(e) }
12
- @path = build_path(*path)
13
-
14
- env_keys.each do |k|
15
- self.store(symbolic_key(k), @env[k])
16
- end
17
-
18
- self.default_proc = envdict_default_proc
19
- end
20
-
21
- def subslice(key)
22
- EnvDict.new(@env, @path, key).tap do |s|
23
- (@slices ||= []) << s
24
- end
25
- end
26
-
27
- def scrub!
28
- @path or raise RuntimeError, "refusing to scrub without path"
29
-
30
- scrub_env!
31
- scrub_slices!
32
- scrub_self!
33
-
34
- @scrubbed = true
35
- end
36
-
37
- private
38
-
39
- def envdict_default_proc
40
- proc do |_, key|
41
- assert_not_scrubbed!
42
- try_string(key) or raise_key_error(key)
43
- end
44
- end
45
-
46
- def try_string(k)
47
- if (skey = k.intern rescue false) and self.include?(skey)
48
- self.fetch(skey)
49
- end
50
- end
51
-
52
- def raise_key_error(k)
53
- envar = build_path(@path, k.to_s).upcase
54
- raise KeyError, "missing environment variable #{envar}"
55
- end
56
-
57
- def env_keys(env = @env)
58
- env.keys.select { |k| under_path?(k) }
59
- end
60
-
61
- def under_path?(k)
62
- !!symbolic_key(k)
63
- end
64
-
65
- def symbolic_key(k)
66
- prefix = build_path(@path, "")
67
- s = k.downcase
68
- if s.slice!(prefix) and !s.empty?
69
- s.intern
70
- end
71
- end
72
-
73
- def build_path(*path)
74
- path = path.compact
75
- if path.empty?
76
- nil
77
- else
78
- path.map { |p| p.to_s.downcase }.join("_")
79
- end
80
- end
81
-
82
- def assert_not_scrubbed!
83
- !@scrubbed or raise SecurityError, "can't access scrubbed environment dictionary"
84
- end
85
-
86
- def scrub_env!
87
- @sources.each do |env|
88
- env_keys(env).each { |k| env.delete(k) }
89
- end
90
- end
91
-
92
- def scrub_slices!
93
- @slices.each { |s| s.scrub! } if @slices
94
- end
95
-
96
- def scrub_self!
97
- self.keys.each do |k|
98
- self.delete(k)
99
- end
100
- end
101
-
102
- end
103
-
104
- end
105
-
106
- end
107
-
108
- end