configuration_service 2.3.1 → 3.0.0

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: 5547c75cb69883e74a7327fe86914d6b9294b3db
4
- data.tar.gz: b53686e2e3557309781fa691081fbbde1682b2c7
3
+ metadata.gz: e4a468a73fdaa5ac4d860611af3fe7f60bbb8533
4
+ data.tar.gz: 1c7cd9e09bf66113b28950938b00299a420d0cc4
5
5
  SHA512:
6
- metadata.gz: f925edffb72981b4d10ebfb4330d89ff4065361a9091bf41f8aa05107a25c602c7ef22a2598cae704c2d40c55e9aedf06d7ce94e606b4ca98fe91ce6d3549425
7
- data.tar.gz: bd35e4fdf79ea9cfe602c51b74a3fa24dca6318fd9975b2e61a2728bd8441ea13df555fd47ce1d3b2d91bf212265d985cc9cf747af57067239e4abc4d29c01a3
6
+ metadata.gz: 7475e17b49bd4430c01850923eebd2ad3e4d1b5cf764e2c1f16d21552cefd5d854cf1c963edf2942568ad42b2d9917db052e0bf223f149fe27815878c97f90fc
7
+ data.tar.gz: f024394e9df43fb5dfdc026c5cef4132f1529a85ae075af7c8205a264acb8d119f64eda80d646fc20e5950e5a5d9917276efcc5e88a0a9527c9320ca98711a2d
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
2
  --require spec_helper
3
+ --format documentation
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ configuration_service
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.3.0
data/Rakefile CHANGED
@@ -7,6 +7,18 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  desc "Test the stub test orchestrator"
9
9
  task :test => :spec do
10
+
10
11
  ENV["TEST_ORCHESTRATION_PROVIDER"] ||= "stub"
11
12
  sh %{bundle exec cucumber}
12
13
  end
14
+
15
+ namespace :test do
16
+ desc "Test includes"
17
+ task :includes do
18
+ sh %{cd lib && for i in configuration_service.rb $(find configuration_service -name '*.rb'); do
19
+ i=${i%.rb}
20
+ ruby -e '$LOAD_PATH.unshift("."); '"require '$i'; "'exit 0' || break
21
+ done}
22
+ end
23
+ end
24
+
@@ -1,46 +1,38 @@
1
1
  @authorization @authorize
2
2
  Feature: Authorization
3
- In order to ensure I am who I say I am
4
- As a CS Client
5
- I want to be authenticated
6
-
7
- Scenario: Token request with no credentials
8
- Given I have no credentials
9
- When I request a token
10
- Then I should not receive a token
11
-
12
- Scenario: Token request with invalid credentials
13
- Given I have invalid credentials
14
- When I request a token
15
- Then I should not receive a token
16
-
17
- Scenario: Token request with valid credentials
18
- Given I have valid credentials
19
- When I request a token
20
- Then I should receive a token
21
-
22
- Scenario: Allowed request
23
- Given I have a token that allows requesting configurations
24
- When I request a configuration
3
+ As the configuration service
4
+ I want to enforce authorization policies
5
+ In order to regulate client actions
6
+
7
+ Scenario: Allowed consumption
8
+ Given the specified configuration exists
9
+ And I am allowed to request configuration
10
+ When I request configuration data
25
11
  Then I should be allowed to request configurations
26
12
 
27
- Scenario: Denied request
28
- Given I have a token that does not allow requesting configurations
29
- When I request a configuration
13
+ Scenario: Denied consumption
14
+ Given I am not allowed to request configuration
15
+ When I request configuration data
30
16
  Then I should be notified that my request is 'not authorized'
31
17
 
32
18
  Scenario: Allowed publication
33
- Given I have a token that allows publishing configurations
34
- When I request publication of a configuration
19
+ Given I am allowed to publish configurations
20
+ When I request publication of the configuration data
35
21
  Then I should be allowed to publish configurations
36
22
 
37
23
  Scenario: Denied publication
38
- Given I have a token that does not allow publishing configurations
39
- When I request publication of a configuration
24
+ Given I am not allowed to publish configurations
25
+ When I request publication of the configuration data
40
26
  Then I should be notified that my request is 'not authorized'
41
27
 
28
+ Scenario: Allowed to create credentials for consuming configuration
29
+ Given the specified configuration exists
30
+ And I am allowed to authorize consumption of configuration
31
+ When I authorize consumption of the configuration
32
+ Then I receive credentials that only allow consumption of the configuration
33
+
42
34
  Scenario: Token-less request
43
35
  Given I do not have a token
44
- When I request a configuration
36
+ When I request configuration data
45
37
  Then I should be notified that my request is 'not authorized'
46
38
 
