conjur-api 5.3.8.pre.319 → 5.3.8.pre.321

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.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +10 -0
  3. data/.dockerignore +1 -0
  4. data/.github/CODEOWNERS +10 -0
  5. data/.gitignore +32 -0
  6. data/.gitleaks.toml +219 -0
  7. data/.overcommit.yml +16 -0
  8. data/.project +18 -0
  9. data/.rubocop.yml +3 -0
  10. data/.rubocop_settings.yml +86 -0
  11. data/.rubocop_todo.yml +709 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +448 -0
  14. data/CONTRIBUTING.md +138 -0
  15. data/Dockerfile +16 -0
  16. data/Gemfile +7 -0
  17. data/Jenkinsfile +136 -0
  18. data/LICENSE +202 -0
  19. data/README.md +162 -0
  20. data/Rakefile +47 -0
  21. data/SECURITY.md +42 -0
  22. data/VERSION +1 -1
  23. data/bin/parse-changelog.sh +12 -0
  24. data/ci/configure_v4.sh +12 -0
  25. data/ci/configure_v5.sh +19 -0
  26. data/ci/oauth/keycloak/create_client +18 -0
  27. data/ci/oauth/keycloak/create_user +21 -0
  28. data/ci/oauth/keycloak/fetch_certificate +18 -0
  29. data/ci/oauth/keycloak/keycloak_functions.sh +71 -0
  30. data/ci/oauth/keycloak/standalone.xml +578 -0
  31. data/ci/oauth/keycloak/wait_for_server +56 -0
  32. data/ci/submit-coverage +36 -0
  33. data/conjur-api.gemspec +41 -0
  34. data/dev/Dockerfile.dev +12 -0
  35. data/dev/docker-compose.yml +56 -0
  36. data/dev/start +22 -0
  37. data/dev/stop +5 -0
  38. data/docker-compose.yml +98 -0
  39. data/example/demo_v4.rb +49 -0
  40. data/example/demo_v5.rb +57 -0
  41. data/features/authenticators.feature +41 -0
  42. data/features/authn.feature +14 -0
  43. data/features/authn_local.feature +32 -0
  44. data/features/exists.feature +37 -0
  45. data/features/group.feature +11 -0
  46. data/features/host.feature +50 -0
  47. data/features/host_factory_create_host.feature +28 -0
  48. data/features/host_factory_token.feature +63 -0
  49. data/features/load_policy.feature +61 -0
  50. data/features/members.feature +51 -0
  51. data/features/new_api.feature +36 -0
  52. data/features/permitted.feature +70 -0
  53. data/features/permitted_roles.feature +30 -0
  54. data/features/public_keys.feature +11 -0
  55. data/features/resource_fields.feature +53 -0
  56. data/features/role_fields.feature +15 -0
  57. data/features/rotate_api_key.feature +13 -0
  58. data/features/step_definitions/api_steps.rb +52 -0
  59. data/features/step_definitions/policy_steps.rb +134 -0
  60. data/features/step_definitions/result_steps.rb +11 -0
  61. data/features/support/env.rb +19 -0
  62. data/features/support/hooks.rb +3 -0
  63. data/features/support/world.rb +12 -0
  64. data/features/update_password.feature +14 -0
  65. data/features/user.feature +58 -0
  66. data/features/variable_fields.feature +20 -0
  67. data/features/variable_value.feature +60 -0
  68. data/features_v4/authn_local.feature +27 -0
  69. data/features_v4/exists.feature +29 -0
  70. data/features_v4/host.feature +18 -0
  71. data/features_v4/host_factory_token.feature +49 -0
  72. data/features_v4/members.feature +39 -0
  73. data/features_v4/permitted.feature +15 -0
  74. data/features_v4/permitted_roles.feature +8 -0
  75. data/features_v4/resource_fields.feature +47 -0
  76. data/features_v4/rotate_api_key.feature +13 -0
  77. data/features_v4/step_definitions/api_steps.rb +17 -0
  78. data/features_v4/step_definitions/result_steps.rb +3 -0
  79. data/features_v4/support/env.rb +23 -0
  80. data/features_v4/support/policy.yml +34 -0
  81. data/features_v4/support/world.rb +12 -0
  82. data/features_v4/variable_fields.feature +11 -0
  83. data/features_v4/variable_value.feature +54 -0
  84. data/lib/conjur/acts_as_resource.rb +123 -0
  85. data/lib/conjur/acts_as_role.rb +142 -0
  86. data/lib/conjur/acts_as_rolsource.rb +32 -0
  87. data/lib/conjur/acts_as_user.rb +68 -0
  88. data/lib/conjur/api/authenticators.rb +43 -0
  89. data/lib/conjur/api/authn.rb +144 -0
  90. data/lib/conjur/api/host_factories.rb +71 -0
  91. data/lib/conjur/api/ldap_sync.rb +38 -0
  92. data/lib/conjur/api/policies.rb +56 -0
  93. data/lib/conjur/api/pubkeys.rb +53 -0
  94. data/lib/conjur/api/resources.rb +109 -0
  95. data/lib/conjur/api/roles.rb +98 -0
  96. data/lib/conjur/api/router/v4.rb +206 -0
  97. data/lib/conjur/api/router/v5.rb +269 -0
  98. data/lib/conjur/api/variables.rb +59 -0
  99. data/lib/conjur/api.rb +105 -0
  100. data/lib/conjur/base.rb +355 -0
  101. data/lib/conjur/base_object.rb +57 -0
  102. data/lib/conjur/build_object.rb +47 -0
  103. data/lib/conjur/cache.rb +26 -0
  104. data/lib/conjur/cert_utils.rb +63 -0
  105. data/lib/conjur/cidr.rb +71 -0
  106. data/lib/conjur/configuration.rb +460 -0
  107. data/lib/conjur/escape.rb +129 -0
  108. data/lib/conjur/exceptions.rb +4 -0
  109. data/lib/conjur/group.rb +41 -0
  110. data/lib/conjur/has_attributes.rb +98 -0
  111. data/lib/conjur/host.rb +27 -0
  112. data/lib/conjur/host_factory.rb +75 -0
  113. data/lib/conjur/host_factory_token.rb +78 -0
  114. data/lib/conjur/id.rb +71 -0
  115. data/lib/conjur/layer.rb +9 -0
  116. data/lib/conjur/log.rb +72 -0
  117. data/lib/conjur/log_source.rb +60 -0
  118. data/lib/conjur/policy.rb +34 -0
  119. data/lib/conjur/policy_load_result.rb +61 -0
  120. data/lib/conjur/query_string.rb +12 -0
  121. data/lib/conjur/resource.rb +29 -0
  122. data/lib/conjur/role.rb +29 -0
  123. data/lib/conjur/role_grant.rb +85 -0
  124. data/lib/conjur/routing.rb +29 -0
  125. data/lib/conjur/user.rb +40 -0
  126. data/lib/conjur/variable.rb +208 -0
  127. data/lib/conjur/webservice.rb +30 -0
  128. data/lib/conjur-api/version.rb +24 -0
  129. data/lib/conjur-api.rb +2 -0
  130. data/publish.sh +5 -0
  131. data/spec/api/host_factories_spec.rb +34 -0
  132. data/spec/api_spec.rb +254 -0
  133. data/spec/base_object_spec.rb +13 -0
  134. data/spec/cert_utils_spec.rb +173 -0
  135. data/spec/cidr_spec.rb +34 -0
  136. data/spec/configuration_spec.rb +330 -0
  137. data/spec/has_attributes_spec.rb +63 -0
  138. data/spec/helpers/errors_matcher.rb +34 -0
  139. data/spec/helpers/request_helpers.rb +10 -0
  140. data/spec/id_spec.rb +29 -0
  141. data/spec/ldap_sync_spec.rb +21 -0
  142. data/spec/log_source_spec.rb +13 -0
  143. data/spec/log_spec.rb +42 -0
  144. data/spec/roles_spec.rb +24 -0
  145. data/spec/spec_helper.rb +113 -0
  146. data/spec/ssl_spec.rb +109 -0
  147. data/spec/uri_escape_spec.rb +21 -0
  148. data/test.sh +76 -0
  149. data/tmp/.keep +0 -0
  150. metadata +194 -3
