conjur-api 4.22.1 → 4.23.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 112df80d0de58ed399d501948d9003abb1afcfb3
4
- data.tar.gz: 33d13ad37bfc43d7f69643eba261b5d6367513f7
3
+ metadata.gz: 91bb6f8e907814c4dd388fef05384202a9e51a29
4
+ data.tar.gz: 4884d67d8ec68a02fdbabe297edeb1e8d95a6d88
5
5
  SHA512:
6
- metadata.gz: 64162326b7b50d050f1b46ba398b2e356cc719b0fa1520c22c6da2007288e52afa7e48e493aae01c9da70a0b15180018a32ff56d40183a7bd1dc31ca439bdb44
7
- data.tar.gz: 54695910fe7b6e085111b7ffa52adb2e3b9b7ca07117d664debaf3439cb6d5d4aa63c0a9684e287257401fb9c1cb86651154c95dde53fbb3802866df564c508b
6
+ metadata.gz: 425b6e7ecbae6f9d79ee004a522ebe51d8ee091f452d3e6d30ff041a33dad04b15d33676b29179105e19f28b537be6325a0f951412a757236e07a1d03dee5954
7
+ data.tar.gz: a4fb4478261d5f9a677c19c2b8103e1f5a9a78015b36dcf17780a1c8288c43de3e3f854b26e1dde1f17c237bde971ac1d9cd1e2544b2fafd195ee10c798f9cdc
@@ -1,3 +1,11 @@
1
+ # v4.23.0
2
+
3
+ * Add `with_audit_roles` and `with_audit_resources` to `Conjur::API`
4
+ to add additional roles and resources to audit records generated by
5
+ requests
6
+
7
+ * Fix encoding of spaces in some urls.
8
+
1
9
  # v4.22.1
2
10
 
3
11
  * `bootstrap` creates host and webservice `conjur/expiration`.
@@ -28,6 +28,7 @@ Gem::Specification.new do |gem|
28
28
  gem.add_development_dependency 'rspec', '~> 3'
29
29
  gem.add_development_dependency 'rspec-expectations', '~> 3.4'
30
30
  gem.add_development_dependency 'webmock'
31
+ gem.add_development_dependency 'aruba', '~> 0.12.0'
31
32
  gem.add_development_dependency 'cucumber'
32
33
  gem.add_development_dependency 'conjur-cli'
33
34
  gem.add_development_dependency 'conjur-debify'