@@ -5,16 +5,14 @@ Feature: Consuming configuration data
5
5
  I want to request access to configuration data
6
6
 
7
7
  Scenario: Metadata-free hit
8
- Given an identifier
9
- And no meta data filter
10
- And configuration data at the index is present
8
+ Given I am allowed to request configuration
9
+ And the specified configuration exists
11
10
  When I request configuration data
12
- Then the configuration data should be returned for the identifier
11
+ Then the specified configuration should be returned
13
12
 
14
13
  Scenario: Metadata-free miss
15
- Given an identifier
16
- And no meta data filter
17
- And configuration data at the index is not present
14
+ Given I am allowed to request configuration
15
+ And the specified configuration does not exist
18
16
  When I request configuration data
19
17
  Then I should receive a 'not found' indication
20
18
 
@@ -37,7 +35,8 @@ Feature: Consuming configuration data
37
35
  Then I should receive a 'no match' indication
38
36
 
39
37
  Scenario: CS request failure
40
- Given a CS request failure
38
+ Given I am allowed to request configuration
39
+ And a CS request failure
41
40
  When I request configuration data
42
41
  Then I should receive a 'request failure' notification
43
42
 
@@ -5,39 +5,37 @@ Feature: Publishing configuration data
5
5
  I want to publish configuration data
6
6
 
7
7
  Scenario: Revision added to metadata
8
- Given an identifier
9
- And some configuration data
8
+ Given I am allowed to publish configurations
10
9
  When I request publication of the configuration data
11
10
  Then I receive a unique revision for my publication
12
11
  And the metadata is updated with the revision by the CS
13
12
 
14
13
  Scenario: Metadata saved with data
15
- Given an identifier
14
+ Given I am allowed to publish configurations
16
15
  And some metadata
17
- And some configuration data
18
16
  When I request publication of the configuration data
19
17
  Then the metadata is also remembered
20
18
 
21
19
  Scenario: Timestamp added to metadata
22
- Given an identifier
23
- And some metadata
24
- And some configuration data
20
+ Given I am allowed to publish configurations
25
21
  When I request publication of the configuration data
26
22
  Then the entry is timestamped
27
23
 
28
24
  Scenario: New revision for publication to existing identifier
29
- Given existing configuration data
30
- When I request publication of configuration data using the existing identifier
25
+ Given I am allowed to publish configurations
26
+ And the specified configuration exists
27
+ When I request publication of the configuration data
31
28
  Then I receive a new unique revision for the publication
32
29
 
33
30
  Scenario: Invalid data
34
- Given an identifier
31
+ Given I am allowed to publish configurations
35
32
  And invalid configuration data
36
33
  When I request publication of the configuration data
37
34
  Then I receive an 'invalid data' notification
38
35
 
39
36
  Scenario: CS publication failure
40
- Given a CS publication failure
37
+ Given I am allowed to publish configurations
38
+ And a CS publication failure
41
39
  When I request publication of the configuration data
42
40
  Then I should receive a 'publication failure' notification
43
41
 
@@ -1,32 +1,8 @@
1
- Given(/^I have no credentials$/) do
2
- pending "Use case supported by Vault command-line client"
3
- end
4
-
5
- When(/^I request a token$/) do
6
- pending "Use case supported by Vault command-line client"
7
- end
8
-
9
- Then(/^I should not receive a token$/) do
10
- pending "Use case supported by Vault command-line client"
11
- end
12
-
13
- Given(/^I have invalid credentials$/) do
14
- pending "Use case supported by Vault command-line client"
15
- end
16
-
17
- Given(/^I have valid credentials$/) do
18
- pending "Use case supported by Vault command-line client"
19
- end
20
-
21
- Then(/^I should receive a token$/) do
22
- pending "Use case supported by Vault command-line client"
23
- end
24
-
25
1
  Given(/^I do not have a token$/) do
26
2
  @test.deauthorize
27
3
  end
28
4
 
29
- Given(/^I have a token that allows requesting configurations$/) do
5
+ Given(/^I am allowed to request configuration$/) do
30
6
  @test.authorize(:requesting_configurations)
31
7
  end
32
8
 
@@ -38,7 +14,7 @@ Then(/^I should be allowed to request configurations$/) do
38
14
  expect(@test.request_allowed?).to eq true
39
15
  end
40
16
 
41
- Given(/^I have a token that does not allow requesting configurations$/) do
17
+ Given(/^I am not allowed to request configuration$/) do
42
18
  @test.authorize(:nothing)
43
19
  end
44
20
 
@@ -46,7 +22,7 @@ Then(/^I should be notified that my request is 'not authorized'$/) do
46
22
  expect(@test.request_allowed?).to eq false
47
23
  end
48
24
 
