conjur-api 4.31.0 → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +1 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +22 -3
  5. data/Dockerfile +12 -3
  6. data/Gemfile +3 -3
  7. data/Jenkinsfile +69 -0
  8. data/LICENSE.md +195 -0
  9. data/README.md +16 -0
  10. data/Rakefile +34 -18
  11. data/ci/wait_for_server.sh +10 -0
  12. data/conjur-api.gemspec +6 -14
  13. data/dev/docker-compose.yml +23 -0
  14. data/dev/empty.yml +2 -0
  15. data/dev/start.sh +15 -0
  16. data/dev/stop.sh +6 -0
  17. data/docker-compose.yml +27 -0
  18. data/features/exists.feature +37 -0
  19. data/features/group.feature +11 -0
  20. data/features/host.feature +20 -0
  21. data/features/host_factory_create_host.feature +28 -0
  22. data/features/host_factory_token.feature +63 -0
  23. data/features/load_policy.feature +61 -0
  24. data/features/members.feature +51 -0
  25. data/features/new_api.feature +36 -0
  26. data/features/permitted.feature +43 -0
  27. data/features/permitted_roles.feature +30 -0
  28. data/features/public_keys.feature +11 -0
  29. data/features/resource_fields.feature +53 -0
  30. data/features/role_fields.feature +15 -0
  31. data/features/rotate_api_key.feature +13 -0
  32. data/features/step_definitions/api_steps.rb +4 -54
  33. data/features/step_definitions/policy_steps.rb +35 -0
  34. data/features/step_definitions/result_steps.rb +7 -0
  35. data/features/support/env.rb +14 -5
  36. data/features/support/hooks.rb +3 -0
  37. data/features/support/world.rb +5 -6
  38. data/features/update_password.feature +14 -0
  39. data/features/user.feature +17 -0
  40. data/features/variable_fields.feature +20 -0
  41. data/features/variable_value.feature +67 -0
  42. data/lib/conjur/acts_as_resource.rb +95 -65
  43. data/lib/conjur/acts_as_role.rb +102 -51
  44. data/lib/conjur/{audit-api.rb → acts_as_rolsource.rb} +10 -14
  45. data/lib/conjur/acts_as_user.rb +13 -22
  46. data/lib/conjur/api/authn.rb +37 -72
  47. data/lib/conjur/api/host_factories.rb +35 -55
  48. data/lib/conjur/api/policies.rb +56 -0
  49. data/lib/conjur/api/pubkeys.rb +36 -160
  50. data/lib/conjur/api/resources.rb +32 -116
  51. data/lib/conjur/api/roles.rb +28 -105
  52. data/lib/conjur/api/variables.rb +22 -91
  53. data/lib/conjur/api.rb +19 -46
  54. data/lib/conjur/base.rb +21 -132
  55. data/lib/conjur/base_object.rb +57 -0
  56. data/lib/conjur/{authn-api.rb → build_object.rb} +23 -11
  57. data/lib/conjur/cast.rb +12 -17
  58. data/lib/conjur/cert_utils.rb +1 -1
  59. data/lib/conjur/cidr.rb +1 -1
  60. data/lib/conjur/configuration.rb +13 -91
  61. data/lib/conjur/escape.rb +1 -2
  62. data/lib/conjur/group.rb +9 -65
  63. data/lib/conjur/has_attributes.rb +22 -59
  64. data/lib/conjur/host.rb +5 -35
  65. data/lib/conjur/host_factory.rb +40 -40
  66. data/lib/conjur/host_factory_token.rb +38 -23
  67. data/lib/conjur/id.rb +63 -0
  68. data/lib/conjur/layer.rb +5 -80
  69. data/lib/conjur/log.rb +1 -1
  70. data/lib/conjur/log_source.rb +1 -1
  71. data/lib/conjur/{secret.rb → policy.rb} +11 -14
  72. data/lib/conjur/{api/secrets.rb → policy_load_result.rb} +35 -22
  73. data/lib/conjur/query_string.rb +2 -1
  74. data/lib/conjur/resource.rb +5 -299
  75. data/lib/conjur/role.rb +5 -317
  76. data/lib/conjur/role_grant.rb +20 -28
  77. data/lib/conjur/user.rb +5 -63
  78. data/lib/conjur/variable.rb +31 -76
  79. data/lib/conjur/{authz-api.rb → webservice.rb} +8 -16
  80. data/lib/conjur-api/version.rb +2 -2
  81. data/publish.sh +7 -0
  82. data/spec/api_spec.rb +208 -0
  83. data/spec/cast_spec.rb +21 -0
  84. data/spec/{lib/cert_utils_spec.rb → cert_utils_spec.rb} +0 -0
  85. data/spec/{lib/cidr_spec.rb → cidr_spec.rb} +0 -0
  86. data/spec/{lib/configuration_spec.rb → configuration_spec.rb} +40 -140
  87. data/spec/{lib/has_attributes_spec.rb → has_attributes_spec.rb} +6 -2
  88. data/spec/{lib/log_source_spec.rb → log_source_spec.rb} +0 -0
  89. data/spec/{lib/log_spec.rb → log_spec.rb} +0 -0
  90. data/spec/roles_spec.rb +24 -0
  91. data/spec/spec_helper.rb +63 -78
  92. data/spec/ssl_spec.rb +3 -5
  93. data/spec/vendor/rest_client_spec.rb +0 -54
  94. data/test.sh +40 -0
  95. metadata +122 -281
  96. data/.kateproject +0 -5
  97. data/LICENSE +0 -22
  98. data/ci/test.sh +0 -9
  99. data/features/audit_resources.feature +0 -15
  100. data/features/audit_roles.feature +0 -15
  101. data/features/bootstrap.feature +0 -31
  102. data/features/step_definitions/cli_steps.rb +0 -5
  103. data/jenkins.sh +0 -27
  104. data/lib/conjur/acts_as_asset.rb +0 -88
  105. data/lib/conjur/annotations.rb +0 -186
  106. data/lib/conjur/api/audit.rb +0 -138
  107. data/lib/conjur/api/deputies.rb +0 -57
  108. data/lib/conjur/api/groups.rb +0 -111
  109. data/lib/conjur/api/hosts.rb +0 -109
  110. data/lib/conjur/api/info.rb +0 -126
  111. data/lib/conjur/api/layers.rb +0 -62
  112. data/lib/conjur/api/ldapsync.rb +0 -115
  113. data/lib/conjur/api/users.rb +0 -106
  114. data/lib/conjur/bootstrap.rb +0 -161
  115. data/lib/conjur/build_from_response.rb +0 -49
  116. data/lib/conjur/core-api.rb +0 -74
  117. data/lib/conjur/deputy.rb +0 -55
  118. data/lib/conjur/env.rb +0 -54
  119. data/lib/conjur/event_source.rb +0 -101
  120. data/lib/conjur/exists.rb +0 -60
  121. data/lib/conjur/graph.rb +0 -295
  122. data/lib/conjur/has_id.rb +0 -43
  123. data/lib/conjur/has_identifier.rb +0 -36
  124. data/lib/conjur/has_owner.rb +0 -51
  125. data/lib/conjur/host-factory-api.rb +0 -38
  126. data/lib/conjur/layer-api.rb +0 -13
  127. data/lib/conjur/ldap_sync_job.rb +0 -89
  128. data/lib/conjur/path_based.rb +0 -86
  129. data/lib/conjur/pubkeys-api.rb +0 -50
  130. data/lib/conjur/standard_methods.rb +0 -91
  131. data/reqspeed.rb +0 -20
  132. data/spec/api/authn_spec.rb +0 -81
  133. data/spec/api/graph_spec.rb +0 -117
  134. data/spec/api/groups_spec.rb +0 -40
  135. data/spec/api/hosts_spec.rb +0 -36
  136. data/spec/api/info_spec.rb +0 -89
  137. data/spec/api/layer_spec.rb +0 -18
  138. data/spec/api/ldapsync_spec.rb +0 -44
  139. data/spec/api/pubkeys_spec.rb +0 -66
  140. data/spec/api/resources_spec.rb +0 -92
  141. data/spec/api/roles_spec.rb +0 -100
  142. data/spec/api/secrets_spec.rb +0 -16
  143. data/spec/api/users_spec.rb +0 -71
  144. data/spec/api/variables_spec.rb +0 -112
  145. data/spec/cas_rest_client.rb +0 -17
  146. data/spec/cidr_helper.rb +0 -24
  147. data/spec/lib/acts_as_user_spec.rb +0 -27
  148. data/spec/lib/annotations_spec.rb +0 -109
  149. data/spec/lib/api_spec.rb +0 -480
  150. data/spec/lib/asset_spec.rb +0 -80
  151. data/spec/lib/audit_spec.rb +0 -155
  152. data/spec/lib/build_from_response_spec.rb +0 -49
  153. data/spec/lib/deputy_spec.rb +0 -25
  154. data/spec/lib/exists_spec.rb +0 -24
  155. data/spec/lib/group_spec.rb +0 -18
  156. data/spec/lib/host_spec.rb +0 -31
  157. data/spec/lib/resource_spec.rb +0 -240
  158. data/spec/lib/role_grant_spec.rb +0 -13
  159. data/spec/lib/role_spec.rb +0 -231
  160. data/spec/lib/standard_methods_spec.rb +0 -66
  161. data/spec/lib/user_spec.rb +0 -77
  162. data/spec/standard_methods_helper.rb +0 -41
  163. data/spec/variable_spec.rb +0 -101
  164. data/spec/vcr_cassettes/Conjur_Resource/_create/with_path-like_identifier.yml +0 -87
  165. data/spec/vcr_cassettes/Conjur_Resource/_create/with_un-encoded_path-like_identifier.yml +0 -87
  166. data/spec/vcr_cassettes/Conjur_Resource/_create/with_uuid_identifier.yml +0 -87
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013-2016 Conjur Inc
2
+ # Copyright 2013-2017 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -20,69 +20,37 @@
20
20
  #
