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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Dockerfile +4 -0
- data/Gemfile +1 -0
- data/conjur-api.gemspec +3 -0
- data/jenkins.sh +11 -0
- data/lib/conjur-api/version.rb +2 -2
- data/lib/conjur/acts_as_user.rb +28 -1
- data/lib/conjur/api.rb +3 -0
- data/lib/conjur/api/audit.rb +14 -1
- data/lib/conjur/api/authn.rb +29 -0
- data/lib/conjur/api/host_factories.rb +93 -0
- data/lib/conjur/api/hosts.rb +4 -2
- data/lib/conjur/api/info.rb +126 -0
- data/lib/conjur/api/users.rb +6 -1
- data/lib/conjur/api/variables.rb +24 -0
- data/lib/conjur/cidr.rb +71 -0
- data/lib/conjur/exceptions.rb +4 -0
- data/lib/conjur/host-factory-api.rb +38 -0
- data/lib/conjur/host.rb +21 -2
- data/lib/conjur/host_factory.rb +75 -0
- data/lib/conjur/host_factory_token.rb +63 -0
- data/lib/conjur/resource.rb +1 -1
- data/lib/conjur/user.rb +19 -11
- data/lib/conjur/variable.rb +25 -2
- data/spec/api/authn_spec.rb +13 -0
- data/spec/api/hosts_spec.rb +10 -2
- data/spec/api/info_spec.rb +89 -0
- data/spec/api/users_spec.rb +21 -0
- data/spec/api/variables_spec.rb +47 -16
- data/spec/cidr_helper.rb +24 -0
- data/spec/lib/acts_as_user_spec.rb +27 -0
- data/spec/lib/api_spec.rb +4 -4
- data/spec/lib/audit_spec.rb +49 -0
- data/spec/lib/cidr_spec.rb +34 -0
- data/spec/lib/configuration_spec.rb +6 -4
- data/spec/lib/host_spec.rb +11 -1
- data/spec/lib/user_spec.rb +18 -3
- data/spec/spec_helper.rb +2 -0
- data/spec/standard_methods_helper.rb +13 -4
- data/spec/variable_spec.rb +32 -0
- metadata +68 -3
data/spec/api/authn_spec.rb
CHANGED
@@ -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
|
data/spec/api/hosts_spec.rb
CHANGED
@@ -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
|
data/spec/api/users_spec.rb
CHANGED
@@ -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
|
data/spec/api/variables_spec.rb
CHANGED
@@ -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
|
-
|
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
|
data/spec/cidr_helper.rb
ADDED
@@ -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
|
data/spec/lib/audit_spec.rb
CHANGED
@@ -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
|
-
|
305
|
-
expect
|
306
|
-
expect
|
307
|
-
|
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
|
|
data/spec/lib/host_spec.rb
CHANGED
@@ -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
|