@@ -0,0 +1,60 @@
1
+ Feature: Work with Variable values.
2
+
3
+ Background:
4
+ Given I run the code:
5
+ """
6
+ @variable_id = "password"
7
+ $conjur.load_policy 'root', <<-POLICY
8
+ - !variable #{@variable_id}
9
+ - !variable #{@variable_id}-2
10
+ POLICY
11
+ @variable = $conjur.resource("cucumber:variable:#{@variable_id}")
12
+ @variable_2 = $conjur.resource("cucumber:variable:#{@variable_id}-2")
13
+ """
14
+
15
+ Scenario: Add a value, retrieve the variable metadata and the value.
16
+ When I run the code:
17
+ """
18
+ @initial_count = @variable.version_count
19
+ @variable.add_value 'value-0'
20
+ """
21
+ And I run the code:
22
+ """
23
+ expect(@variable.version_count).to eq(@initial_count + 1)
24
+ """
25
+ And I run the code:
26
+ """
27
+ @variable.value(@variable.version_count)
28
+ """
29
+ Then the result should be "value-0"
30
+
31
+ Scenario: Retrieve a historical value.
32
+ Given I run the code:
33
+ """
34
+ @variable.add_value 'value-0'
35
+ @variable.add_value 'value-1'
36
+ @variable.add_value 'value-2'
37
+ """
38
+ When I run the code:
39
+ """
40
+ @variable.value(@variable.version_count - 2)
41
+ """
42
+ Then the result should be "value-0"
43
+
44
+ Scenario: Retrieve multiple values in a batch
45
+ Given I run the code:
46
+ """
47
+ @variable.add_value 'value-0'
48
+ @variable_2.add_value 'value-2'
49
+ """
50
+ When I run the code:
51
+ """
52
+ $conjur.variable_values([ @variable, @variable_2 ].map(&:id))
53
+ """
54
+ Then the JSON should be:
55
+ """
56
+ {
57
+ "cucumber:variable:password": "value-0",
58
+ "cucumber:variable:password-2": "value-2"
59
+ }
60
+ """
@@ -0,0 +1,27 @@
1
+ Feature: When co-located with the Conjur server, the API can use the authn-local service to authenticate.
2
+
3
+ Scenario: authn-local can be used to obtain an access token.
4
+ When I run the code:
5
+ """
6
+ Conjur::API.authenticate_local "alice"
7
+ """
8
+ Then the JSON should have "data"
9
+
10
+ Scenario: Conjur API supports construction from authn-local.
11
+ When I run the code:
12
+ """
13
+ @api = Conjur::API.new_from_authn_local "alice"
14
+ @api.token
15
+ """
16
+ Then the JSON should have "data"
17
+
18
+ Scenario: Conjur API will automatically refresh the token.
19
+ When I run the code:
20
+ """
21
+ @api = Conjur::API.new_from_authn_local "alice"
22
+ @api.token
23
+ @api.force_token_refresh
24
+ @api.token
25
+ """
26
+ Then the JSON should have "data"
27
+ And the JSON at "data" should be "alice"
@@ -0,0 +1,29 @@
1
+ Feature: Check if an object exists.
2
+
3
+ Scenario: A created group resource exists
4
+ When I run the code:
5
+ """
6
+ $conjur.resource('cucumber:group:developers').exists?
7
+ """
8
+ Then the result should be "true"
9
+
10
+ Scenario: An un-created resource doesn't exist
11
+ When I run the code:
12
+ """
13
+ $conjur.resource('cucumber:food:bacon').exists?
14
+ """
15
+ Then the result should be "false"
16
+
17
+ Scenario: A created group role exists
18
+ When I run the code:
19
+ """
20
+ $conjur.role('cucumber:group:developers').exists?
21
+ """
22
+ Then the result should be "true"
23
+
24
+ Scenario: An un-created role doesn't exist
25
+ When I run the code:
26
+ """
27
+ $conjur.role('cucumber:food:bacon').exists?
28
+ """
29
+ Then the result should be "false"
@@ -0,0 +1,18 @@
1
+ Feature: Display Host object fields.
2
+
3
+ Background:
4
+ Given a new host
5
+
6
+ Scenario: API key of a newly created host is available and valid.
7
+ Then I run the code:
8
+ """
9
+ expect(@host.exists?).to be(true)
10
+ expect(@host.api_key).to be
11
+ """
12
+
13
+ Scenario: API key of a a host can be rotated.
14
+ Then I run the code:
15
+ """
16
+ api_key = @host.rotate_api_key
17
+ Conjur::API.new_from_key("host/#{@host.id.identifier}", api_key).token
18
+ """
@@ -0,0 +1,49 @@
1
+ Feature: Working with host factory tokens.
2
+
3
+ Background:
4
+ Given I run the code:
5
+ """
6
+ @expiration = (DateTime.now + 1.hour).change(sec: 0)
7
+ """
8
+
9
+
10
+ Scenario: Create a new host factory token.
11
+ When I run the code:
12
+ """
13
+ @token = $host_factory.create_token(@expiration)
14
+ """
15
+ Then I can run the code:
16
+ """
17
+ expect(@token).to be_instance_of(Conjur::HostFactoryToken)
18
+ expect(@token.token).to be_instance_of(String)
19
+ expiration = @token.expiration
20
+ expiration = expiration.change(sec: 0)
21
+ expect(expiration).to eq(@expiration)
22
+ """
23
+
24
+ Scenario: Create multiple new host factory tokens.
25
+ When I run the code:
26
+ """
27
+ $host_factory.create_tokens @expiration, count: 2
28
+ """
29
+ Then the JSON should have 2 items
30
+
31
+ Scenario: Revoke a host factory token using the token object.
32
+ When I run the code:
33
+ """
34
+ @token = $host_factory.create_token @expiration
35
+ """
36
+ Then I can run the code:
37
+ """
38
+ @token.revoke
39
+ """
40
+
41
+ Scenario: Revoke a host factory token using the API.
42
+ When I run the code:
43
+ """
44
+ @token = $host_factory.create_token @expiration
45
+ """
46
+ Then I can run the code:
47
+ """
48
+ $conjur.revoke_host_factory_token @token.token
49
+ """
@@ -0,0 +1,39 @@
1
+ Feature: Display role members and memberships.
2
+
3
+ Scenario: Show a role's members.
4
+ When I run the code:
5
+ """
6
+ $conjur.role('cucumber:group:everyone').members.map(&:as_json)
7
+ """
8
+ Then the JSON should be:
9
+ """
10
+ [
11
+ {
12
+ "admin_option": false,
13
+ "member": "cucumber:group:developers",
14
+ "role": "cucumber:group:everyone"
15
+ },
16
+ {
17
+ "admin_option": true,
18
+ "member": "cucumber:group:security_admin",
19
+ "role": "cucumber:group:everyone"
20
+ }
21
+ ]
22
+ """
23
+
24
+ Scenario: Show a role's memberships.
25
+ When I run the code:
26
+ """
27
+ $conjur.role('cucumber:group:developers').memberships.map(&:as_json)
28
+ """
29
+ Then the JSON should be:
30
+ """
31
+ [
32
+ {
33
+ "id": "cucumber:group:developers"
34
+ },
35
+ {
36
+ "id": "cucumber:group:everyone"
37
+ }
38
+ ]
39
+ """
@@ -0,0 +1,15 @@
1
+ Feature: Check if a role has permission on a resource.
2
+
3
+ Scenario: Check if the current user has the privilege.
4
+ When I run the code:
5
+ """
6
+ $conjur.resource('cucumber:variable:db-password').permitted? 'execute'
7
+ """
8
+ Then the result should be "true"
9
+
10
+ Scenario: Check if a different user has the privilege.
11
+ When I run the code:
12
+ """
13
+ $conjur.resource('cucumber:variable:db-password').permitted? 'execute', role: "cucumber:user:bob"
14
+ """
15
+ Then the result should be "false"
@@ -0,0 +1,8 @@
1
+ Feature: Enumerate roles which have a permission on a resource.
2
+
3
+ Scenario: Permitted roles can be enumerated.
4
+ When I run the code:
5
+ """
6
+ $conjur.resource('cucumber:variable:db-password').permitted_roles 'execute'
7
+ """
8
+ Then the JSON should include "cucumber:layer:myapp"
@@ -0,0 +1,47 @@
1
+ Feature: Display basic resource fields.
2
+
3
+ Scenario: Group exposes id, kind, identifier, and gidnumber.
4
+ When I run the code:
5
+ """
6
+ resource = $conjur.resource('cucumber:group:developers')
7
+ [ resource.id, resource.account, resource.kind, resource.identifier, resource.gidnumber ]
8
+ """
9
+ Then the JSON should be:
10
+ """
11
+ [
12
+ "cucumber:group:developers",
13
+ "cucumber",
14
+ "group",
15
+ "developers",
16
+ 2000
17
+ ]
18
+ """
19
+
20
+ Scenario: User exposes id, kind, identifier, and uidnumber.
21
+ When I run the code:
22
+ """
23
+ resource = $conjur.resource('cucumber:user:alice')
24
+ [ resource.id, resource.account, resource.kind, resource.identifier, resource.uidnumber ]
25
+ """
26
+ Then the JSON should be:
27
+ """
28
+ [
29
+ "cucumber:user:alice",
30
+ "cucumber",
31
+ "user",
32
+ "alice",
33
+ 2000
34
+ ]
35
+ """
36
+
37
+ Scenario: Resource#owner is the owner object
38
+ When I run the code:
39
+ """
40
+ $conjur.resource('cucumber:group:developers').owner.id
41
+ """
42
+ Then the result should be "cucumber:group:security_admin"
43
+ And I run the code:
44
+ """
45
+ $conjur.resource('cucumber:group:developers').class
46
+ """
47
+ Then the result should be "Conjur::Group"
@@ -0,0 +1,13 @@
1
+ Feature: Rotate the API key.
2
+
3
+ Scenario: Logged-in user can rotate the API key.
4
+ When I run the code:
5
+ """
6
+ $conjur.role('cucumber:user:alice').rotate_api_key
7
+ """
8
+ Then I can run the code:
9
+ """
10
+ @api_key = @result.strip
11
+ @conjur = Conjur::API.new_from_key 'alice', @api_key
12
+ @conjur.token
13
+ """
@@ -0,0 +1,17 @@
1
+ Given(/^a new host$/) do
2
+ @host_id = "app-#{random_hex}"
3
+ host = Conjur::API.host_factory_create_host($token, @host_id)
4
+ @host_api_key = host.api_key
5
+ expect(@host_api_key).to be
6
+
7
+ @host = $conjur.resource("cucumber:host:#{@host_id}")
8
+ @host.attributes['api_key'] = @host_api_key
9
+ end
10
+
11
+ When(/^I(?: can)? run the code:$/) do |code|
12
+ @result = eval(code).tap do |result|
13
+ if ENV['DEBUG']
14
+ puts result
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ Then(/^the result should be "([^"]+)"$/) do |expected|
2
+ expect(@result.to_s).to eq(expected.to_s)
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start
4
+
5
+ require 'json_spec/cucumber'
6
+ require 'conjur/api'
7
+
8
+ Conjur.configuration.appliance_url = ENV['CONJUR_APPLIANCE_URL'] || 'https://conjur_4/api'
9
+ Conjur.configuration.account = ENV['CONJUR_ACCOUNT'] || 'cucumber'
10
+ Conjur.configuration.cert_file = "./tmp/conjur.pem"
11
+ Conjur.configuration.authn_local_socket = "/run/authn-local-4/.socket"
12
+ Conjur.configuration.version = 4
13
+
14
+ Conjur.configuration.apply_cert_config!
15
+
16
+ $username = ENV['CONJUR_AUTHN_LOGIN'] || 'admin'
17
+ $password = ENV['CONJUR_AUTHN_API_KEY'] || 'secret'
18
+
19
+ $api_key = Conjur::API.login $username, $password
20
+ $conjur = Conjur::API.new_from_key $username, $api_key
21
+
22
+ $host_factory = $conjur.resource('cucumber:host_factory:myapp')
23
+ $token = $host_factory.create_token(Time.now + 1.hour)
@@ -0,0 +1,34 @@
1
+ - !user
2
+ id: alice
3
+ uidnumber: 2000
4
+
5
+ - !group
6
+ id: developers
7
+ gidnumber: 2000
8
+
9
+ - !group everyone
10
+
11
+ - !grant
12
+ role: !group everyone
13
+ member: !group developers
14
+
15
+ - !variable db-password
16
+
17
+ - !variable ssh-key
18
+
19
+ - !variable
20
+ id: ssl-certificate
21
+ kind: SSL certificate
22
+ mime_type: application/x-pem-file
23
+
24
+ - !layer myapp
25
+
26
+ - !host-factory
27
+ id: myapp
28
+ layers: [ !layer myapp ]
29
+
30
+ - !permit
31
+ role: !layer myapp
32
+ privileges: [ read, execute ]
33
+ resources:
34
+ - !variable db-password
@@ -0,0 +1,12 @@
1
+ module ApiWorld
2
+ def last_json
3
+ @result.to_json
4
+ end
5
+
6
+ def random_hex nbytes = 12
7
+ @random ||= Random.new
8
+ @random.bytes(nbytes).unpack('h*').first
9
+ end
10
+ end
11
+
12
+ World ApiWorld
@@ -0,0 +1,11 @@
1
+ Feature: Display Variable fields.
2
+
3
+ Background:
4
+ When I run the code:
5
+ """
6
+ $conjur.resource('cucumber:variable:ssl-certificate')
7
+ """
8
+
9
+ Scenario: Display MIME type and kind
10
+ Then the JSON at "mime_type" should be "application/x-pem-file"
11
+ And the JSON at "kind" should be "SSL certificate"
@@ -0,0 +1,54 @@
1
+ Feature: Work with Variable values.
2
+ Background:
3
+ Given I run the code:
4
+ """
5
+ @variable = $conjur.resource("cucumber:variable:db-password")
6
+ @variable_2 = $conjur.resource("cucumber:variable:ssh-key")
7
+ """
8
+
9
+ Scenario: Add a value, retrieve the variable metadata and the value.
10
+ Given I run the code:
11
+ """
12
+ @initial_count = @variable.version_count
13
+ @variable.add_value 'value-0'
14
+ """
15
+ When I run the code:
16
+ """
17
+ expect(@variable.version_count).to eq(@initial_count + 1)
18
+ """
19
+ And I run the code:
20
+ """
21
+ @variable.value
22
+ """
23
+ Then the result should be "value-0"
24
+
25
+ Scenario: Retrieve a historical value.
26
+ Given I run the code:
27
+ """
28
+ @variable.add_value 'value-0'
29
+ @variable.add_value 'value-1'
30
+ @variable.add_value 'value-2'
31
+ """
32
+ When I run the code:
33
+ """
34
+ @variable.value(@variable.version_count - 2)
35
+ """
36
+ Then the result should be "value-0"
37
+
38
+ Scenario: Retrieve multiple values in a batch
39
+ Given I run the code:
40
+ """
41
+ @variable.add_value 'value-0'
42
+ @variable_2.add_value 'value-2'
43
+ """
44
+ When I run the code:
45
+ """
46
+ $conjur.variable_values([ @variable, @variable_2 ].map(&:id))
47
+ """
48
+ Then the JSON should be:
49
+ """
50
+ {
51
+ "db-password": "value-0",
52
+ "ssh-key": "value-2"
53
+ }
54
+ """
@@ -0,0 +1,123 @@
1
+ #
2
+ # Copyright 2013-2017 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+
22
+ module Conjur
23
+ # This module is included in object classes that have resource behavior.
24
+ module ActsAsResource
25
+ # @api private
26
+ def self.included(base)
27
+ base.include HasAttributes
28
+ base.include Escape
29
+ base.extend QueryString
30
+ end
31
+
32
+ # The full role id of the role that owns this resource.
33
+ #
34
+ # @example
35
+ # api.current_role # => 'conjur:user:jon'
36
+ # resource = api.create_resource 'conjur:example:resource-owner'
37
+ # resource.owner # => 'conjur:user:jon'
38
+ #
39
+ # @return [String] the full role id of this resource's owner.
40
+ def owner
41
+ build_object attributes['owner'], default_class: Role
42
+ end
43
+
44
+ # Check whether this object exists by performing a HEAD request to its URL.
45
+ #
46
+ # This method will return false if the object doesn't exist.
47
+ #
48
+ # @example
49
+ # does_not_exist = api.user 'does-not-exist' # This returns without error.
50
+ #
51
+ # # this is wrong!
52
+ # owner = does_not_exist.owner # raises RestClient::ResourceNotFound
53
+ #
54
+ # # this is right!
55
+ # owner = if does_not_exist.exists?
56
+ # does_not_exist.owner
57
+ # else
58
+ # nil # or some sensible default
59
+ # end
60
+ #
61
+ # @return [Boolean] does it exist?
62
+ def exists?
63
+ begin
64
+ url_for(:resources_resource, credentials, id).head
65
+ true
66
+ rescue RestClient::Forbidden
67
+ true
68
+ rescue RestClient::ResourceNotFound
69
+ false
70
+ end
71
+ end
72
+
73
+ # Lists roles that have a specified privilege on the resource.
74
+ #
75
+ # This will return only roles of which api.current_user is a member.
76
+ #
77
+ # Options:
78
+ #
79
+ # * **offset** Zero-based offset into the result set.
80
+ # * **limit** Total number of records returned.
81
+ #
82
+ # @example
83
+ # resource = api.resource 'conjur:variable:example'
84
+ # resource.permitted_roles 'execute' # => ['conjur:user:admin']
85
+ # # After permitting 'execute' to user 'jon'
86
+ # resource.permitted_roles 'execute' # => ['conjur:user:admin', 'conjur:user:jon']
87
+ #
88
+ # @param privilege [String] the privilege
89
+ # @return [Array<String>] the ids of roles that have `privilege` on this resource.
90
+ def permitted_roles privilege
91
+ result = JSON.parse url_for(:resources_permitted_roles, credentials, id, privilege).get
92
+ if result.is_a?(Hash) && ( count = result['count'] )
93
+ count
94
+ else
95
+ result
96
+ end
97
+ end
98
+
99
+ # True if the logged-in role, or a role specified using the :role option, has the
100
+ # specified +privilege+ on this resource.
101
+ #
102
+ # @example
103
+ # api.current_role # => 'conjur:cat:mouse'
104
+ # resource.permitted_roles 'execute' # => ['conjur:user:admin', 'conjur:cat:mouse']
105
+ # resource.permitted_roles 'update', # => ['conjur:user:admin', 'conjur:cat:gino']
106
+ #
107
+ # resource.permitted? 'update' # => false, `mouse` can't update this resource
108
+ # resource.permitted? 'execute' # => true, `mouse` can execute it.
109
+ # resource.permitted? 'update', role: 'conjur:cat:gino' # => true, `gino` can update it.
110
+ # @param privilege [String] the privilege to check
111
+ # @param role [String,nil] :role check whether the role given by this full role id is permitted
112
+ # instead of checking +api.current_role+.
113
+ # @return [Boolean]
114
+ def permitted? privilege, role: nil
115
+ url_for(:resources_check, credentials, id, privilege, role)
116
+ true
117
+ rescue RestClient::Forbidden
118
+ false
119
+ rescue RestClient::ResourceNotFound
120
+ false
121
+ end
122
+ end
123
+ end