conjur-api 4.19.1 → 4.20.0

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.
@@ -65,4 +65,17 @@ describe Conjur::API do
65
65
  expect(Conjur::API.update_password(user, password, 'new-password')).to eq(:response)
66
66
  end
67
67
  end
68
+
69
+ describe '::rotate_api_key' do
70
+ it 'puts with basic auth' do
71
+ expect_request(
72
+ method: :put,
73
+ url: 'http://authn.example.com/users/api_key',
74
+ user: user,
75
+ password: password,
76
+ headers: { }
77
+ ).and_return double('response', body: 'new api key')
78
+ expect(Conjur::API.rotate_api_key user, password).to eq('new api key')
79
+ end
80
+ end
68
81
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'standard_methods_helper'
3
+ require 'cidr_helper'
3
4
 
4
5
  describe Conjur::API, api: :dummy do
5
6
  describe '::enroll_host' do
@@ -16,10 +17,17 @@ describe Conjur::API, api: :dummy do
16
17
  end
17
18
 
18
19
  describe '#create_host' do
19
- it_should_behave_like "standard_create with", :host, nil, :options do
20
- let(:invoke) { subject.create_host :options }
20
+ it_should_behave_like "standard_create with", :host, nil, some: :options do
21
+ let(:invoke) { subject.create_host some: :options }
22
+ end
23
+
24
+ include_examples 'CIDR create' do
25
+ def create opts
26
+ api.create_host opts
27
+ end
21
28
  end
22
29
  end
30
+
23
31
  describe '#host' do
24
32
  it_should_behave_like "standard_show with", :host, :id do
25
33
  let(:invoke) { subject.host :id }
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+ require 'standard_methods_helper'
3
+
4
+ describe Conjur::API, api: :dummy do
5
+ before do
6
+ # The standard test setup doesn't do this
7
+ allow(Conjur.configuration).to receive(:appliance_url).and_return 'https://example.com/api'
8
+ end
9
+
10
+ let(:version_string) { '4.5.0-75-gde404a6' }
11
+ let(:response_json){
12
+ {
13
+ 'services' => {
14
+ 'authn' => {
15
+ 'version' => version_string
16
+ }
17
+ }
18
+ }
19
+ }
20
+ let(:response){ double('response', body: response_json.to_json) }
21
+
22
+ describe '+appliance_info' do
23
+ subject{ Conjur::API.appliance_info }
24
+ context 'when /info does not exist' do
25
+ it 'raises a FeatureNotAvailable exception' do
26
+ expect_request(
27
+ method: :get,
28
+ url: 'https://example.com/info'
29
+ ).and_raise RestClient::ResourceNotFound
30
+ expect{ subject }.to raise_error(Conjur::FeatureNotAvailable)
31
+ end
32
+ end
33
+
34
+ context 'when /info exists' do
35
+ it 'returns the response json' do
36
+ expect_request(
37
+ method: :get,
38
+ url: 'https://example.com/info'
39
+ ).and_return response
40
+
41
+ expect(subject).to eq(response_json)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '+service_names' do
47
+ subject{ Conjur::API.service_names }
48
+ it 'returns the service names' do
49
+ expect_request(
50
+ method: :get,
51
+ url: 'https://example.com/info'
52
+ ).and_return response
53
+ expect(subject).to eq(%w(authn))
54
+ end
55
+ end
56
+
57
+ describe '+service_version' do
58
+ subject{ Conjur::API.service_version(service)}
59
+ context 'when the service name is valid' do
60
+ let(:service){'authn'}
61
+ let(:expected_version){ "4.5.0".to_version }
62
+ before {
63
+ expect_request(
64
+ method: :get,
65
+ url: 'https://example.com/info'
66
+ ).at_least(1).times.and_return response
67
+ }
68
+ it 'returns the version as a Semantic::Version' do
69
+ expect(subject).to eq(expected_version)
70
+ end
71
+ describe 'can be compared' do
72
+ it 'returns the version as a Semantic::Version' do
73
+ expect(subject >= Semantic::Version.new('4.5.0')).to eq(true)
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when the service name is not valid' do
79
+ let(:service){'blahblah'}
80
+ it 'raises an exception' do
81
+ expect_request(
82
+ method: :get,
83
+ url: 'https://example.com/info'
84
+ ).at_least(1).times.and_return response
85
+ expect{ subject }.to raise_error(RuntimeError, /Unknown service/i)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,11 +1,32 @@
1
1
  require 'spec_helper'