49
- Given(/^I have a token that allows publishing configurations$/) do
25
+ Given(/^I am allowed to publish configurations$/) do
50
26
  @test.authorize(:publishing_configurations)
51
27
  end
52
28
 
@@ -58,6 +34,19 @@ Then(/^I should be allowed to publish configurations$/) do
58
34
  expect(@test.request_allowed?).to eq true
59
35
  end
60
36
 
61
- Given(/^I have a token that does not allow publishing configurations$/) do
37
+ Given(/^I am not allowed to publish configurations$/) do
62
38
  @test.authorize(:requesting_configurations)
63
39
  end
40
+
41
+ Given(/^I am allowed to authorize consumption of configuration$/) do
42
+ @test.authorize(:admin)
43
+ end
44
+
45
+ When(/^I authorize consumption of the configuration$/) do
46
+ @test.authorize_consumption
47
+ end
48
+
49
+ Then(/^I receive credentials that only allow consumption of the configuration$/) do
50
+ expect(@test.credentials_allow_consumption?).to eq true
51
+ expect(@test.credentials_allow_publication?).to eq false
52
+ end
@@ -6,19 +6,18 @@ Then(/^I should receive a 'no match' indication$/) do
6
6
  expect(@test.request_not_matched?).to eq true
7
7
  end
8
8
 
9
- Then(/^the configuration data should be returned for the identifier$/) do
9
+ Then(/^the specified configuration should be returned$/) do
10
10
  expect(@test.configuration_found_for_identifier?).to eq true
11
11
  end
12
12
 
13
13
  Given(/^no meta data filter$/) do
14
14
  end
15
15
 
16
- Given(/^configuration data at the index is present$/) do
16
+ Given(/^the specified configuration exists$/) do
17
17
  @test.given_existing_configuration
18
18
  end
19
19
 
20
20
  When(/^I request configuration data$/) do
21
- @test.authorize(:requesting_configurations)
22
21
  @test.request_configuration
23
22
  end
24
23
 
