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.
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur/api/audit.rb +40 -16
- data/lib/conjur/base.rb +2 -0
- data/lib/conjur/event_source.rb +88 -0
- data/spec/lib/audit_spec.rb +31 -25
- metadata +4 -3
data/lib/conjur-api/version.rb
CHANGED
data/lib/conjur/api/audit.rb
CHANGED
@@ -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
|
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
|
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
|
42
|
-
|
43
|
-
path << "
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
data/lib/conjur/base.rb
CHANGED
@@ -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
|
data/spec/lib/audit_spec.rb
CHANGED
@@ -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){ {
|
7
|
-
let(:expected_options){ options.slice(:
|
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){ "
|
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
|
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
|
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){ "
|
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
|
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
|
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.
|
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-
|
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:
|
310
|
+
hash: -3076546680650394555
|
310
311
|
requirements: []
|
311
312
|
rubyforge_project:
|
312
313
|
rubygems_version: 1.8.25
|