2
2
  require 'standard_methods_helper'
3
+ require 'cidr_helper'
3
4
 
4
5
  describe Conjur::API, api: :dummy do
5
6
  describe '#create_user' do
6
7
  it_should_behave_like 'standard_create with', :user, nil, login: 'login', other: true do
7
8
  let(:invoke) { api.create_user 'login', other: true }
8
9
  end
10
+
11
+ include_examples 'CIDR create' do
12
+ def create opts
13
+ api.create_user 'login', opts
14
+ end
15
+ end
16
+ end
17
+
18
+ describe 'user#rotate_api_key' do
19
+ let(:userid){ 'alice@wonderland' }
20
+ let(:new_api_key){ 'new api key' }
21
+ it 'PUTS to /authn/users/api_key?id=:userid' do
22
+ expect_request(
23
+ method: :put,
24
+ url: "#{authn_host}/users/api_key?id=#{api.fully_escape userid}",
25
+ headers: credentials[:headers],
26
+ payload: ''
27
+ ).and_return double('response', body: new_api_key)
28
+ expect(api.user(userid).rotate_api_key).to eq(new_api_key)
29
+ end
9
30
  end
10
31
 
11
32
  describe 'user#update' do
@@ -13,6 +13,25 @@ describe Conjur::API, api: :dummy do
13
13
  it_should_behave_like 'standard_show with', :variable, :id
14
14
  end
15
15
 
16
+
17
+ let (:expected_url) { nil }
18
+ let (:expected_headers) { {} }
19
+ shared_context "Stubbed API" do
20
+ before {
21
+ expect_request(
22
+ method: :get,
23
+ url: expected_url,
24
+ headers: credentials[:headers].merge(expected_headers)
25
+ ) {
26
+ if defined? return_error
27
+ raise return_error
28
+ else
29
+ double( code: return_code, body: return_body )
30
+ end
31
+ }
32
+ }
33
+ end
34
+
16
35
  describe "#variable_values" do
17
36
 
18
37
  let (:varlist) { ["var/1","var/2","var/3" ] }
@@ -22,22 +41,7 @@ describe Conjur::API, api: :dummy do
22
41
  expect { api.variable_values([]) }.to raise_exception(ArgumentError)
23
42
  end
24
43
 
25
- shared_context "Stubbed API" do
26
- let (:expected_url) { "#{core_host}/variables/values?vars=#{varlist.map {|v| api.fully_escape(v) }.join(",")}" }
27
- before {
28
- expect_request(
29
- method: :get,
30
- url: expected_url,
31
- headers: credentials[:headers]
32
- ) {
33
- if defined? return_error
34
- raise return_error
35
- else
36
- double( code: return_code, body: return_body )
37
- end
38
- }
39
- }
40
- end
44
+ let (:expected_url) { "#{core_host}/variables/values?vars=#{varlist.map {|v| api.fully_escape(v) }.join(",")}" }
41
45
 
42
46
  let (:invoke) { api.variable_values(varlist) }
43
47
 
@@ -78,4 +82,31 @@ describe Conjur::API, api: :dummy do
78
82
 
79
83
  end
80
84
 
85
+ describe '#variable_expirations' do
86
+ include_context "Stubbed API"
87
+ let (:expected_url) { "#{core_host}/variables/expirations" }
88
+ let (:return_code) { '200' }
89
+ let (:return_body) { '[]' }
90
+
91
+ context "with no interval" do
92
+ subject {api.variable_expirations}
93
+ it { is_expected.to eq([]) }
94
+ end
95
+
96
+ context "with Fixnum interval" do
97
+ let (:interval) { 2.weeks }
98
+ let (:expected_headers) { {:params => { :duration => "PT#{interval.to_i}S" } } }
99
+ subject { api.variable_expirations(2.weeks) }
100
+ it { is_expected.to eq([]) }
101
+ end
102
+
103
+ context "with String interval" do
104
+ let (:interval) { 'P2W' }
105
+ let (:expected_headers) { {:params => { :duration => 'P2W' } } }
106
+ subject { api.variable_expirations('P2W') }
107
+ it { is_expected.to eq([]) }
108
+ end
109
+
110
+ end
111
+
81
112
  end