@@ -26,7 +25,7 @@ Then(/^the configuration data should be returned for the index and meta data fil
26
25
  pending "Searching with metadata filters not yet supported"
27
26
  end
28
27
 
29
- Given(/^configuration data at the index is not present$/) do
28
+ Given(/^the specified configuration does not exist$/) do
30
29
  @test.given_missing_configuration
31
30
  end
32
31
 
@@ -1,11 +1,4 @@
1
- Given(/^an identifier$/) do
2
- end
3
-
4
- Given(/^some configuration data$/) do
5
- end
6
-
7
1
  When(/^I request publication of the configuration data$/) do
8
- @test.authorize(:publishing_configurations)
9
2
  @test.publish_configuration
10
3
  end
11
4
 
@@ -33,11 +26,6 @@ Given(/^existing configuration data$/) do
33
26
  @test.given_existing_configuration
34
27
  end
35
28
 
36
- When(/^I request publication of configuration data using the existing identifier$/) do
37
- @test.authorize(:publishing_configurations)
38
- @test.publish_configuration
39
- end
40
-
41
29
  Then(/^I receive a new unique revision for the publication$/) do
42
30
  expect(@test.published_revision).to_not eq @test.existing_revision
43
31
  end
@@ -1,16 +1,17 @@
1
- require "configuration_service/utils"
1
+ require "configuration_service/client"
2
2
 
3
3
  module ConfigurationService
4
4
  class AdminClient
5
5
 
6
6
  ##
7
+ # @deprecated use ConfigurationService::Client instead
7
8
  # @param [String] token
8
9
  # @param [String] provider
9
10
  # @return [ConfigurationService::AdminClient] object
10
11
  #
11
12
  def initialize(token, provider)
12
- @token = token
13
- @provider = provider
13
+ warn "[DEPRECATION] 'ConfigurationService::AdminClient' is deprecated. Please use 'ConfigurationService::Client'."
14
+ @client = ConfigurationService::Client.new(token, provider)
14
15
  end
15
16
 
16
17
  ##
@@ -19,8 +20,7 @@ module ConfigurationService
19
20
  # @raise [ConfigurationService::ConfigurationNotFoundError]
20
21
  #
21
22
  def request_configuration(identifier)
22
- @provider.request_configuration(identifier, @token) or
23
- raise ConfigurationNotFoundError, "configuration not found for identifier: #{identifier}"
23
+ @client.request_configuration(identifier)
24
24
  end
25
25
 
26
26
  ##
@@ -31,14 +31,9 @@ module ConfigurationService
31
31
  # @raise [ConfigurationaService::Error] if data or metadata is not a hash
32
32
  #
33
33
  def publish_configuration(identifier, data, metadata = {})
34
- Utils.dictionary?(data) or raise ConfigurationService::Error, "data must be a dictionary"
35
- Utils.dictionary?(metadata) or raise ConfigurationService::Error, "metadata must be a dictionary"
36
-
37
- metadata = Utils.decorate(metadata)
38
- configuration = Configuration.new(identifier, data, metadata)
39
- @provider.publish_configuration(configuration, @token)
34
+ @client.publish_configuration(identifier, data, metadata)
40
35
  end
41
-
36
+
42
37
  end
43
38
 
44
39
  end
@@ -1,5 +1,4 @@
1
- require "securerandom"
2
- require "configuration_service/utils"
1
+ require "configuration_service/client"
3
2
 
4
3
  module ConfigurationService
5
4
 
@@ -15,6 +14,8 @@ module ConfigurationService
15
14
  ##
16
15
  # Creates a new configuration service API instance
17
16
  #
17
+ # @deprecated use ConfigurationService::Client instead
18
+ #
18
19
  # @param [String] identifier
19
20
  # the unique identity of some configuration data and its associated metadata.
20
21
  # It might be the name of a service or service component. It might include an environment label
@@ -30,9 +31,9 @@ module ConfigurationService
30
31
  # a configured service provider instance, to which requests will be delegated.
31
32
  #
32
33
  def initialize(identifier, token, provider)
34
+ warn "[DEPRECATION] 'ConfigurationService::Base' is deprecated. Please use 'ConfigurationService::Client'."
33
35
  @identifier = identifier
34
- @token = token
35
- @provider = provider
36
+ @client = ConfigurationService::Client.new(token, provider)
36
37
  end
37
38
 
38
39
  ##
@@ -45,8 +46,7 @@ module ConfigurationService
45
46
  # @raise [ConfigurationService::Error] if the request failed
46
47
  #
47
48
  def request_configuration
48
- @provider.request_configuration(@identifier, @token) or
49
- raise ConfigurationNotFoundError, "configuration not found for identifier: #{@identifier}"
49
+ @client.request_configuration(@identifier)
50
50
  end
51
51
 
52
52
  ##
@@ -70,13 +70,8 @@ module ConfigurationService
70
70
  # @return [ConfigurationService::Configuration] object containing the configuration data, decorated metadata and identifier
71
71
  # @raise [ConfigurationService::Error] if publication failed
72
72
  #
73
- def publish_configuration(data, metadata = {})
74
- Utils.dictionary?(data) or raise ConfigurationService::Error, "data must be a dictionary"
75
- Utils.dictionary?(metadata) or raise ConfigurationService::Error, "metadata must be a dictionary"
76
-
77
- metadata = Utils.decorate(metadata)
78
- configuration = Configuration.new(@identifier, data, metadata)
79
- @provider.publish_configuration(configuration, @token)
73
+ def publish_configuraion(data, metadata = {})
74
+ @client.publish_configuration(@identifier, data, metadata = {})
80
75
  end
81
76
 
82
77
  end
@@ -0,0 +1,82 @@
1
+ require "configuration_service/utils"
2
+
3
+ module ConfigurationService
4
+ class Client
5
+
6
+ ##
7
+ # Creates a new instance of configuration service client
8
+ #
9
+ # @param [String] credentials
10
+ # opaque string representing authority to access the configuration data and associated metadata.
11
+ # Interpretation of the credentials is provider-dependent; it is opaque to the API and client.
12
+ # @param [Object] provider
13
+ # a configured service provider instance, to which requests will be delegated.
14
+ # @return [ConfigurationService::Client] client to interact with Configuration::Service
15
+ #
16
+ def initialize(credentials, provider)
17
+ @credentials = credentials
18
+ @provider = provider
19
+ end
20
+
21
+ ##
22
+ # Requests the configuration data and metadata
23
+ # Delegates the request to the configured +provider+.
24
+ #
25
+ # @param [String] identifier unique identifier of configuration
26
+ # @return [ConfigurationService::Configuration] object containing the configuration data, metadata and identifier
27
+ # @raise [ConfigurationService::ConfigurationNotFoundError] if no configuration was found for the configured +identifier+
28
+ # @raise [ConfigurationService::Error] if the request failed
29
+ #
30
+ def request_configuration(identifier)
31
+ @provider.request_configuration(identifier, @credentials) or
32
+ raise ConfigurationNotFoundError, "configuration not found for identifier: #{identifier}"
33
+ end
34
+
35
+ ##
36
+ # Publishes configuration data and metadata
37
+ #
38
+ # The +metadata+ is decorated with the following keys:
39
+ #
40
+ # * "timestamp" - the current UTC time in ISO8601 format
41
+ # * "revision" - a UUID for this publication
42
+ #
43
+ # Delegates the request to the configured +provider+. The provider may further decorate the +metadata+.
44
+ #
45
+ # It is recommended that both the +data+ and +metadata+ dictionaries use strings as keys,
46
+ # and that values be limited to those that can be serialized to JSON.
47
+ #
48
+ # @param [String] identifier
49
+ # unique configuration identifier
50
+ # @param [Hash] data
51
+ # dictionary of probably sensitive configuration data intended for an application, which providers are expected to secure
52
+ # @param [Hash] metadata
53
+ # dictionary of data about the configuration data, which providers are not expected to secure
54
+ # @return [ConfigurationService::Configuration] object containing the configuration data, decorated metadata and identifier
55
+ # @raise [ConfigurationService::Error] if publication failed
56
+ #
57
+ def publish_configuration(identifier, data, metadata = {})
58
+ Utils.dictionary?(data) or raise ConfigurationService::Error, "data must be a dictionary"
59
+ Utils.dictionary?(metadata) or raise ConfigurationService::Error, "metadata must be a dictionary"
60
+
61
+ metadata = Utils.decorate(metadata)
62
+ configuration = Configuration.new(identifier, data, metadata)
63
+ @provider.publish_configuration(configuration, @credentials)
64
+ end
65
+
66
+ ##
67
+ # Authorize consumption of a configuration ie. get credentials to consume configurations ie. get a token to consume configurations
68
+ #
69
+ # @param [String] identifier
70
+ # unique identifier of configuration
71
+ # @return [String] credentials allowing consumption of the provided configuration
72
+ # @raise [ConfigurationService::ConfigurationNotFoundError] if no configuration was found for the configured +identifier+
73
+ # @raise [ConfigurationService::Error] if the request failed
74
+ ##
75
+ def authorize_consumption(identifier)
76
+ @provider.authorize_consumption(identifier, @credentials) or
77
+ raise ConfigurationNotFoundError, "configuration not found for identifier: #{identifier}"
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -1,4 +1,6 @@
1
- Dir.glob(File.expand_path("../factory/**/*.rb", __FILE__), &method(:require))
1
+ require "configuration_service/factory/context"
2
+ require "configuration_service/factory/environment_context"
3
+ require "configuration_service/factory/yaml_file_context"
2
4
 
3
5
  module ConfigurationService
4
6
 
@@ -60,32 +62,17 @@ module ConfigurationService
60
62
  def self.create_client(context = EnvironmentContext.new)
61
63
  context = Context.new(context) if context.is_a?(Hash)
62
64
  provider = create_provider(context)
63
- ConfigurationService::Base.new(context.identifier, context.token, provider)
65
+ ConfigurationService::Client.new(context.token, provider)
64
66
  ensure
65
67
  context.scrub!
66
68
  end
67
69
 
68
70
  ##
69
- # Create a configuration service admin client
70
- #
71
- # @param [ConfigurationService::Factory::EnvironmentContext, ConfigurationService::Factory::Context, Hash] context
72
- # the factory context
73
- # @return [ConfigurationService::AdminClient] the configuration service admin client created
74
- #
75
- # When the +context+ is a Hash, it is wrapped in a {ConfigurationService::Factory::Context}, which does not scrub
76
- # sources after the configuration service client is created. For this reason, the process +ENV+ should never
77
- # be given as the +context+; rather give no +context+, so that the default {ConfigurationService::Factory::EnvironmentContext}
78
- # will be used to safely scrub the process +ENV+ and (on JRuby) system properties after the configuration service client is created.
79
- #
80
- # Because the {ConfigurationService::AdminClient} operates over multiple configuration identifiers,
81
- # it does not require an +identifier+ property from the context.
82
- #
71
+ # @deprecated use create_client()
72
+ # @ see create_client()
73
+ ##
83
74
  def self.create_admin_client(context = EnvironmentContext.new)
84
- context = Context.new(context) if context.is_a?(Hash)
85
- provider = create_provider(context)
86
- ConfigurationService::AdminClient.new(context.token, provider)
87
- ensure
88
- context.scrub!
75
+ create_client(context)
89
76
  end
90
77
 
91
78
  private
@@ -1,3 +1,5 @@
1
+ require "configuration_service/factory/context/symbolic_access_wrapper"
2
+
1
3
  module ConfigurationService
2
4
 
3
5
  module Factory
@@ -71,7 +71,7 @@ module ConfigurationService
71
71
  .select { |envvar| envvar.start_with?(config_prefix) && @scrub_keys << envvar }
72
72
  .map { |envvar, value| [envvar.sub(config_prefix, "").downcase.intern, value] }
73
73
  .to_h
74
- @env = SymbolicAccessWrapper.new(env)
74
+ @env = Context::SymbolicAccessWrapper.new(env)
75
75
  end
76
76
 
77
77
  ##
@@ -19,7 +19,7 @@ module ConfigurationService
19
19
  #
20
20
  def initialize(filename)
21
21
  @filename = File.expand_path(filename)
22
- @env = SymbolicAccessWrapper.new(YAML.load_file(@filename))
22
+ @env = Context::SymbolicAccessWrapper.new(YAML.load_file(@filename))
23
23
  end
24
24
 
25
25
  ##
@@ -22,7 +22,7 @@ module ConfigurationService
22
22
  :admin => 'b72b9ae7-3849-a335-67b6-administrator',
23
23
  :consumer => '64867ebd-6364-0bd3-3fda-81-requestor',
24
24
  :publisher => 'f53606cb-7f3c-4432-afe8-44-publisher',
25
- :nothing => '2972abd7-b055-4841-8ad1-4a34-nothing',
25
+ :none => '2972abd7-b055-4841-8ad1-4a34-nothing',
26
26
  } unless defined?(BUILTIN_TOKENS)