21
21
  module Conjur
22
22
 
23
- # Secrets stored in Conjur are represented by {http://developer.conjur.net/reference/services/directory/variable Variables}.
23
+ # Protected (secret) data stored in Conjur.
24
+ #
24
25
  # The code responsible for the actual encryption of variables is open source as part of the
25
26
  # {https://github.com/conjurinc/slosilo Slosilo} library.
26
27
  #
27
- # You should not generally create instances of this class directly. Instead, you can get them from
28
- # {Conjur::API} methods such as {Conjur::API#create_variable} and {Conjur::API#variable}.
29
- #
30
- # Conjur variables store metadata (mime-type and secret kind) with each secret.
28
+ # Each variables has some standard metadata (`mime-type` and secret `kind`).
31
29
  #
32
30
  # Variables are *versioned*. Storing secrets in multiple places is a bad security practice, but
33
31
  # overwriting a secret accidentally can create a major problem for development and ops teams. Conjur
34
- # discourages bad security practices while avoiding ops disasters by storing all previous versions of
35
- # a secret.
32
+ # discourages bad security practices while avoiding ops disasters by storing previous versions of
33
+ # a secret (up to a fixed limit, to avoid unbounded database growth).
36
34
  #
37
35
  # ### Important
38
36
  # A common pitfall when trying to access older versions of a variable is to assume that `0` is the oldest
