conjur-api 4.7.1 → 4.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,6 +20,6 @@
20
20
  #
21
21
  module Conjur
22
22
  class API
23
- VERSION = "4.7.1"
23
+ VERSION = "4.7.2"
24
24
  end
25
25
  end
@@ -17,33 +17,57 @@
17
17
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
18
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+
21
+ require 'conjur/event_source'
20
22
  module Conjur
21
23
  class API
24
+ # Return all events visible to the current authorized role
25
+ def audit options={}, &block
26
+ audit_event_feed "", options, &block
27
+ end
28
+
22
29
  # Return audit events related to the given role_id. Identitical to audit_events
23
30
  # except that a String may be given instead of a Role object.
24
31
  # @param role [String] the role for which events should be returned.
25
- def audit_role role, options={}
26
- audit_event_feed 'role', (role.roleid rescue role), options
27
- end
28
-
29
-
30
- # Return audit events related to the current authenticated role.
31
- def audit_current_role options={}
32
- audit_event_feed 'role', nil, options
32
+ def audit_role role, options={}, &block
33
+ audit_event_feed "roles/#{CGI.escape cast(role, :roleid)}", options, &block
33
34
  end
34
35
 
35
36
  # Return audit events related to the given resource
36
- def audit_resource resource, options={}
37
- audit_event_feed 'resource', (resource.resourceid rescue resource), options
37
+ def audit_resource resource, options={}, &block
38
+ audit_event_feed "resources/#{CGI.escape cast(resource, :resourceid)}", options, &block
38
39
  end
39
40
 
40
41
  private
41
- def audit_event_feed kind, identifier=nil, options={}
42
- path = "feeds/#{kind}"
43
- path << "/#{CGI.escape identifier}" if identifier
44
- query = options.slice(:limit, :offset)
45
- path << "?#{query.to_param}" unless query.empty?
46
- parse_response RestClient::Resource.new(Conjur::Audit::API.host, credentials)[path].get
42
+ def audit_event_feed path, options={}, &block
43
+ query = options.slice(:since, :till)
44
+ path << "?#{query.to_param}" unless query.empty?
45
+ if options[:follow]
46
+ follow_events path, &block
47
+ else
48
+ parse_response(RestClient::Resource.new(Conjur::Audit::API.host, credentials)[path].get).tap do |events|
49
+ block.call(events) if block
50
+ end
51
+ end
52
+ end
53
+
54
+ def follow_events path, &block
55
+ opts = credentials.dup.tap{|h| h[:headers][:accept] = "text/event-stream"}
56
+ block_response = lambda do |response|
57
+ response.error! unless response.code == "200"
58
+ es = EventSource.new
59
+ es.message{ |e| block[e.data] }
60
+ response.read_body do |chunk|
61
+ es.feed chunk
62
+ end
63
+ end
64
+ url = "#{Conjur::Audit::API.host}/#{path}"
65
+ RestClient::Request.execute(
66
+ url: url,
67
+ headers: opts[:headers],
68
+ method: :get,
69
+ block_response: block_response
70
+ )
47
71
  end
48
72
 
49
73
  def parse_response response
@@ -30,12 +30,14 @@ require 'conjur/escape'
30
30
  require 'conjur/log'
31
31
  require 'conjur/log_source'
32
32
  require 'conjur/standard_methods'
33
+ require 'conjur/cast'
33
34
 
34
35
  module Conjur
35
36
  class API
36
37
  include Escape
37
38
  include LogSource
38
39
  include StandardMethods
40
+ include Cast
39
41
 
40
42
  class << self
41
43
  # Parse a role id into [ account, 'roles', kind, id ]
