conjur-api 4.7.1 → 4.7.2

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.
@@ -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