39
- # version. In fact, `0` references the *latest* version, while *1* is the oldest.
40
- #
37
+ # version. Variable versions are `1`-based, with `1` being the oldest.
41
38
  #
42
39
  # ### Permissions
43
40
  #
44
- # * To *read* the value of a `variable`, you must have permission to `'execute'` the variable.
41
+ # * To *fetch* the value of a `variable`, you must have permission to `'execute'` the variable.
45
42
  # * To *add* a value to a `variable`, you must have permission to `'update'` the variable.
46
43
  # * To *show* metadata associated with a variable, but *not* the value of the secret, you must have `'read'`
47
44
  # permission on the variable.
48
45
  #
49
- # When you create a secret, the creator role is granted all three of the above permissions.
50
- #
51
46
  # @example Get a variable and access its metadata and the latest value
52
- # variable = api.variable 'example'
47
+ # variable = api.resource 'myorg:variable:example'
53
48
  # puts variable.kind # "example-secret"
54
49
  # puts variable.mime_type # "text/plain"
55
50
  # puts variable.value # "supahsecret"
56
- #
57
- # @example Variable permissions
58
- # # use our 'admin' api to create a variable 'permissions-example
59
- # admin_var = admin_api.create_variable 'text/plain', 'example', 'permissions-example'
60
- #
61
- # # get a 'view' to it from user 'alice'
62
- # alice_var = alice_api.variable admin_var.id
63
- #
64
- # # Initilally, all of the following raise a RestClient::Forbidden exception
65
- # alice_var.attributes
66
- # alice_var.value
67
- # alice_var.add_value 'hi'
68
- #
69
- # # Allow alice to see the variables attributes
70
- # admin_var.permit 'read', alice
71
- # alice_var.attributes # OK
72
- #
73
- # # Allow alice to update the variable
74
- # admin_var.permit 'update', alice
75
- # alice_var.add_value 'hello'
76
- #
77
- # # Notice that alice still can't see the variable's value:
78
- # alice_var.value # raises RestClient::Forbidden
79
- #
80
- # # Finally, we let alice execute the variable
81
- # admin_var.permit 'execute', alice
82
- # alice_var.value # 'hello'
83
- #
51
+
84
52
  # @example Variables are versioned
