conjur-cli 4.4.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,11 +18,11 @@ class MockAPI
18
18
  else
19
19
  id = SecureRandom.uuid
20
20
  end
21
- host ||= create_thing(:host, id, options, role: true)
21
+ host ||= create_thing(:host, id, options, role: true, api_key: true)
22
22
  end
23
23
 
24
24
  def create_user(id, options = {})
25
- thing(:user, id) || create_thing(:user, id, options, role: true)
25
+ thing(:user, id) || create_thing(:user, id, options, role: true, api_key: true)
26
26
  end
27
27
 
28
28
  def create_variable(mime_type, kind)
@@ -70,6 +70,9 @@ class MockAPI
70
70
  end
71
71
  end
72
72
 
73
+ if kind_options[:api_key]
74
+ thing.api_key = SecureRandom.uuid
75
+ end
73
76
  if kind_options[:role]
74
77
  thing.roleid = id
75
78
  class << thing
@@ -0,0 +1,52 @@
1
+ module Conjur
2
+ module Audit
3
+ class Follower
4
+ # Initialize a follower that will fetch more records by
5
+ # calling :block: with options to merge into the options passed
6
+ # to the audit method (eg, limit, offset)
7
+ def initialize &block
8
+ @fetch = block
9
+ end
10
+
11
+ # Follow audit events, yielding non-empty
12
+ # arrays of new events to :block: as they
13
+ # are fetched.
14
+ def follow &block
15
+ @last_event_id = nil
16
+
17
+ loop do
18
+ new_events = fetch_new_events
19
+ block.call new_events unless new_events.empty?
20
+ sleep 1 if new_events.empty?
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ # Fetch all events after @last_event_id, updating it
27
+ # to point to the last event returned by this method.
28
+ # May return an empty array if no new events are available.
29
+ def fetch_new_events
30
+ # If @last_event_id is nil just fetch and return the
31
+ # most recent events, updating @last_event_id
32
+ if @last_event_id.nil?
33
+ events = @fetch.call(offset: 0)
34
+ @last_event_id = events.last['event_id'] unless events.empty?
35
+ return events
36
+ end
37
+
38
+ # We have a @last_event_id, fetch batches of events until we
39
+ # find it.
40
+ events = []
41
+ while (index = events.find_index{|e| e['event_id'] == @last_event_id}).nil?
42
+ events = @fetch.call(offset: events.length - 1, limit: 10).reverse.concat events
43
+ end
44
+
45
+ # Update @last_event_id and return the sliced events, reversing it one
46
+ # last time (because the block given to follow expects events to be reversed)
47
+ @last_event_id = events.last['event_id'] unless events.empty?
48
+ events[index + 1..-1].reverse
49
+ end
50
+ end
51
+ end
52
+ end
@@ -43,7 +43,11 @@ module Conjur::Authn
43
43
  end
44
44
 
45
45
  def netrc
46
- @netrc ||= Netrc.read
46
+ args = []
47
+ if path = Conjur::Config[:netrc_path]
48
+ args.unshift(path)
49
+ end
50
+ @netrc ||= Netrc.read(*args)
47
51
  end
48
52
 
49
53
  def get_credentials(options = {})
@@ -1,5 +1,6 @@
1
1
  require 'conjur/command'
2
2
  require 'active_support/ordered_hash'
3
+ require 'conjur/audit/follower'
3
4
 
4
5
  class Conjur::Command
5
6
  class Audit < self
@@ -7,6 +8,40 @@ class Conjur::Command
7
8
 
8
9
  class << self
9
10
  private
