soar_pl 0.0.5 → 0.0.6

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: a33dc515b79a055e58c4cd8322db826b7e8ea527
4
- data.tar.gz: b8efb7557335ff3438c1c3ac61a434c397743ad1
3
+ metadata.gz: e2b08e955891c93d88edb864c6699ac241c236d6
4
+ data.tar.gz: 0d2615ff9cf68374b1f865aa0246264d33859c9d
5
5
  SHA512:
6
- metadata.gz: 8d864b0032344dcbdb3651c52708c76ed4765279867af052eef98d30f94a19e4615ee5f89c31a6df2764729b14194c7fa6477c240acbfa7805225453336fa835
7
- data.tar.gz: 36fc2a86fd22f232ec34dc1b10c23335a8b5fd58a1bb179b43095d7c01af4225863ccb74a4979d83b12c4e305d05ea1de2ab4c54bf19ec9537b1a1dfdb5c1b65
6
+ metadata.gz: 0b94c726c2dd3507818944dd314973446edd3a04d9af421a167c5b8d6f1c63ea34eb16ae25ef809a4dd6efcfce4719f1a9d4b4153e8962f30374c445daebabec
7
+ data.tar.gz: 487f45e98d1da42adf7aa04d1c7d82c5e1f9cc251eb229dd18b639f60eda1e2749ee9e6f8e62d23e2160096865565225effd4931e87410818369b44b6441baa9
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  SoarPl is a generic authorization policy implementation. It was designed for use in the SOAR architecture. Extend the AuthorizationPolicy class with your own, and provide the needed IDM interaction and rule set for interrogating subject_identifier, requestor_identifier, resource_identifier and request in order to make an authorization decision. The policy communicates the result using jsend.
4
4
 
5
+ The policy can be given a subject identifier, representing the subject to be authorized. Optionally, the resource identifier of the resource the subject wants to access can be supplied, as well as details of the request itself. Additionally, the identifier of the requestor asking the authorization question of the policy can also be supplied. This information in conjunction with the subject's roles and attributes as discovered from the (optional) IDM provided, form the full information set that the rule set can use to make the authorization decision.
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -20,7 +22,8 @@ Or install it yourself as:
20
22
  spec.add_development_dependency 'soar_pl'
21
23
  bundle exec irb
22
24
 
23
- Extend the AuthorizationPolicy class to create a policy. Examples can be found here: https://github.hetzner.co.za/hetznerZA/soar_policies/tree/master/production
25
+ In the examples that follow, @iut refers to 'implementation under test' a.k.a 'item under test'
26
+ Extend the {SoarPl::AuthorizationPolicy AuthorizationPolicy} class to create a policy. Examples can be found here: https://github.hetzner.co.za/hetznerZA/soar_policies/tree/master/production
24
27
 
25
28
  The implementation reaches out to the IDM provided and retrieves entity roles and attributes.
26
29
  The IDM provided must adhere to the following API:
@@ -53,7 +56,7 @@ Optionally, require roles to be present for an entity that you identify with a s
53
56
 
54
57
  If requiring roles, you must provide an IDM to retrieve the entity's roles, and the attributes for each role, from:
55
58
 
56
- @iut.has_idm(@idm_instance)
59
+ @iut.use_idm(@idm_instance)
57
60
 
58
61
  Check authorization for a subject identifier, (optionally) providing it with all your rule set (MyRules) needs to make the authorization decision:
59
62
 
@@ -93,3 +96,8 @@ Bug reports and feature requests are welcome by email to ernst dot van dot graan
93
96
 
94
97
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
95
98
 
99
+ ## TODO
100
+
101
+ - The IDM API will be published in a future gem, along with a SOAR reference identity registry implementation
102
+ - Examples are currently in a private repo, this will be made public as the use matures
103
+ - Helper methods for interrogating status may be added (e.g. valid?, configuration_valid?, allowed?, denied?, etc.)
@@ -17,89 +17,36 @@ module SoarPl
17
17
  attr_accessor :request_debug_allow
18
18
 
19
19
  def initialize(policy_identifier, policy_configuration)
20
- data = { 'dependencies' =>
21
- { 'configuration' => 'invalid',
22
- 'policy_identifier' => 'invalid',
23
- 'rule_set' => 'invalid' } }
24
20
  @roles = []