85
- # var = api.variable 'version-example'
53
+ # variable = api.resource 'myorg:variable:example'
86
54
  # # Unless you set a variables value when you create it, the variable starts out without a value and version_count
87
55
  # # is 0.
88
56
  # var.version_count # => 0
@@ -106,9 +74,16 @@ module Conjur
106
74
  # # Notice that version 0 of a variable is always the most recent:
107
75
  # var.value 0 # => 'value 2'
108
76
  #
109
- class Variable < RestClient::Resource
110
- include ActsAsAsset
77
+ class Variable < BaseObject
78
+ include ActsAsResource
111
79
 
80
+ def as_json options={}
81
+ result = super(options)
82
+ result["mime_type"] = mime_type
83
+ result["kind"] = kind
84
+ result
85
+ end
86
+
112
87
  # The kind of secret represented by this variable, for example, `'postgres-url'` or
113
88
  # `'aws-secret-access-key'`.
114
89
  #
@@ -120,7 +95,7 @@ module Conjur
120
95
  # @note this is **not** the same as the `kind` part of a qualified Conjur id.
121
96
  # @return [String] a string representing the kind of secret.
122
97
  def kind
123
- attributes['kind']
98
+ annotation_value 'conjur/kind' || "secret"
124
99
  end
125
100
 
126
101
  # The MIME Type of the variable's value.
@@ -134,7 +109,7 @@ module Conjur
134
109
  #
135
110
  # @return [String] a MIME type, such as `'text/plain'` or `'application/octet-stream'`.
136
111
  def mime_type
137
- attributes['mime_type']
112
+ annotation_value 'conjur/mime_type' || "text/plain"
138
113
  end
139
114
 
140
115
  # Add a new value to the variable.
@@ -155,7 +130,7 @@ module Conjur
155
130
  logger << "Adding a value to variable #{id}"
156
131
  end
157
132
  invalidate do
158
- self['values'].post value: value
133
+ core_resource['secrets'][id.to_url_path].post value
159
134
  end
160
135
  end
161
136
 
@@ -170,7 +145,12 @@ module Conjur
170
145
  #
171
146
  # @return [Integer] the number of versions
172
147
  def version_count
173
- self.attributes['version_count']
148
+ secrets = attributes['secrets']
149
+ if secrets.empty?
150
+ 0
151
+ else
152
+ secrets.last['version']
153
+ end
174
154
  end
