configuration_service 2.2.0 → 2.3.1

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
  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