25
21
  @policy_identifier = policy_identifier
26
22
  @configuration = policy_configuration
27
-
28
- valid_policy_identifier = valid_non_empty_string?(policy_identifier)
29
- valid_configuration = @configuration.is_a?(Hash)
30
- #byebug
31
- valid_rule_set = (self.class.name != 'SoarPl::AuthorizationPolicy')
32
-
33
- if (policy_identifier.nil?)
34
- @status = fail('no identifier provided')
35
- elsif (not valid_policy_identifier)
36
- @status = fail('invalid identifier provided')
37
- elsif policy_configuration.nil?
38
- @status = fail('no configuration provided')
39
- elsif not valid_configuration
40
- @status = fail('invalid configuration provided', data)
41
- elsif not valid_rule_set
42
- # Must extend this class and provide a rule set in apply_rule_set(...)
43
- @status = fail('invalid rule set provided')
44
- else
45
- @status = success_data(data)
46
- end
47
- data['dependencies']['configuration'] = (valid_configuration ? 'valid' : 'invalid')
48
- data['dependencies']['rule_set'] = (valid_rule_set ? 'valid' : 'invalid')
49
- data['dependencies']['policy_identifier'] = (valid_policy_identifier ? 'valid' : 'invalid')
23
+ validate_bootstrap(policy_identifier, policy_configuration)
50
24
  setup
51
25
  end
52
26
 
53
27
  def requires_roles(roles)
54
28
  roles = [roles] if not roles.is_a?(Array)
55
-
56
29
  @roles = roles
57
30
  end
58
31
 
59
- def has_idm(idm)
32
+ def use_idm(idm)
60
33
  @idm = idm
61
34
  end
62
35
 
63
36
  def authorize(subject_identifier, requestor_identifier, resource_identifier, request)
64
- #byebug
65
- if request
66
- requested = request
67
- begin
68
- requested = JSON.parse(request) if not request.is_a?(Hash)
69
- rescue => ex
70
- return fail("Invalid request", build_result(false, "Invalid request", @idm))
71
- end
72
- end
73
- return fail_invalid("resource identifier") if resource_identifier and (not valid_non_empty_string?(resource_identifier))
74
- return fail("Invalid request", build_result(false, "Invalid request", @idm)) if requested and (not requested.is_a?(Hash))
75
- return fail_invalid("requestor identifier") if requestor_identifier and (not valid_non_empty_string?(requestor_identifier))
76
- return fail_invalid("subject identifier") if subject_identifier and (not valid_non_empty_string?(subject_identifier))
37
+ result = translate_request(request)
38
+ return result if result['status'] == 'fail'
39
+ requested = result['data']['requested']
77
40
 
78
- subject_roles = []
79
- attributes = {}
80
- begin
81
- subject_roles = discover_subject_roles(subject_identifier) if @idm
82
- rescue => ex
83
- error = 'Entity error (IDM)'
84
- return fail(error, build_result(false, error, @idm))
85
- end
86
-
87
- return success_data(build_result(false, "Role missing", @idm)) if not roles_present?(subject_roles, @roles)
88
-
89
- begin
90
- attributes = discover_subject_role_attributes(subject_identifier, subject_roles) if @idm
91
- rescue => ex
92
- error = 'Entity error (IDM)'
93
- return fail(error, build_result(false, error, @idm))
94
- end
41
+ validation_error = validate_authorization(subject_identifier, requestor_identifier, resource_identifier, requested)
42
+ return validation_error if validation_error
95
43
 
96
- result, message = apply_rule_set(subject_identifier, requestor_identifier, resource_identifier, requested, subject_roles, attributes)
44
+ result = discover_entity(subject_identifier)
45
+ error = result['data']['notifications'].first
46
+ return fail(error, build_result(false, error, @idm)) if result['status'] == 'fail'
97
47
 
98
- if (result)
99
- success_data(build_result(true, message, @idm))
100
- else
101
- success_data(build_result(false, message, @idm))
102
- end
48
+ result, message = apply_rule_set(subject_identifier, requestor_identifier, resource_identifier, requested, result['data']['subject_roles'], result['data']['attributes'])
49
+ build_response(result, message)
103
50
  end
104
51
 
105
52
  protected