175
155
 
176
156
  # Return the version of a variable.
@@ -205,34 +185,9 @@ module Conjur
205
185
  # @param options [Hash]
206
186
  # @option options [Boolean, false] :show_expired show value even if variable has expired
207
187
  # @return [String] the value of the variable
208
- def value(version = nil, options = {})
209
- url = 'value'
188
+ def value version = nil, options = {}
210
189
  options['version'] = version if version
211
- url << '?' + options.to_query unless options.empty?
212
- self[url].get.body
190
+ core_resource['secrets'][id.to_url_path][options_querystring options].get.body
213
191
  end
214
-
215
- # Set the variable to expire after the given interval. The
216
- # interval can either be an ISO8601 duration or it can the number
217
- # of seconds for which the variable should be valid. Once a
218
- # variable has expired, its value will no longer be retrievable.
219
- #
220
- # You must have the **`'update'`** permission on a variable to call this method.
221
- #
222
- # @example Use an ISO8601 duration to set the expiration for a variable to tomorrow
223
- # var = api.variable 'my-secret'
224
- # var.expires_in "P1D"
225
- #
226
- # @example Use ActiveSupport to set the expiration for a variable to tomorrow
227
- # require 'active_support/all'
228
- # var = api.variable 'my-secret'
229
- # var.expires_in 1.day
230
- # @param interval a String containing an ISO8601 duration, otherwise the number of seconds before the variable xpires
231
- # @return [Hash] description of the variable's expiration, including the (Conjur server) time when it expires
232
- def expires_in interval
233
- duration = interval.respond_to?(:to_str) ? interval : "PT#{interval.to_i}S"
234
- JSON::parse(self['expiration'].post(duration: duration).body)
235
- end
236
-
237
192
  end
238
193
  end
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright 2013-2017 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -19,20 +19,12 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
- module Authz
23
- class API < Conjur::API
24
- class << self
25
-
26
- # The URL for the audit service
27
- #
28
- # @return [String] the audit service url.
29
- def host
30
- Conjur.configuration.authz_url
31
- end
32
- end
33
- end
22
+ # A Conjur Webservice, which protects access to service code.
23
+ #
24
+ # Permissions on webservices can be granted and interpreted in a free-form way
25
+ # which is appropriate to the domain. For example, for a Docker registry
26
+ # which is guarded by a Webservice, the likely privileges would be `pull` and `push`.
27
+ class Webservice < BaseObject
28
+ include ActsAsResource
34
29
  end
35
30
  end
36
-
37
- require 'conjur/api/roles'
38
- require 'conjur/api/resources'
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2016 Conjur Inc.
1
+ # Copyright 2013-2017 Conjur Inc.
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  # this software and associated documentation files (the "Software"), to deal in
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Conjur
21
21
  class API
22
- VERSION = "4.31.0"
22
+ VERSION = "5.0.0.rc1"
23
23
  end
24
24
  end