27
27
 
28
28
  ##
@@ -41,14 +41,19 @@ module ConfigurationService
41
41
  #
42
42
  # Fetches configuration from the singleton {ConfigurationService::StubStore}.
43
43
  #
44
+ # @param [String] identifier
45
+ # unique configuration identifier
46
+ # @param [String] credentials
47
+ # token for authentication and authorization
48
+ #
44
49
  # @return [ConfigurationService::Configuration] if authorized and found
45
50
  # @return [nil] if not found
46
51
  # @raise [ConfigurationService::AuthorizationError] if not authorized for the +:consumer+ role
47
52
  #
48
53
  # @see ConfigurationService::Base#request_configuration
49
54
  #
50
- def request_configuration(identifier, token)
51
- authorize_request(:consumer, token)
55
+ def request_configuration(identifier, credentials)
56
+ authorize_request(:consumer, credentials)
52
57
  data, metadata = @configurations.fetch(identifier)
53
58
  Configuration.new(identifier, data, metadata)
54
59
  rescue KeyError
@@ -58,25 +63,41 @@ module ConfigurationService
58
63
  ##
59
64
  # Publish configuration
60
65
  #
61
- # @param [ConfigurationService::Configuration] configuration configuration to publish
66
+ # @param [ConfigurationService::Configuration] configuration
67
+ # configuration to publish
68
+ # @param [String] credentials
69
+ # token to authenticate and authorize
62
70
  #