@@ -0,0 +1,88 @@
1
+ module Conjur
2
+ # An EventSource instance is used to parse a stream in the format given by
3
+ # the Server Sent Events standard: http://www.whatwg.org/specs/web-apps/current-work/#server-sent-events
4
+ class EventSource
5
+ class Event < Struct.new(:data, :name, :id);
6
+ end
7
+
8
+ # @!attribute retry [r]
9
+ # @return [Fixnum] the last retry field received, or nil if no retry fields
10
+ # have been received.
11
+ attr_reader :retry
12
+
13
+ # @!attribute last_event_id [r]
14
+ # @return [String] the id of the last fully received event, or nil if no
15
+ # events have been received containing an id field.
16
+ attr_reader :last_event_id
17
+
18
+ # @!attribute json [rw]
19
+ # @return [Boolean] (true) Whether to parse event's data field as JSON.
20
+ attr_accessor :json
21
+ alias json? json
22
+
23
+ def initialize
24
+ @json = true
25
+ @on = {}
26
+ @all = []
27
+ @buffer = ""
28
+ end
29
+
30
+ # Feed a chunk of data to the EventSource and dispatch any fully receieved
31
+ # events.
32
+ # @param [String] chunk the data to parse
33
+ def feed chunk
34
+ @buffer << chunk
35
+
36
+ while i = @buffer.index("\n\n")
37
+ process_event @buffer.slice!(0..i)
38
+ end
39
+ end
40
+
41
+ # Adds a listener for :name:
42
+ def on name, &block
43
+ (@on[name.to_sym] ||= []) << block
44
+ end
45
+
46
+ # Listens to all messages
47
+ def message &block
48
+ @all << block
49
+ end
50
+
51
+ protected
52
+ def process_event s
53
+ data, id, name = [], nil, nil
54
+ s.lines.map(&:chomp).each do |line|
55
+ field, value = case line
56
+ when /^:/ then
57
+ next # comment, do nothing
58
+ when /^(.*?):(.*)$/ then
59
+ [$1, $2]
60
+ else
61
+ [line, ''] # this is what the spec says, I swear!
62
+ end
63
+ # spec allows one optional space after the colon
64
+ value = value[1..-1] if value.start_with? ' '
65
+ case field
66
+ when 'data' then
67
+ data << value
68
+ when 'id' then
69
+ id = value
70
+ when 'event' then
71
+ name = value.to_sym
72
+ when 'retry' then
73
+ @retry = value.to_i
74
+ end
75
+ end
76
+ @last_event_id = id
77
+ dispatch_event(data.join("\n"), id, name) unless data.empty?
78
+ end
79
+
80
+ def dispatch_event data, id, name
81
+ data = JSON.parse(data) if json?
82
+ name = (name || :message).to_sym
83
+ event = Event.new(data, name, id)
84
+ ((@on[name] || []) + @all).each { |p| p.call event }
85
+ end
86
+
87
+ end
88
+ end
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  describe Conjur::API, api: :dummy do
4
4
  describe "audit API methods" do
5
5
 
6
- let(:options){ {limit:20, offset: 51, some_unwanted_option: 'heloo!'} }
7
- let(:expected_options){ options.slice(:limit, :offset) }
6
+ let(:options){ {since:Time.at(0).to_s, till: Time.now.to_s, some_unwanted_option: 'heloo!'} }
7
+ let(:expected_options){ options.slice(:since, :till) }
8
8
  let(:response){ ['some event'] }
9
9
  let(:include_options){ false }
10
10
  let(:query){ include_options ? '?' + expected_options.to_query : '' }
@@ -22,14 +22,37 @@ describe Conjur::API, api: :dummy do
22
22
  end
23
23
 
24
24
 
25
+ describe "#audit" do
26
+ let(:expected_path){ '' }
27
+ let(:args){ [] }
28
+ let(:full_args){ include_options ? args + [options] : args }
29
+
30
+ shared_examples_for "gets all visible events" do
31
+ it "GETs /" do
32
+ expect_request
33
+ api.audit(*full_args).should == response
34
+ end
35
+ end
36
+
37
+ context "when called without options" do
38
+ let(:include_options){ false }
39
+ it_behaves_like "gets all visible events"
40
+ end
41
+
42
+ context "when called with time options" do
43
+ let(:include_options){ true }
44
+ it_behaves_like "gets all visible events"
45
+ end
46
+ end
47
+
25
48
  describe "#audit_role" do