@@ -0,0 +1,15 @@
1
+ Feature: audit with additional resources
2
+
3
+ Background:
4
+ Given I create the variable "$ns_foo"
5
+
6
+ Scenario: with one additional resource
7
+ When I create an api with the additional audit resource "webservice:ws1"
8
+ And I check to see if I'm permitted to "read" variable "$ns_foo"
9
+ Then an audit event for variable "$ns_foo" with action "check" and resource "webservice:ws1" is generated
10
+
11
+ Scenario: with more than one additional resource
12
+ When I create an api with the additional audit resources "webservice:ws1, webservice:ws2"
13
+ And I check to see if I'm permitted to "read" variable "$ns_foo"
14
+ Then an audit event for variable "$ns_foo" with action "check" and resources "webservice:ws1, webservice:ws2" is generated
15
+
@@ -0,0 +1,15 @@
1
+ Feature: audit with additional resources
2
+
3
+ Background:
4
+ Given I create the variable "$ns_foo"
5
+
6
+ Scenario: with one additional resource
7
+ When I create an api with the additional audit role "user:auditor1"
8
+ And I check to see if I'm permitted to "read" variable "$ns_foo"
9
+ Then an audit event for variable "$ns_foo" with action "check" and role "user:auditor1" is generated
10
+
11
+ Scenario: with more than one additional resource
12
+ When I create an api with the additional audit roles "user:auditor2,group:auditors"
13
+ And I check to see if I'm permitted to "read" variable "$ns_foo"
14
+ Then an audit event for variable "$ns_foo" with action "check" and roles "user:auditor2,group:auditors" is generated
15
+
@@ -19,6 +19,39 @@ Then(/^expressions "([^"]*)" and "([^"]*)" are equal$/) do |code, test|
19
19
  expect(eval(code)).to eq(eval(test))
20
20
  end
21
21
 
22
+ Then(/^expression "(.*?)" is equal to$/) do |code, test|
23
+ step %Q{expressions "#{code}" and "#{test}" are equal}
24
+ end
25
+
22
26
  Then(/^expression "([^"]*)" includes "([^"]*)"$/) do |code, test|
23
27
  expect(eval(code)).to include(eval(test))
24
28
  end
29
+
30
+ Then(/^I evaluate the expression "([^"]*)"$/) do |code|
31
+ eval(code)
32
+ end
33
+
34
+ Then(/^I evaluate the expression$/) do |code|
35
+ step %Q{I evaluate the expression "#{code}"}
36
+ end
37
+
38
+ Then(/^I create the variable "(.*?)"$/) do |var|
39
+ api.create_variable('text/plain', 'secret', :id => var)
40
+ end
41
+
42
+ Then(/^I create an api with the additional audit (role|resource)[s]* "(.*?)"$/) do |type, things|
43
+ @api = api.send("with_audit_#{type}s", things.split(','))
44
+ end
45
+
46
+ Then(/^I check to see if I'm permitted to "(.*?)" variable "(.*?)"$/) do |priv, var|
47
+ api.variable(var).resource.permitted?(priv)
48
+ end
49
+
50
+ Then(/^an audit event for variable "(.*?)" with action "(.*?)" and (role|resource)[s]* "(.*?)" is generated$/) do |var, action, type, things|
51
+ resource_ids = things.split(',').collect {|id| api.resource(id).resourceid }
52
+ event_found = api.audit_resource(api.resource("variable:#{var}")).any? do |e|
53
+ e['action'] == action &&
54
+ Set.new(e["#{type}s"]).superset?(Set.new(resource_ids))
55
+ end
56
+ expect(event_found).to be true
57
+ end
@@ -0,0 +1,5 @@
1
+ Transform /\$ns/ do |s|
2
+ s.gsub('$ns', namespace)
3
+ end
4
+
5
+
@@ -1,3 +1,4 @@
1
+ require 'aruba/cucumber'
1
2
  require 'conjur/cli'
2
3
 
3
4
  Conjur::Config.load
@@ -0,0 +1,13 @@
1
+ module ApiWorld
2
+
3
+ def api
4
+ @api ||= Conjur::Authn.connect(nil, :noask => true)
5
+ end
6
+
7
+ def namespace
8
+ @namespace ||= api.create_variable('text/plain', 'id').id.tap {|ns| puts "namespace: #{ns}"}
9
+ end
10
+
11
+ end
12
+
13
+ World ApiWorld
data/jenkins.sh CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash -ex
2
2
 
3
- CONJUR_VERSION=${CONJUR_VERSION:-"4.6"}
3
+ CONJUR_VERSION=${CONJUR_VERSION:-"5.0"}
4
4
  DOCKER_IMAGE=${DOCKER_IMAGE:-"registry.tld/conjur-appliance-cuke-master:$CONJUR_VERSION-stable"}
5
5
  NOKILL=${NOKILL:-"0"}
6
6
  PULL=${PULL:-"1"}
@@ -19,6 +19,6 @@
19
19
 
20
20
  module Conjur
21
21
  class API
22
- VERSION = "4.22.1"
22
+ VERSION = "4.23.0"
23
23
  end
24
24
  end
@@ -97,11 +97,10 @@ class RestClient::Resource
97
97
  # @return {Conjur::API} the new api
98
98
  def conjur_api
99
99
  api = Conjur::API.new_from_token token, remote_ip
100
- if conjur_privilege
101
- api.with_privilege conjur_privilege
102
- else
103
- api
104
- end
100
+ api = api.with_privilege(conjur_privilege) if conjur_privilege
101
+ api = api.with_audit_roles(audit_roles) if audit_roles
102
+ api = api.with_audit_resources(audit_resources) if audit_resources
103
+ api
105
104
  end
106
105
 
107
106
  # Get an authentication token from the clients Authorization header.
@@ -129,6 +128,14 @@ class RestClient::Resource
129
128
  options[:headers][:x_conjur_privilege]
130
129
  end
131
130
 
131
+ def audit_roles
132
+ options[:headers][:conjur_audit_roles].try { |r| Conjur::API.decode_audit_ids(r) }
133
+ end
134
+
135
+ def audit_resources
136
+ options[:headers][:conjur_audit_resources].try { |r| Conjur::API.decode_audit_ids(r) }
137
+ end
138
+
132
139
  # The username this resource authenticates as.
133
140
  #
134
141
  # @return [String] the username
@@ -141,6 +141,15 @@ module Conjur
141
141
  def new_from_token(token, remote_ip = nil)
142
142
  self.new nil, nil, token, remote_ip
143
143
  end
144
+
145
+ def encode_audit_ids(ids)
146
+ ids.collect{|id| CGI::escape(id)}.join('&')
147
+ end
148
+
149
+ def decode_audit_ids(ids)
150
+ ids.split('&').collect{|id| CGI::unescape(id)}
151
+ end
152
+
144
153
  end
145
154
 
146
155
  # Create a new instance from a username and api key or a token.
@@ -179,6 +188,16 @@ module Conjur
179
188
  # The optional global privilege (e.g. 'elevate' or 'reveal') which should be attempted on the request.
180
189
  attr_accessor :privilege
181
190
 
191
+ #@!attribute [rw] audit_roles
192
+ # An array of role ids that should be included in any audit
193
+ # records generated by requsts made by this instance of the api.
194
+ attr_accessor :audit_roles
195
+
196
+ #@!attribute [rw] audit_resources
197
+ # An array of resource ids that should be included in any audit
198
+ # records generated by requsts made by this instance of the api.
199
+ attr_accessor :audit_resources
200
+
182
201
  # The name of the user as which this api instance is authenticated. This is available whether the api
183
202
  # instance was created from credentials or an authentication token.
184
203
  #
@@ -233,6 +252,8 @@ module Conjur
233
252
  h[:authorization] = "Token token=\"#{Base64.strict_encode64 token.to_json}\""
234
253
  h[:x_conjur_privilege] = @privilege if @privilege
235
254
  h[:x_forwarded_for] = @remote_ip if @remote_ip
255
+ h[:conjur_audit_roles] = Conjur::API.encode_audit_ids(@audit_roles) if @audit_roles
256
+ h[:conjur_audit_resources] = Conjur::API.encode_audit_ids(@audit_resources) if @audit_resources
236
257
  end
237
258
  { headers: headers, username: username }
238
259
  end
@@ -245,7 +266,23 @@ module Conjur
245
266
  api.privilege = privilege
246
267
  end
247
268
  end
248
-
269
+
270
+ def with_audit_roles role_ids
271
+ role_ids = Array(role_ids)
272
+ self.class.new(username, api_key, token, remote_ip).tap do |api|
273
+ # Ensure that all role ids are fully qualified
274
+ api.audit_roles = role_ids.collect { |id| api.role(id).roleid }
275
+ end
276
+ end
277
+
278
+ def with_audit_resources resource_ids
279
+ resource_ids = Array(resource_ids)
280
+ self.class.new(username, api_key, token, remote_ip).tap do |api|
281
+ # Ensure that all resource ids are fully qualified
282
+ api.audit_resources = resource_ids.collect { |id| api.resource(id).resourceid }
283
+ end
284
+ end
285
+
249
286
  private
250
287
 
251
288
  def token_valid?
@@ -31,13 +31,19 @@ module Conjur
31
31
  # fully_escape 'foo/bar@baz'
32
32
  # # => "foo%2Fbar%40baz"
33
33
  #
34
+ # @example
35
+ # fully_escape 'test/Domain Controllers'
36
+ # # => "test%2FDomain%20Controllers"
37
+ #
34
38
  # @param [String] str the string to escape
35
39
  # @return [String] the escaped string
36
40
  def fully_escape(str)
37
- require 'cgi'
38
- CGI.escape(str.to_s)
41
+ # CGI escape uses + for spaces, which our services don't support :-(
42
+ # We just gsub it.
43
+ CGI.escape(str.to_s).gsub('+', '%20')
39
44
  end
40
45
 
46
+
41
47
  # Escape a URI path component.
42
48
  #
43
49
  # This method simply calls {Conjur::Escape::ClassMethods#path_or_query_escape}.
@@ -121,4 +127,4 @@ module Conjur
121
127
  self.class.query_escape str
122
128
  end
123
129
  end
124
- end
130
+ end
@@ -260,6 +260,7 @@ describe Conjur::API do
260
260
  end
261
261
  end
262
262
  end
263
+
263
264
 
264
265
  context "from api key", logged_in: true do
265
266
  let(:api_key) { "theapikey" }
@@ -299,38 +300,67 @@ describe Conjur::API do
299
300
  end
300
301
 
301
302
  context "from logged-in RestClient::Resource" do
303
+ let (:authz_header) { %Q{Token token="#{token_encoded}"} }
304
+ let (:priv_header) { nil }
305
+ let (:forwarded_for_header) { nil }
306
+ let (:audit_roles_header) { nil }
307
+ let (:audit_resources_header) { nil }
308
+ let (:username) { 'bob' }
309
+ subject { resource.conjur_api }
310
+
311
+ shared_examples "it can clone itself" do
312
+ it "has the authz header" do
313
+ expect(subject.credentials[:headers][:authorization]).to eq(authz_header)
314
+ end
315
+ it "has the conjur privilege header" do
316
+ expect(subject.credentials[:headers][:x_conjur_privilege]).to eq(priv_header)
317
+ end
318
+ it "has the forwarded for header" do
319
+ expect(subject.credentials[:headers][:x_forwarded_for]).to eq(forwarded_for_header)
320
+ end
321
+ it "has the audit_roles header" do
322
+ expect(subject.credentials[:headers][:conjur_audit_roles]).to eq(audit_roles_header)
323
+ end
324
+ it "has the audit_resources header" do
325
+ expect(subject.credentials[:headers][:conjur_audit_resources]).to eq(audit_resources_header)
326
+ end
327
+ it "has the username" do
328
+ expect(subject.credentials[:username]).to eq(username)
329
+ end
330
+ end
331
+
302
332
  let(:token_encoded) { Base64.strict_encode64(token.to_json) }
303
- let(:headers) { { authorization: "Token token=\"#{token_encoded}\"" } }
333
+ let(:base_headers) { { authorization: authz_header } }
334
+ let(:headers) { base_headers }
304
335
  let(:resource) { RestClient::Resource.new("http://example.com", { headers: headers })}
305
- it "can construct a new API instance" do
306
- api = resource.conjur_api
307
- expect(api.credentials[:headers][:authorization]).to eq("Token token=\"#{token_encoded}\"")
308
- expect(api.credentials[:headers][:x_conjur_privilege]).to be_nil
309
- expect(api.credentials[:headers][:x_forwarded_for]).to be_nil
310
- expect(api.credentials[:username]).to eq("bob")
336
+ context 'basic functioning' do
337
+ it_behaves_like 'it can clone itself'
311
338
  end
312
339
 
313
340
  context "privileged" do
314
- let(:headers) { { authorization: "Token token=\"#{token_encoded}\"", x_conjur_privilege: "elevate" } }
315
- it "can clone itself" do
316
- api = resource.conjur_api
317
- expect(api.credentials[:headers][:authorization]).to eq("Token token=\"#{token_encoded}\"")
318
- expect(api.credentials[:headers][:x_conjur_privilege]).to eq("elevate")
319
- expect(api.credentials[:headers][:x_forwarded_for]).to be_nil
320
- expect(api.credentials[:username]).to eq("bob")
321
- end
341
+ let(:priv_header) { 'elevate' }
342
+ let(:headers) { base_headers.merge(x_conjur_privilege: priv_header) }
343
+ it_behaves_like "it can clone itself"
322
344
  end
323
345
 
324
- context "privileged" do
325
- let(:headers) { { authorization: "Token token=\"#{token_encoded}\"", x_forwarded_for: "66.0.0.1" } }
326
- it "can clone itself" do
327
- api = resource.conjur_api
328
- expect(api.credentials[:headers][:authorization]).to eq("Token token=\"#{token_encoded}\"")
329
- expect(api.credentials[:headers][:x_conjur_privilege]).to be_nil
330
- expect(api.credentials[:headers][:x_forwarded_for]).to eq("66.0.0.1")
331
- expect(api.credentials[:username]).to eq("bob")
332
- end
346
+ context "forwarded for" do
347
+ let(:forwarded_for_header) { "66.0.0.1" }
348
+ let(:headers) { base_headers.merge(x_forwarded_for: forwarded_for_header) }
349
+ it_behaves_like 'it can clone itself'
350
+ end
351
+
352
+ context "audit roles" do
353
+ let(:audit_roles_header) { Conjur::API.encode_audit_ids(['account:kind:role1', 'account:kind:role2']) }
354
+ let(:headers) { base_headers.merge(:conjur_audit_roles => audit_roles_header) }
355
+ it_behaves_like 'it can clone itself'
356
+ end
357
+
358
+ context "audit resources" do
359
+ let(:audit_resources_header) { Conjur::API.encode_audit_ids(['account:kind:resource1', 'account:kind:resource2']) }
360
+ let(:headers) { base_headers.merge(:conjur_audit_resources => audit_resources_header) }
361
+ it_behaves_like 'it can clone itself'
333
362
  end
363
+
334
364
  end
335
365
  end
336
366
 
@@ -360,4 +390,21 @@ describe Conjur::API do
360
390
  end
361
391
  end
362
392
  end
393
+
394
+ describe 'url escapes' do
395
+ let(:urls){[
396
+ 'foo/bar@baz',
397
+ '/test/some group with spaces'
398
+ ]}
399
+
400
+ describe '#fully_escape' do
401
+ let(:expected){[
402
+ 'foo%2Fbar%40baz',
403
+ '%2Ftest%2Fsome%20group%20with%20spaces'
404
+ ]}
405
+ it 'escapes the urls correctly' do
406
+ expect(urls.map{|u| Conjur::API.fully_escape u}).to eq(expected)
407
+ end
408
+ end
409
+ end
363
410
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conjur-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.22.1
4
+ version: 4.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafal Rzepecki
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-13 00:00:00.000000000 Z
12
+ date: 2016-04-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -129,6 +129,20 @@ dependencies:
129
129
  - - '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
+ - !ruby/object:Gem::Dependency
133
+ name: aruba
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 0.12.0
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ~>
144
+ - !ruby/object:Gem::Version
145
+ version: 0.12.0
132
146
  - !ruby/object:Gem::Dependency
133
147
  name: cucumber
134
148
  requirement: !ruby/object:Gem::Requirement
@@ -323,9 +337,13 @@ files:
323
337
  - Rakefile
324
338
  - ci/test.sh
325
339
  - conjur-api.gemspec
340
+ - features/audit_resources.feature
341
+ - features/audit_roles.feature
326
342
  - features/bootstrap.feature
327
343
  - features/step_definitions/api_steps.rb
344
+ - features/step_definitions/cli_steps.rb
328
345
  - features/support/env.rb
346
+ - features/support/world.rb
329
347
  - jenkins.sh
330
348
  - lib/conjur-api.rb
331
349
  - lib/conjur-api/version.rb
@@ -459,9 +477,13 @@ signing_key:
459
477
  specification_version: 4
460
478
  summary: Conjur API
461
479
  test_files:
480
+ - features/audit_resources.feature
481
+ - features/audit_roles.feature
462
482
  - features/bootstrap.feature
463
483
  - features/step_definitions/api_steps.rb
484
+ - features/step_definitions/cli_steps.rb
464
485
  - features/support/env.rb
486
+ - features/support/world.rb
465
487
  - spec/api/authn_spec.rb
466
488
  - spec/api/graph_spec.rb
467
489
  - spec/api/groups_spec.rb