63
71
  # @return [ConfigurationService::Configuration] published configuration
64
72
  # @raise [ConfigurationService::Error] on failure.
65
73
  #
66
74
  # @see ConfigurationService::Base#publish_configuration
67
75
  #
68
- def publish_configuration(configuration, token)
69
- authorize_request(:publisher, token)
76
+ def publish_configuration(configuration, credentials)
77
+ authorize_request(:publisher, credentials)
70
78
  @configurations.store(configuration.identifier, configuration.data, configuration.metadata)
71
79
  configuration
72
80
  end
73
81
 
82
+ ##
83
+ # Authorizes consumption of configuration
84
+ #
85
+ # @param [String] identifier of configuration to be consumed
86
+ # @param [String] credentials that allow me to authorize consumption of the configuration
87
+ #
88
+ # @return [String] credentials allowing consumption of the configuration
89
+ ##
90
+ def authorize_consumption(identifier, credentials)
91
+ authorize_request(:admin, credentials)
92
+ BUILTIN_TOKENS[:consumer]
93
+ end
94
+
74
95
  private
75
96
 
76
- def authorize_request(role, token)
77
- raise AuthorizationError.new("missing token") unless token
78
- raise AuthorizationError.new("authorization failed") unless token == BUILTIN_TOKENS[role] or token == BUILTIN_TOKENS[:admin]
79
- end
97
+ def authorize_request(role, credentials)
98
+ raise AuthorizationError.new("missing credentials") unless credentials
99
+ raise AuthorizationError.new("authorization failed") unless credentials == BUILTIN_TOKENS[role] or credentials == BUILTIN_TOKENS[:admin]
100
+ end
80
101
 
81
102
  end
82
103
 
@@ -21,12 +21,13 @@ module ConfigurationService
21
21
  # * {#service_provider_configuration}
22
22
  # * {#service_provider}
23
23
  # * {#broken_service_provider}
24
- # * {#token_for}
24
+ # * {#credentials_for}
25
25
  # * {#delete_configuration}
26
26
  #
27
27
  class OrchestrationProvider
28
28
 