data/publish.sh ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash -e
2
+
3
+ docker pull registry.tld/conjurinc/publish-rubygem
4
+
5
+ summon --yaml "RUBYGEMS_API_KEY: !var rubygems/api-key" \
6
+ docker run --rm --env-file @SUMMONENVFILE -v "$(pwd)":/opt/src \
7
+ registry.tld/conjurinc/publish-rubygem conjur-api
data/spec/api_spec.rb ADDED
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+ require 'fakefs/spec_helpers'
3
+
4
+ describe Conjur::API do
5
+
6
+ let(:account) { 'api-spec-acount' }
7
+ before { allow(Conjur.configuration).to receive_messages account: account }
8
+
9
+ shared_context "logged in", logged_in: true do
10
+ let(:login) { "bob" }
11
+ let(:token) { { 'data' => login, 'timestamp' => Time.now.to_s } }
12
+ let(:remote_ip) { nil }
13
+ let(:api_args) { [ token, { remote_ip: remote_ip } ] }
14
+ subject(:api) { Conjur::API.new_from_token(*api_args) }
15
+ end
16
+
17
+ shared_context "logged in with an API key", logged_in: :api_key do
18
+ include_context "logged in"
19
+ let(:api_key) { "theapikey" }
20
+ let(:api_args) { [ login, api_key, { remote_ip: remote_ip, account: account } ] }
21
+ subject(:api) { Conjur::API.new_from_key(*api_args) }
22
+ end
23
+
24
+ shared_context "logged in with a token file", logged_in: :token_file do
25
+ include FakeFS::SpecHelpers
26
+ include_context "logged in"
27
+ let(:token_file) { "token_file" }
28
+ let(:api_args) { [ token_file, { remote_ip: remote_ip } ] }
29
+ subject(:api) { Conjur::API.new_from_token_file(*api_args) }
30
+ end
31
+
32
+ def time_travel delta
33
+ allow(api.authenticator).to receive(:gettime).and_wrap_original do |m|
34
+ m[] + delta
35
+ end
36
+ allow(api.authenticator).to receive(:monotonic_time).and_wrap_original do |m|
37
+ m[] + delta
38
+ end
39
+ allow(Time).to receive(:now).and_wrap_original do |m|
40
+ m[] + delta
41
+ end
42
+ end
43
+
44
+ describe '#token' do
45
+ context 'with token file available', logged_in: :token_file do
46
+ def write_token token
47
+ File.write token_file, JSON.generate(token)
48
+ end
49
+
50
+ before do
51
+ write_token token
52
+ end
53
+
54
+ it "reads the file to get a token" do
55
+ expect(api.instance_variable_get("@token")).to eq(nil)
56
+ expect(api.token).to eq(token)
57
+ expect(api.credentials).to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login })
58
+ end
59
+
60
+ context "after expiration" do
61
+ it 'it reads a new token' do
62
+ expect(Time.parse(api.token['timestamp'])).to be_within(5.seconds).of(Time.now)
63
+
64
+ time_travel 6.minutes
65
+ new_token = token.merge "timestamp" => Time.now.to_s
66
+ write_token new_token
67
+
68
+ expect(api.token).to eq(new_token)
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'with API key available', logged_in: :api_key do
74
+ it "authenticates to get a token" do
75
+ expect(Conjur::API).to receive(:authenticate).with(login, api_key, account: account).and_return token
76
+
77
+ expect(api.instance_variable_get("@token")).to eq(nil)
78
+ expect(api.token).to eq(token)
79
+ expect(api.credentials).to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login })
80
+ end
81
+
82
+ context "after expiration" do
83
+
84
+ shared_examples "it gets a new token" do
85
+ it 'by refreshing' do
86
+ allow(Conjur::API).to receive(:authenticate).with(login, api_key, account: account).and_return token
87
+ expect(Time.parse(api.token['timestamp'])).to be_within(5.seconds).of(Time.now)
88
+
89
+ time_travel 6.minutes
90
+ new_token = token.merge "timestamp" => Time.now.to_s
91
+
92
+ expect(Conjur::API).to receive(:authenticate).with(login, api_key, account: account).and_return new_token
93
+ expect(api.token).to eq(new_token)
94
+ end
95
+ end
96
+
97
+ it_should_behave_like "it gets a new token"
98
+ end
99
+ end
100
+
101
+ context 'with no API key available', logged_in: true do
102
+ it "returns the token used to create it" do
103
+ expect(api.token).to eq token
104
+ end
105
+
106
+ it "doesn't try to refresh an old token" do
107
+ expect(Conjur::API).not_to receive :authenticate
108
+ api.token # vivify
109
+ time_travel 6.minutes
110
+ expect { api.token }.not_to raise_error
111
+ end
112
+ end
113
+ end
114
+
115
+ context "credential handling", logged_in: true do
116
+ context "from token" do
117
+ describe '#credentials' do
118
+ subject { super().credentials }
119
+ it { is_expected.to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login }) }
120
+ end
121
+
122
+ context "with remote_ip" do
123
+ let(:remote_ip) { "66.0.0.1" }
124
+ describe '#credentials' do
125
+ subject { super().credentials }
126
+ it { is_expected.to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"", :x_forwarded_for=>"66.0.0.1" }, username: login }) }
127
+ end
128
+ end
129
+ end
130
+
131
+ context "from logged-in RestClient::Resource" do
132
+ let (:authz_header) { %Q{Token token="#{token_encoded}"} }
133
+ let (:priv_header) { nil }
134
+ let (:forwarded_for_header) { nil }
135
+ let (:audit_roles_header) { nil }
136
+ let (:audit_resources_header) { nil }
137
+ let (:username) { 'bob' }
138
+ subject { resource.conjur_api }
139
+
140
+ shared_examples "it can clone itself" do
141
+ it "has the authz header" do
142
+ expect(subject.credentials[:headers][:authorization]).to eq(authz_header)
143
+ end
144
+ it "has the username" do
145
+ expect(subject.credentials[:username]).to eq(username)
146
+ end
147
+ end
148
+
149
+ let(:token_encoded) { Base64.strict_encode64(token.to_json) }
150
+ let(:base_headers) { { authorization: authz_header } }
151
+ let(:headers) { base_headers }
152
+ let(:resource) { RestClient::Resource.new("http://example.com", { headers: headers })}
153
+ context 'basic functioning' do
154
+ it_behaves_like 'it can clone itself'
155
+ end
156
+
157
+ context "forwarded for" do
158
+ let(:forwarded_for_header) { "66.0.0.1" }
159
+ let(:headers) { base_headers.merge(x_forwarded_for: forwarded_for_header) }
160
+ it_behaves_like 'it can clone itself'
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "#role_from_username", logged_in: true do
166
+ it "returns a user role when username is plain" do
167
+ expect(Conjur::API.role_from_username(api, "plain-username", account).id).to eq("#{account}:user:plain-username")
168
+ end
169
+
170
+ it "returns an appropriate role kind when username is qualified" do
171
+ expect(Conjur::API.role_from_username(api, "host/foo/bar", account).id).to eq("#{account}:host:foo/bar")
172
+ end
173
+ end
174
+
175
+ describe "#current_role", logged_in: true do
176
+ context "when logged in as user" do
177
+ let(:login) { 'joerandom' }
178
+ it "returns a user role" do
179
+ expect(api.current_role(account).id).to eq("#{account}:user:joerandom")
180
+ end
181
+ end
182
+
183
+ context "when logged in as host" do
184
+ let(:host) { "somehost" }
185
+ let(:login) { "host/#{host}" }
186
+ it "returns a host role" do
187
+ expect(api.current_role(account).id).to eq("#{account}:host:somehost")
188
+ end
189
+ end
190
+ end
191
+
192
+ describe 'url escapes' do
193
+ let(:urls){[
194
+ 'foo/bar@baz',
195
+ '/test/some group with spaces'
196
+ ]}
197
+
198
+ describe '#fully_escape' do
199
+ let(:expected){[
200
+ 'foo%2Fbar%40baz',
201
+ '%2Ftest%2Fsome%20group%20with%20spaces'
202
+ ]}
203
+ it 'escapes the urls correctly' do
204
+ expect(urls.map{|u| Conjur::API.fully_escape u}).to eq(expected)
205
+ end
206
+ end
207
+ end
208
+ end
data/spec/cast_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Conjur::Cast do
4
+ let!(:object) {
5
+ Object.new.tap do |obj|
6
+ class << obj
7
+ include Conjur::Cast
8
+ end
9
+ end
10
+ }
11
+
12
+ it 'String casts to itself' do
13
+ expect(object.send(:cast_to_id, "foo")).to eq("foo")
14
+ end
15
+ it 'Id casts to to_s' do
16
+ expect(object.send(:cast_to_id, "foo")).to eq("foo")
17
+ end
18
+ it 'Array casts via #join' do
19
+ expect(object.send(:cast_to_id, [ "foo", "bar" ])).to eq("foo:bar")
20
+ end
21
+ end
File without changes
File without changes