26
49
  let(:role_id){ 'acct:user:foobar' }
27
50
  let(:role){ double('role', roleid: role_id) }
28
- let(:expected_path){ "feeds/role/#{CGI.escape role_id}" }
51
+ let(:expected_path){ "roles/#{CGI.escape role_id}" }
29
52
  let(:args){ [role_id] }
30
53
  let(:full_args){ include_options ? args + [options] : args }
31
54
  shared_examples_for "gets roles feed" do
32
- it "GETs feeds/role/:role_id" do
55
+ it "GETs roles/:role_id" do
33
56
  expect_request
34
57
  api.audit_role(*full_args).should == response
35
58
  end
@@ -45,39 +68,22 @@ describe Conjur::API, api: :dummy do
45
68
  it_behaves_like "gets roles feed"
46
69
  end
47
70
 
48
- context "when called with pagination options" do
71
+ context "when called with time options" do
49
72
  let(:include_options){ true }
50
73
  let(:args){ [ role_id ] }
51
74
  it_behaves_like "gets roles feed"
52
75
  end
53
76
  end
54
77
 
55
- describe "#audit_current_role" do
56
- let(:expected_path){ "feeds/role" }
57
- let(:args){ include_options ? [options] : [] }
58
- shared_examples_for "gets current role feed" do
59
- it "GETS feeds/role" do
60
- expect_request
61
- api.audit_current_role(*args).should == response
62
- end
63
- end
64
- context "when called with no args" do
65
- it_behaves_like "gets current role feed"
66
- end
67
- context "when called with pagination options" do
68
- let(:include_options){ true }
69
- it_behaves_like "gets current role feed"
70
- end
71
- end
72
78
 
73
79
  describe "#audit_resource" do
74
80
  let(:resource_id){ 'acct:food:bacon' }
75
81
  let(:resource){ double('resource', resourceid: resource_id) }
76
- let(:expected_path){ "feeds/resource/#{CGI.escape resource_id}" }
82
+ let(:expected_path){ "resources/#{CGI.escape resource_id}" }
77
83
  let(:args){[resource_id]}
78
84
  let(:full_args){ include_options ? args + [options] : args }
79
85
  shared_examples_for "gets the resource feed" do
80
- it "GETS feeds/resource/:resource_id" do
86
+ it "GETS resources/:resource_id" do
81
87
  expect_request
82
88
  api.audit_resource(*full_args).should == response
83
89
  end
@@ -93,7 +99,7 @@ describe Conjur::API, api: :dummy do
93
99
  it_behaves_like "gets the resource feed"
94
100
  end
95
101
 
96
- context "when called with pagination options" do
102
+ context "when called with time options" do
97
103
  let(:include_options) { true }
98
104
  it_behaves_like "gets the resource feed"
99
105
  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.7.1
4
+ version: 4.7.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-03-14 00:00:00.000000000 Z
13
+ date: 2014-03-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rest-client
@@ -237,6 +237,7 @@ files:
237
237
  - lib/conjur/deputy.rb
238
238
  - lib/conjur/env.rb
239
239
  - lib/conjur/escape.rb
240
+ - lib/conjur/event_source.rb
240
241
  - lib/conjur/exists.rb
241
242
  - lib/conjur/group.rb
242
243
  - lib/conjur/has_attributes.rb
@@ -306,7 +307,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
306
307
  version: '0'
307
308
  segments:
308
309
  - 0
309
- hash: 1666526476905320839
310
+ hash: -3076546680650394555
310
311
  requirements: []
311
312
  rubyforge_project:
312
313
  rubygems_version: 1.8.25