@@ -111,6 +58,16 @@ module SoarPl
111
58
  # override me
112
59
  end
113
60
 
61
+ def discover_entity(subject_identifier)
62
+ subject_roles = discover_subject_roles(subject_identifier) if @idm
63
+ return fail("Role missing") if not roles_present?(subject_roles, @roles)
64
+ attributes = discover_subject_role_attributes(subject_identifier, subject_roles) if @idm
65
+ success_data( { 'subject_roles' => subject_roles, 'attributes' => attributes } )
66
+
67
+ rescue => ex
68
+ return fail('Entity error (IDM)')
69
+ end
70
+
114
71
  def discover_subject_roles(subject_identifier)
115
72
  subject_roles = @idm.get_roles(subject_identifier)
116
73
  end
@@ -125,6 +82,70 @@ module SoarPl
125
82
 
126
83
  private
127
84
 
85
+ def validate_bootstrap(policy_identifier, policy_configuration)
86
+ valid_policy_identifier = valid_non_empty_string?(policy_identifier)
87
+ valid_configuration = @configuration.is_a?(Hash)
88
+ valid_rule_set = (self.class.name != 'SoarPl::AuthorizationPolicy')
89
+ set_bootstrap_status(policy_identifier, policy_configuration, valid_configuration, valid_rule_set, valid_policy_identifier)
90
+
91
+ return valid_configuration, valid_rule_set, valid_policy_identifier
92
+ end
93
+
94
+ def data_invalidated
95
+ { 'dependencies' =>
96
+ { 'configuration' => 'invalid',
97
+ 'policy_identifier' => 'invalid',
98
+ 'rule_set' => 'invalid' } }
99
+ end
100
+
101
+ def set_bootstrap_status(policy_identifier, policy_configuration, valid_configuration, valid_rule_set, valid_policy_identifier)
102
+ data = data_invalidated
103
+
104
+ if (policy_identifier.nil?)
105
+ @status = fail('no identifier provided')
106
+ elsif (not valid_policy_identifier)
107
+ @status = fail('invalid identifier provided')
108
+ elsif policy_configuration.nil?
109
+ @status = fail('no configuration provided')
110
+ elsif not valid_configuration
111
+ @status = fail('invalid configuration provided', data)
112
+ elsif not valid_rule_set
113
+ # Must extend this class and provide a rule set in apply_rule_set(...)
114
+ @status = fail('invalid rule set provided')
115
+ else
116
+ @status = success_data(data)
117
+ end
118
+
119
+ data['dependencies']['configuration'] = (valid_configuration ? 'valid' : 'invalid')
120
+ data['dependencies']['rule_set'] = (valid_rule_set ? 'valid' : 'invalid')
121
+ data['dependencies']['policy_identifier'] = (valid_policy_identifier ? 'valid' : 'invalid')
122
+ end
123
+
124
+ def translate_request(request)
125
+ requested = {}
126
+ if request
127
+ requested = request
128
+ begin
129
+ requested = JSON.parse(request) if not request.is_a?(Hash)
130
+ rescue => ex
131
+ return fail("Invalid request", build_result(false, "Invalid request", @idm))
132
+ end
133
+ end
134
+ success_data({'requested' => requested})
135
+ end
136
+
137
+ def validate_authorization(subject_identifier, requestor_identifier, resource_identifier, requested)
138
+ return fail_invalid("resource identifier") if resource_identifier and (not valid_non_empty_string?(resource_identifier))
139
+ return fail("Invalid request", build_result(false, "Invalid request", @idm)) if requested and (not requested.is_a?(Hash))
140
+ return fail_invalid("requestor identifier") if requestor_identifier and (not valid_non_empty_string?(requestor_identifier))
141
+ return fail_invalid("subject identifier") if subject_identifier and (not valid_non_empty_string?(subject_identifier))
142
+ end
143
+
144
+ def build_response(result, message)
145
+ return success_data(build_result(true, message, @idm)) if result
146
+ success_data(build_result(false, message, @idm))
147
+ end
148
+
128
149
  def fail_invalid(description)
129
150
  fail("Invalid #{description}", build_result(false, "Invalid #{description}", @idm))
130
151
  end
@@ -1,3 +1,3 @@
1
1
  module SoarPl
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soar_pl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernst van Graan