11
+ SHORT_FORMATS = {
12
+ 'resource:check' => lambda{|e| "checked that they can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
13
+ 'resource:create' => lambda{|e| "created resource #{e[:resource_id]} owned by #{e[:owner]}" },
14
+ 'resource:update' => lambda{|e| "gave #{e[:resource]} to #{e[:owner]}" },
15
+ 'resource:destroy' => lambda{|e| "destroyed resource #{e[:resource]}" },
16
+ 'resource:permit' => lambda{|e| "permitted #{e[:grantee]} to #{e[:privilege]} #{e[:resource]} (grant option: #{!!e[:grant_option]})" },
17
+ 'resource:deny' => lambda{|e| "denied #{e[:privilege]} from #{e[:grantee]} on #{e[:resource]}" },
18
+ 'resource:permitted_roles' => lambda{|e| "listed roles permitted to #{e[:permission]} on #{e[:resource]}" },
19
+ 'role:check' => lambda{|e| "checked that #{e[:role] == e[:conjur_user] ? 'they' : e[:role]} can #{e[:privilege]} #{e[:resource]} (#{e[:allowed]})" },
20
+ 'role:grant' => lambda{|e| "granted role #{e[:role]} to #{e[:member]} #{e[:admin_option] ? ' with ' : ' without '}admin" },
21
+ 'role:revoke' => lambda{|e| "revoked role #{e[:role]} from #{e[:member]}" },
22
+ 'role:create' => lambda{|e| "created role #{e[:role_id]}" }
23
+ }
24
+
25
+
26
+ def short_event_format e
27
+ e.symbolize_keys!
28
+ # hack: sometimes resource is a hash. We don't want that!
29
+ if e[:resource] && e[:resource].kind_of?(Hash)
30
+ e[:resource] = e[:resource]['id']
31
+ end
32
+ s = "[#{Time.at(e[:timestamp])}] "
33
+ s << " #{e[:conjur_user]}"
34
+ s << " (as #{e[:conjur_role]})" if e[:conjur_role] != e[:conjur_user]
35
+ formatter = SHORT_FORMATS["#{e[:asset]}:#{e[:action]}"]
36
+ if formatter
37
+ s << " " << formatter.call(e)
38
+ else
39
+ s << " unknown event: #{e[:asset]}:#{e[:action]}!"
40
+ end
41
+ s << " (failed with #{e[:error]})" if e[:error]
42
+ s
43
+ end
44
+
10
45
  def extract_int_option(source, name, dest=nil)
11
46
  if val = source[name]
12
47
  raise "Expected an integer for #{name}, but got #{val}" unless /\d+/ =~ val
@@ -15,15 +50,24 @@ class Conjur::Command
15
50
  end
16
51
 
17
52
  def extract_audit_options options
18
- {}.tap do |opts|
19
- [:limit, :offset].each do |name|
20
- extract_int_option(options, name, opts)
21
- end
53
+ # Do a little song and dance to simplify testing
54
+ extracted = options.slice :follow, :short
55
+ [:limit, :offset].each do |name|
56
+ extract_int_option(options, name, extracted)
22
57
  end
58
+ if extracted[:follow] && extracted[:offset]
59
+ exit_now! "--offset option not allowed for --follow", 1
60
+ end
61
+ extracted
23
62
  end
24
63
 
25
- def show_audit_events events
26
- puts JSON.pretty_generate(events)
64
+ def show_audit_events events, options
65
+ events.reverse!
66
+ if options[:short]
67
+ events.each{|e| puts short_event_format(e)}
68
+ else
69
+ puts JSON.pretty_generate(events)
70
+ end
27
71
  end
28
72
 
29
73
  def audit_feed_command kind, &block
@@ -34,9 +78,23 @@ class Conjur::Command
34
78
  c.desc "Offset of the first event to return"
35
79
  c.flag [:o, :offset]
36
80
 
81
+ c.desc "Short output format"
82
+ c.switch [:s, :short]
83
+
84
+ c.desc "Follow events as they are generated"
85
+ c.switch [:f, :follow]
86
+
37
87
  c.action do |global_options, options, args|
38
- opts = extract_audit_options options
39
- show_audit_events instance_exec(args, opts, &block)
88
+ options = extract_audit_options options
89
+ if options[:follow]
90
+ Conjur::Audit::Follower.new do |merge_options|
91
+ instance_exec(args, options.merge(merge_options), &block)
92
+ end.follow do |events|
93
+ show_audit_events events, options
94
+ end
95
+ else
96
+ show_audit_events instance_exec(args, options, &block), options
97
+ end
40
98
  end
41
99
  end
42
100
  end
@@ -93,8 +93,10 @@ module Conjur
93
93
 
94
94
  def create_variable id = nil, options = {}, &block
95
95
  options[:id] = id if id
96
- mime_type = options.delete(:mime_type)
97
- kind = options.delete(:kind)
96
+ mime_type = options.delete(:mime_type) || 'text/plain'
97
+ kind = options.delete(:kind) || 'secret'
98
+ var = api.create_variable(mime_type, kind, options)
99
+ do_object var, &block
98
100
  end
99
101
 
100
102
  def owns
@@ -19,5 +19,5 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
- VERSION = "4.4.0"
22
+ VERSION = "4.5.0"
23
23
  end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Conjur::Audit::Follower do
4
+
5
+ end
@@ -0,0 +1,28 @@
1
+ require 'conjur/authn'
2
+ require 'conjur/config'
3
+
4
+ describe Conjur::Authn do
5
+ describe "netrc" do
6
+ before {
7
+ Conjur::Authn.instance_variable_set("@netrc", nil)
8
+ Conjur::Config.should_receive(:[]).with(:netrc_path).and_return path
9
+ }
10
+ after {
11
+ Conjur::Authn.instance_variable_set("@netrc", nil)
12
+ }
13
+ context "with specified netrc_path" do
14
+ let(:path) { double("path") }
15
+ it "consults Conjur::Config for netrc_path" do
16
+ Netrc.should_receive(:read).with(path).and_return netrc = double("netrc")
17
+ Conjur::Authn.netrc.should == netrc
18
+ end
19
+ end
20
+ context "without specified netrc_path" do
21
+ let(:path) { nil }
22
+ it "uses default netrc path" do
23
+ Netrc.should_receive(:read).with().and_return netrc = double("netrc")
24
+ Conjur::Authn.netrc.should == netrc
25
+ end
26
+ end
27
+ end
28
+ end
@@ -5,7 +5,7 @@ describe Conjur::Command::Audit, logged_in: true do
5
5
 
6
6
  def expect_api_call method, *args
7
7
  api.should_receive(method.to_sym).with(*args).and_return events
8
- described_class.should_receive(:show_audit_events).with(events)
8
+ described_class.should_receive(:show_audit_events).with(events, an_instance_of(Hash))
9
9
  end
10
10
 
11
11
  def invoke_expecting_api_call method, *args
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conjur-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
4
+ version: 4.5.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Rafał Rzepecki
@@ -9,151 +10,172 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-12-24 00:00:00.000000000 Z
13
+ date: 2014-01-14 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: conjur-api
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
- - - '>='
20
+ - - ! '>='
19
21
  - !ruby/object:Gem::Version
20
22
  version: '4.0'
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
- - - '>='
28
+ - - ! '>='
26
29
  - !ruby/object:Gem::Version
27
30
  version: '4.0'
28
31
  - !ruby/object:Gem::Dependency
29
32
  name: gli
30
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
31
35
  requirements:
32
- - - '>='
36
+ - - ! '>='
33
37
  - !ruby/object:Gem::Version
34
38
  version: '0'
35
39
  type: :runtime
36
40
  prerelease: false
37
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
38
43
  requirements:
39
- - - '>='
44
+ - - ! '>='
40
45
  - !ruby/object:Gem::Version
41
46
  version: '0'
42
47
  - !ruby/object:Gem::Dependency
43
48
  name: highline
44
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
45
51
  requirements:
46
- - - '>='
52
+ - - ! '>='
47
53
  - !ruby/object:Gem::Version
48
54
  version: '0'
49
55
  type: :runtime
50
56
  prerelease: false
51
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
52
59
  requirements:
53
- - - '>='
60
+ - - ! '>='
54
61
  - !ruby/object:Gem::Version
55
62
  version: '0'
56
63
  - !ruby/object:Gem::Dependency
57
64
  name: netrc
58
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
59
67
  requirements:
60
- - - '>='
68
+ - - ! '>='
61
69
  - !ruby/object:Gem::Version
62
70
  version: '0'
63
71
  type: :runtime
64
72
  prerelease: false
65
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
66
75
  requirements:
67
- - - '>='
76
+ - - ! '>='
68
77
  - !ruby/object:Gem::Version
69
78
  version: '0'
70
79
  - !ruby/object:Gem::Dependency
71
80
  name: methadone
72
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
73
83
  requirements:
74
- - - '>='
84
+ - - ! '>='
75
85
  - !ruby/object:Gem::Version
76
86
  version: '0'
77
87
  type: :runtime
78
88
  prerelease: false
79
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
80
91
  requirements:
81
- - - '>='
92
+ - - ! '>='
82
93
  - !ruby/object:Gem::Version
83
94
  version: '0'
84
95
  - !ruby/object:Gem::Dependency
85
96
  name: deep_merge
86
97
  requirement: !ruby/object:Gem::Requirement
98
+ none: false
87
99
  requirements:
88
- - - '>='
100
+ - - ! '>='
89
101
  - !ruby/object:Gem::Version
90
102
  version: '0'
91
103
  type: :runtime
92
104
  prerelease: false
93
105
  version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
94
107
  requirements:
95
- - - '>='
108
+ - - ! '>='
96
109
  - !ruby/object:Gem::Version
97
110
  version: '0'
98
111
  - !ruby/object:Gem::Dependency
99
112
  name: cas_rest_client
100
113
  requirement: !ruby/object:Gem::Requirement
114
+ none: false
101
115
  requirements:
102
- - - '>='
116
+ - - ! '>='
103
117
  - !ruby/object:Gem::Version
104
118
  version: '0'
105
119
  type: :runtime
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
108
123
  requirements:
109
- - - '>='
124
+ - - ! '>='
110
125
  - !ruby/object:Gem::Version
111
126
  version: '0'
112
127
  - !ruby/object:Gem::Dependency
113
128
  name: rspec
114
129
  requirement: !ruby/object:Gem::Requirement
130
+ none: false
115
131
  requirements:
116
- - - '>='
132
+ - - ! '>='
117
133
  - !ruby/object:Gem::Version
118
134
  version: '0'
119
135
  type: :development
120
136
  prerelease: false
121
137
  version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
122
139
  requirements:
123
- - - '>='
140
+ - - ! '>='
124
141
  - !ruby/object:Gem::Version
125
142
  version: '0'
126
143
  - !ruby/object:Gem::Dependency
127
144
  name: simplecov
128
145
  requirement: !ruby/object:Gem::Requirement
146
+ none: false
129
147
  requirements:
130
- - - '>='
148
+ - - ! '>='
131
149
  - !ruby/object:Gem::Version
132
150
  version: '0'
133
151
  type: :development
134
152
  prerelease: false
135
153
  version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
136
155
  requirements:
137
- - - '>='
156
+ - - ! '>='
138
157
  - !ruby/object:Gem::Version
139
158
  version: '0'
140
159
  - !ruby/object:Gem::Dependency
141
160
  name: aruba
142
161
  requirement: !ruby/object:Gem::Requirement
162
+ none: false
143
163
  requirements:
144
- - - '>='
164
+ - - ! '>='
145
165
  - !ruby/object:Gem::Version
146
166
  version: '0'
147
167
  type: :development
148
168
  prerelease: false
149
169
  version_requirements: !ruby/object:Gem::Requirement
170
+ none: false
150
171
  requirements:
151
- - - '>='
172
+ - - ! '>='
152
173
  - !ruby/object:Gem::Version
153
174
  version: '0'
154
175
  - !ruby/object:Gem::Dependency
155
176
  name: ci_reporter
156
177
  requirement: !ruby/object:Gem::Requirement
178
+ none: false
157
179
  requirements:
158
180
  - - ~>
159
181
  - !ruby/object:Gem::Version
@@ -161,6 +183,7 @@ dependencies:
161
183
  type: :development
162
184
  prerelease: false
163
185
  version_requirements: !ruby/object:Gem::Requirement
186
+ none: false
164
187
  requirements:
165
188
  - - ~>
166
189
  - !ruby/object:Gem::Version
@@ -168,6 +191,7 @@ dependencies:
168
191
  - !ruby/object:Gem::Dependency
169
192
  name: rake
170
193
  requirement: !ruby/object:Gem::Requirement
194
+ none: false
171
195
  requirements:
172
196
  - - ~>
173
197
  - !ruby/object:Gem::Version
@@ -175,6 +199,7 @@ dependencies:
175
199
  type: :development
176
200
  prerelease: false
177
201
  version_requirements: !ruby/object:Gem::Requirement
202
+ none: false
178
203
  requirements:
179
204
  - - ~>
180
205
  - !ruby/object:Gem::Version
@@ -212,6 +237,7 @@ files:
212
237
  - features/support/env.rb
213
238
  - features/support/hooks.rb
214
239
  - lib/conjur.rb
240
+ - lib/conjur/audit/follower.rb
215
241
  - lib/conjur/authn.rb
216
242
  - lib/conjur/cli.rb
217
243
  - lib/conjur/command.rb
@@ -236,6 +262,8 @@ files:
236
262
  - lib/conjur/dsl/runner.rb
237
263
  - lib/conjur/identifier_manipulation.rb
238
264
  - lib/conjur/version.rb
265
+ - spec/audit/follower_spec.rb
266
+ - spec/authn_spec.rb
239
267
  - spec/command/assets_spec.rb
240
268
  - spec/command/audit_spec.rb
241
269
  - spec/command/authn_spec.rb
@@ -251,26 +279,33 @@ files:
251
279
  homepage: https://github.com/inscitiv/cli-ruby
252
280
  licenses:
253
281
  - MIT
254
- metadata: {}
255
282
  post_install_message:
256
283
  rdoc_options: []
257
284
  require_paths:
258
285
  - lib
259
286
  required_ruby_version: !ruby/object:Gem::Requirement
287
+ none: false
260
288
  requirements:
261
- - - '>='
289
+ - - ! '>='
262
290
  - !ruby/object:Gem::Version
263
291
  version: '0'
292
+ segments:
293
+ - 0
294
+ hash: 1871278325472077316
264
295
  required_rubygems_version: !ruby/object:Gem::Requirement
296
+ none: false
265
297
  requirements:
266
- - - '>='
298
+ - - ! '>='
267
299
  - !ruby/object:Gem::Version
268
300
  version: '0'
301
+ segments:
302
+ - 0
303
+ hash: 1871278325472077316
269
304
  requirements: []
270
305
  rubyforge_project:
271
- rubygems_version: 2.0.3
306
+ rubygems_version: 1.8.25
272
307
  signing_key:
273
- specification_version: 4
308
+ specification_version: 3
274
309
  summary: Conjur command line interface
275
310
  test_files:
276
311
  - features/dsl_context.feature
@@ -284,6 +319,8 @@ test_files:
284
319
  - features/step_definitions/dsl_steps.rb
285
320
  - features/support/env.rb
286
321
  - features/support/hooks.rb
322
+ - spec/audit/follower_spec.rb
323
+ - spec/authn_spec.rb
287
324
  - spec/command/assets_spec.rb
288
325
  - spec/command/audit_spec.rb
289
326
  - spec/command/authn_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 873f90a23b9e22be41441f80c9086f5c005137fe
4
- data.tar.gz: 7c6d8a46e66a871415dc3085bc28ef6551c30289
5
- SHA512:
6
- metadata.gz: efe1fdb784cd353cbf45d0b60ab4744bc5bdd83c9ee333257e4ca0515b4e486426edd03645a125b349443729c241a18e42966adb773fd11b9ab533a9eab56a01
7
- data.tar.gz: 5bec66f78fdccf45d679b2f58a8f4c7cec8e2a65d2bafe116b8e266832b9590fc6c50200278b806b22847664a41a53a03bdd601107bb9fc6a47f74630ac87664