@@ -0,0 +1,24 @@
1
+ shared_examples_for "CIDR create" do
2
+ it "formats the CIDRs correctly" do
3
+ cidrs = %w(192.0.2.0/24 198.51.100.0/24)
4
+ expect do
5
+ create cidr: cidrs.map(&IPAddr.method(:new))
6
+ end.to call_standard_create_with anything, anything, hash_including(cidr: cidrs)
7
+ end
8
+
9
+ it "parses addresses given as strings" do
10
+ expect do
11
+ create cidr: %w(192.0.2.0/255.255.255.128)
12
+ end.to call_standard_create_with anything, anything, hash_including(cidr: %w(192.0.2.0/25))
13
+ end
14
+
15
+ it "raises ArgumentError on invalid CIDR" do
16
+ expect do
17
+ create cidr: %w(192.0.2.0/255.255.0.255)
18
+ end.to raise_error ArgumentError
19
+
20
+ expect do
21
+ create cidr: %w(192.0.2.256/1)
22
+ end.to raise_error ArgumentError
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ describe Conjur::ActsAsUser, api: :dummy do
2
+ subject do
3
+ api.user 'kmitnick'
4
+ end
5
+
6
+ describe '#set_cidr_restrictions' do
7
+ it "sends the new restrictions to the authn server" do
8
+ expect_request(
9
+ headers: hash_including(content_type: :json),
10
+ url: "http://authn.example.com/users?id=kmitnick",
11
+ method: :put,
12
+ payload: { cidr: ['192.0.2.1/32'] }.to_json
13
+ )
14
+ subject.set_cidr_restrictions %w(192.0.2.1)
15
+ end
16
+
17
+ it "resets the restrictions on the authn server if given empty cidr string" do
18
+ expect_request(
19
+ headers: hash_including(content_type: :json),
20
+ url: "http://authn.example.com/users?id=kmitnick",
21
+ method: :put,
22
+ payload: { cidr: [] }.to_json
23
+ )
24
+ subject.set_cidr_restrictions []
25
+ end
26
+ end
27
+ end
data/spec/lib/api_spec.rb CHANGED
@@ -55,13 +55,13 @@ describe Conjur::API do
55
55
  let (:kind) { "sample-kind" }
56
56
 
57
57
  it "fails on non-string ids" do
58
- expect { subject.parse_id({}, kind) }.to raise_error
58
+ expect { subject.parse_id({}, kind) }.to raise_error /Unexpected class/
59
59
  end
60
60
 
61
61
  it "fails on malformed ids (<2 tokens)" do
62
- expect { subject.parse_id("foo", kind) }.to raise_error
63
- expect { subject.parse_id("", kind) }.to raise_error
64
- expect { subject.parse_id(nil, kind) }.to raise_error
62
+ expect { subject.parse_id("foo", kind) }.to raise_error /Expecting at least two /
63
+ expect { subject.parse_id("", kind) }.to raise_error /Expecting at least two /
64
+ expect { subject.parse_id(nil, kind) }.to raise_error /Unexpected class/
65
65
  end
66
66
 
67
67
  describe "returns array of [account, kind, subkind, id]" do
@@ -102,5 +102,54 @@ describe Conjur::API, api: :dummy do
102
102
  it_behaves_like "gets the resource feed"
103
103
  end
104
104
  end
105
+
106
+ describe "#audit_send" do
107
+ let(:username) { "user" }
108
+ let(:api){ Conjur::API.new_from_key username, 'key' }
109
+ let(:credentials) { { headers: { authorization: "Token token=\"stub\"" } } } #, username: username } }
110
+
111
+ before do
112
+ allow(api).to receive_messages credentials: credentials
113
+ end
114
+
115
+ context "valid input" do
116
+ let(:http_parameters) {
117
+ {
118
+ headers: credentials[:headers].merge(content_type: "text/plain"),
119
+ method: :post ,
120
+ url: "#{Conjur::Authz::API.host}/audit"
121
+ }
122
+ }
123
+
124
+ it "sends Hash as JSON" do
125
+ event = { action: "login", user: "alice" }
126
+ expect(RestClient::Request).to receive(:execute).with(
127
+ http_parameters.merge( payload: event.to_json )
128
+ )
129
+ api.audit_send event
130
+ end
131
+ it "sends array as JSON" do
132
+ events = [ { action: "login", user: "alice" }, { action: "sudo", user: "alice" } ]
133
+ expect(RestClient::Request).to receive(:execute).with(
134
+ http_parameters.merge( payload: events.to_json )
135
+ )
136
+ api.audit_send events
137
+ end
138
+
139
+ it "sends string as is (consider it preformatted JSON)" do
140
+ events_serialized = "this is supposed to be JSON"
141
+ expect(RestClient::Request).to receive(:execute).with(
142
+ http_parameters.merge( payload: events_serialized )
143
+ )
144
+ api.audit_send events_serialized
145
+ end
146
+ end
147
+
148
+ it "rejects any other types of arguments" do
149
+ expect { api.audit_send( api ) }.to raise_error(ArgumentError)
150
+ end
151
+
152
+ end
105
153
  end