29
29
  ACTIVITY_ROLE_MAP = {
30
+ :admin => :admin,
30
31
  :requesting_configurations => :consumer,
31
32
  :publishing_configurations => :publisher,
32
33
  :nothing => :none # if possible, provide credentials that don't allow operations on the configuration identifier
@@ -84,7 +85,7 @@ module ConfigurationService
84
85
  #
85
86
  # Deleting non-existent configuration should not produce an error.
86
87
  # The +@identifier+ instance variable may be used to identify the configuration to delete,
87
- # but +@token+ should not be used, because it may not be sufficiently authorized.
88
+ # but +@credentials+ should not be used, because it may not be sufficiently authorized.
88
89
  #
89
90
  # @return [nil] always
90
91
  #
@@ -93,7 +94,7 @@ module ConfigurationService
93
94
  end
94
95
 
95
96
  ##
96
- # Provide a token that authorizes a role
97
+ # Provide a credentials that authorizes a role
97
98
  #
98
99
  # Valid roles are:
99
100
  #
@@ -101,27 +102,27 @@ module ConfigurationService
101
102
  # * +:publisher+
102
103
  # * +:nothing+
103
104
  #
104
- # Note that a token should be returned for +:nothing+, but the token should
105
+ # Note that a credentials should be returned for +:nothing+, but the credentials should
105
106
  # not be authorized to consume or publish to the +identifier+.
106
107
  #
107
- # @return [String] a token
108
+ # @return [String] a credentials
108
109
  #
109
- def token_for(role)
110
- raise NotImplementedError, "#{self.class} must implement token_for(role)"
110
+ def credentials_for(role)
111
+ raise NotImplementedError, "#{self.class} must implement credentials_for(role)"
111
112
  end
112
113
 
113
114
  ##
114
115
  # @see ConfigurationService::Test::Orchestrator#authorize
115
116
  #
116
117
  def authorize(role)
117
- @token = token_for(role)
118
+ @credentials = credentials_for(role)
118
119
  end
119
120
 
120
121
  ##
121
122
  # @see ConfigurationService::Test::Orchestrator#deauthorize
122
123
  #
123
124
  def deauthorize
124
- @token = nil
125
+ @credentials = nil
125
126
  end
126
127
 
127
128
  ##
@@ -178,10 +179,27 @@ module ConfigurationService
178
179
  #
179
180
  def request_configuration
180
181
  wrap_response do
181
- @requested_configuration = service.request_configuration
182
+ @requested_configuration = service.request_configuration(@identifier)
182
183
  end
183
184
  end
184
185
 
186
+ ##
187
+ # Authorize consumption of a configuration
188
+ #
189
+ # @return [String] credentials allowing consumption of a configuration
190
+ ##
191
+ def authorize_consumption
192
+ @credentials = service.authorize_consumption(@identifier)
193
+ end
194
+
195
+ def credentials_allow_consumption?
196
+ request_configuration
197
+ end
198
+
199
+ def credentials_allow_publication?
200
+ publish_configuration
201
+ end
202
+
185
203
  ##
186
204
  # Publish configuration
187
205
  #
@@ -197,9 +215,9 @@ module ConfigurationService
197
215
  def publish_configuration
198
216
  wrap_response do
199
217
  if @metadata
200
- service.publish_configuration(configuration, @metadata)
218
+ service.publish_configuration(@identifier, configuration, @metadata)
201
219
  else
202
- service.publish_configuration(configuration)
220
+ service.publish_configuration(@identifier, configuration)
203
221
  end
204
222
  end
205
223
  end
@@ -241,37 +259,39 @@ module ConfigurationService
241
259
 
242
260
  private
243
261
 
244
- def configuration
245
- @configuration ||= {"verbose" => true}
246
- end
262
+ def configuration
263
+ @configuration ||= {"verbose" => true}
264
+ end
265
+
266
+ def service
247
267
 
248
- def service
249
- provider = if @fail_next
250
- @fail_next = false
251
- broken_service_provider
252
- else
253
- service_provider
254
- end
255
- ConfigurationService.new(@identifier, @token, provider)
268
+ provider = service_provider
269
+
270
+ if @fail_next
271
+ @fail_next = false
272
+ provider = broken_service_provider
256
273
  end
274
+
275
+ ConfigurationService::Client.new(@credentials, provider)
276
+ end
257
277
 
258
- def authorized_as(role)
259
- restore_token = @token
260
- authorize(role)
261
- yield.tap do
262
- @token = restore_token
263
- end
278
+ def authorized_as(role)
279
+ restore_credentials = @credentials
280
+ authorize(role)
281
+ yield.tap do
282
+ @credentials = restore_credentials
264
283
  end
284
+ end
265
285
 
266
- def wrap_response # :nodoc:
267
- begin
268
- ConfigurationService::Test::Response::Success.new(yield)
269
- rescue ConfigurationService::ConfigurationNotFoundError
270
- ConfigurationService::Test::Response::Success.new(nil)
271
- rescue ConfigurationService::Error => e
272
- ConfigurationService::Test::Response::Failure.new(e)
273
- end
286
+ def wrap_response # :nodoc:
287
+ begin
288
+ ConfigurationService::Test::Response::Success.new(yield)
289
+ rescue ConfigurationService::ConfigurationNotFoundError
290
+ ConfigurationService::Test::Response::Success.new(nil)
291
+ rescue ConfigurationService::Error => e
292
+ ConfigurationService::Test::Response::Failure.new(e)
274
293
  end
294
+ end
275
295
 
276
296
  end
277
297
 
@@ -124,6 +124,23 @@ module ConfigurationService
124
124
  @response = @provider.publish_configuration
125
125
  end
126
126
 
127
+ ##
128
+ # Get credentials to consume a configuration
129
+ ##
130
+ def authorize_consumption
131
+ @provider.authorize_consumption
132
+ end
133
+
134
+ def credentials_allow_consumption?
135
+ @response = @provider.credentials_allow_consumption?
136
+ request_allowed?
137
+ end
138
+
139
+ def credentials_allow_publication?
140
+ @response = @provider.credentials_allow_publication?
141
+ request_allowed?
142
+ end
143
+
127
144
  ##
128
145
  # Configuration for the requested identifier was found
129
146
  #
@@ -263,10 +280,10 @@ module ConfigurationService
263
280
  #
264
281
  def bootstrapped_configuration_service_functional?
265
282
  response = begin
266
- ConfigurationService::Test::Response::Success.new(@service.request_configuration)
267
- rescue ConfigurationService::Error => e
268
- ConfigurationService::Test::Response::Failure.new(e)
269
- end
283
+ ConfigurationService::Test::Response::Success.new(@service.request_configuration('test'))
284
+ rescue ConfigurationService::Error => e
285
+ ConfigurationService::Test::Response::Failure.new(e)
286
+ end
270
287
  !response.failed?
271
288
  end
272
289
 
@@ -281,9 +298,10 @@ module ConfigurationService
281
298
 
282
299
  private
283
300
 
284
- def role_for(activity)
285
- ConfigurationService::Test::OrchestrationProvider::ACTIVITY_ROLE_MAP[activity]
286
- end
301
+ def role_for(activity)
302
+ ConfigurationService::Test::OrchestrationProvider::ACTIVITY_ROLE_MAP[activity]
303
+ end
304
+
287
305
  end
288
306
 
289
307
  end
@@ -19,6 +19,8 @@ module ConfigurationService
19
19
  #
20
20
  class Success
21
21
 
22
+ attr_reader :response
23
+
22
24
  ##
23
25
  # @param [ConfigurationService::Configuration, nil] response
24
26
  # a configuration service response, or +nil+ if a {ConfigurationService::ConfigurationNotFoundError} was raised
@@ -51,13 +51,13 @@ module ConfigurationService
51
51
  end
52
52
 
53
53
  ##
54
- # Provide a token that authorizes a role
54
+ # Provide credentials that authorizes a role
55
55
  #
56
- # The token is taken from {ConfigurationService::Provider::Stub::BUILTIN_TOKENS}
56
+ # The credentials are taken from {ConfigurationService::Provider::Stub::BUILTIN_TOKENS}
57
57
  #
58
- # @see ConfigurationService::Test::OrchestrationProvider#token_for
58
+ # @see ConfigurationService::Test::OrchestrationProvider#credentials_for
59
59
  #
60
- def token_for(role)
60
+ def credentials_for(role)
61
61
  ConfigurationService::Provider::Stub::BUILTIN_TOKENS[role]
62
62
  end
63
63
 
@@ -1,5 +1,5 @@
1
1
  module ConfigurationService
2
2
 
3
- VERSION = "2.3.1"
3
+ VERSION = "3.0.0"
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.3.1
4
+ version: 3.0.0
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-20 00:00:00.000000000 Z
11
+ date: 2016-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -90,6 +90,8 @@ files:
90
90
  - ".gemspec"
91
91
  - ".gitignore"
92
92
  - ".rspec"
93
+ - ".ruby-gemset"
94
+ - ".ruby-version"
93
95
  - ".travis.yml"
94
96
  - ".yardopts"
95
97
  - Gemfile
@@ -109,6 +111,7 @@ files:
109
111
  - lib/configuration_service.rb
110
112
  - lib/configuration_service/admin_client.rb
111
113
  - lib/configuration_service/base.rb
114
+ - lib/configuration_service/client.rb
112
115
  - lib/configuration_service/configuration.rb
113
116
  - lib/configuration_service/errors.rb
114
117
  - lib/configuration_service/factory.rb
@@ -155,4 +158,3 @@ signing_key:
155
158
  specification_version: 4
156
159
  summary: Configuration service
157
160
  test_files: []
158
- has_rdoc: