configuration_service 2.3.1 → 3.0.0

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