106
154
  end
155
+
@@ -0,0 +1,34 @@
1
+ require 'conjur/cidr'
2
+
3
+ describe Conjur::CIDR do
4
+ def cidr addr
5
+ Conjur::CIDR.validate addr
6
+ end
7
+
8
+ describe '.validate' do
9
+ it 'rejects malformed addresses' do
10
+ expect { Conjur::CIDR.validate '192.0.2.2/255.255.0.255' }.to raise_error ArgumentError
11
+ expect { Conjur::CIDR.validate '192.0.2.2/0.255.0.0' }.to raise_error ArgumentError
12
+ expect { Conjur::CIDR.validate '192.0.256.2' }.to raise_error ArgumentError
13
+ expect { Conjur::CIDR.validate '::/:ffff:' }.to raise_error ArgumentError
14
+ end
15
+ end
16
+
17
+ describe '#prefixlen' do
18
+ it 'calculates prefix mask length' do
19
+ expected = {
20
+ '0.0.0.0/0' => 0,
21
+ '192.0.2.0/24' => 24,
22
+ '192.0.2.1' => 32,
23
+ '192.0.2.0/255.255.255.0' => 24,
24
+ '10.0.0.0/255.0.0.0' => 8,
25
+ '1234::/42' => 42,
26
+ '1234::/ffff::' => 16,
27
+ '::/::' => 0,
28
+ }
29
+ expected.each do |addr, len|
30
+ expect(Conjur::CIDR.validate(addr).prefixlen).to eq len
31
+ end
32
+ end
33
+ end
34
+ end
@@ -301,10 +301,12 @@ CERT
301
301
 
302
302
 
303
303
  it 'does not rescue from other exceptions' do
304
- expect(store).to receive(:add_cert).with(cert).once.and_raise(OpenSSL::X509::StoreError.new('some other message'))
305
- expect{subject}.to raise_exception
306
- expect(store).to receive(:add_cert).with(cert).once.and_raise(ArgumentError.new('bad news'))
307
- expect{subject}.to raise_exception
304
+ exn = OpenSSL::X509::StoreError.new('some other message')
305
+ expect(store).to receive(:add_cert).with(cert).once.and_raise(exn)
306
+ expect{subject}.to raise_error exn
307
+ exn = ArgumentError.new('bad news')
308
+ expect(store).to receive(:add_cert).with(cert).once.and_raise(exn)
309
+ expect{subject}.to raise_error exn
308
310
  end
309
311
  end
310
312
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Conjur::Host, api: :dummy do
4
- subject { Conjur::Host.new 'http://example.com/hosts/my%2Fhostname', nil }
4
+ subject(:host) { Conjur::Host.new 'http://example.com/hosts/my%2Fhostname', nil }
5
5
 
6
6
  describe '#resource' do
7
7
  subject { super().resource }
@@ -18,4 +18,14 @@ describe Conjur::Host, api: :dummy do
18
18
  to_return(:status => 200, :headers => {location: 'foo'})
19
19
  expect(subject.enrollment_url).to eq('foo')
20
20
  end
21
+
22
+ describe '#update' do
23
+ it "calls set_cidr_restrictions if given CIDR" do
24
+ expect(host).to receive(:set_cidr_restrictions).with(['192.0.2.0/24'])
25
+ host.update cidr: ['192.0.2.0/24']
26
+
27
+ expect(host).to_not receive(:set_cidr_restrictions)
28
+ host.update foo: 42
29
+ end
30
+ end
21
31
  end