conjur-api 4.19.1 → 4.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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