conjur-api 4.10.1 → 4.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +0 -4
- data/conjur-api.gemspec +3 -1
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur/base.rb +21 -4
- data/lib/conjur/configuration.rb +1 -6
- data/lib/conjur/resource.rb +1 -11
- data/spec/api/authn_spec.rb +11 -11
- data/spec/api/hosts_spec.rb +3 -3
- data/spec/api/layer_spec.rb +1 -1
- data/spec/api/pubkeys_spec.rb +4 -4
- data/spec/api/resources_spec.rb +5 -5
- data/spec/api/roles_spec.rb +6 -2
- data/spec/api/users_spec.rb +4 -4
- data/spec/api/variables_spec.rb +10 -10
- data/spec/lib/annotations_spec.rb +17 -17
- data/spec/lib/api_spec.rb +118 -59
- data/spec/lib/asset_spec.rb +11 -11
- data/spec/lib/audit_spec.rb +4 -4
- data/spec/lib/build_from_response_spec.rb +7 -7
- data/spec/lib/configuration_spec.rb +109 -49
- data/spec/lib/deputy_spec.rb +19 -6
- data/spec/lib/exists_spec.rb +15 -13
- data/spec/lib/host_spec.rb +10 -3
- data/spec/lib/log_source_spec.rb +1 -1
- data/spec/lib/log_spec.rb +5 -5
- data/spec/lib/resource_spec.rb +23 -53
- data/spec/lib/role_grant_spec.rb +3 -3
- data/spec/lib/role_spec.rb +54 -34
- data/spec/lib/standard_methods_spec.rb +15 -15
- data/spec/lib/user_spec.rb +32 -12
- data/spec/spec_helper.rb +9 -10
- data/spec/standard_methods_helper.rb +6 -6
- data/spec/variable_spec.rb +12 -7
- metadata +36 -14
- data/.rspec +0 -2
data/spec/lib/api_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'timecop'
|
2
3
|
|
3
4
|
shared_examples_for "API endpoint" do
|
4
5
|
before { Conjur.configuration = Conjur::Configuration.new }
|
@@ -6,30 +7,42 @@ shared_examples_for "API endpoint" do
|
|
6
7
|
let(:service_name) { api.name.split('::')[-2].downcase }
|
7
8
|
context "in development" do
|
8
9
|
before(:each) do
|
9
|
-
Conjur::Configuration.
|
10
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "development"
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#host' do
|
14
|
+
subject { super().host }
|
15
|
+
it do
|
16
|
+
is_expected.to eq("http://localhost:#{Conjur.configuration.service_base_port + port_offset}")
|
10
17
|
end
|
11
|
-
its "host" do
|
12
|
-
should == "http://localhost:#{Conjur.configuration.service_base_port + port_offset}"
|
13
18
|
end
|
14
19
|
end
|
15
20
|
context "'ci' account" do
|
16
21
|
before {
|
17
|
-
Conjur::Configuration.
|
22
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:account).and_return 'ci'
|
18
23
|
}
|
19
24
|
context "in stage" do
|
20
25
|
before(:each) do
|
21
|
-
Conjur::Configuration.
|
26
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "stage"
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#host' do
|
30
|
+
subject { super().host }
|
31
|
+
it do
|
32
|
+
is_expected.to eq("https://#{service_name}-ci-conjur.herokuapp.com")
|
22
33
|
end
|
23
|
-
its "host" do
|
24
|
-
should == "https://#{service_name}-ci-conjur.herokuapp.com"
|
25
34
|
end
|
26
35
|
end
|
27
36
|
context "in ci" do
|
28
37
|
before(:each) do
|
29
|
-
Conjur::Configuration.
|
38
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "ci"
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#host' do
|
42
|
+
subject { super().host }
|
43
|
+
it do
|
44
|
+
is_expected.to eq("https://#{service_name}-ci-conjur.herokuapp.com")
|
30
45
|
end
|
31
|
-
its "host" do
|
32
|
-
should == "https://#{service_name}-ci-conjur.herokuapp.com"
|
33
46
|
end
|
34
47
|
end
|
35
48
|
end
|
@@ -58,39 +71,39 @@ describe Conjur::API do
|
|
58
71
|
context "for short id (2 tokens)" do
|
59
72
|
let(:id) { "token#1:token#2" }
|
60
73
|
let(:current_account) { "current_account" }
|
61
|
-
before(:each) { Conjur::Core::API.
|
74
|
+
before(:each) { allow(Conjur::Core::API).to receive(:conjur_account).and_return current_account }
|
62
75
|
|
63
76
|
it "account: current account" do
|
64
|
-
subject[0].
|
77
|
+
expect(subject[0]).to eq(current_account)
|
65
78
|
end
|
66
79
|
|
67
80
|
it "kind: passed kind" do
|
68
|
-
subject[1].
|
81
|
+
expect(subject[1]).to eq(kind)
|
69
82
|
end
|
70
83
|
|
71
84
|
it "subkind: token #1 (escaped)" do
|
72
|
-
subject[2].
|
85
|
+
expect(subject[2]).to eq(escaped("token#1"))
|
73
86
|
end
|
74
87
|
|
75
88
|
it "id: token #2 (escaped)" do
|
76
|
-
subject[3].
|
89
|
+
expect(subject[3]).to eq(escaped("token#2"))
|
77
90
|
end
|
78
91
|
end
|
79
92
|
|
80
93
|
context "for long ids (3+ tokens)" do
|
81
94
|
let(:id) { "token#1:token#2:token#3:token#4" }
|
82
95
|
it "account: token #1 (escaped)" do
|
83
|
-
subject[0].
|
96
|
+
expect(subject[0]).to eq(escaped("token#1"))
|
84
97
|
end
|
85
98
|
|
86
99
|
it "kind: passed kind" do
|
87
|
-
subject[1].
|
100
|
+
expect(subject[1]).to eq(kind)
|
88
101
|
end
|
89
102
|
it "subkind: token #2 (escaped)" do
|
90
|
-
subject[2].
|
103
|
+
expect(subject[2]).to eq(escaped("token#2"))
|
91
104
|
end
|
92
105
|
it "id: tail of id starting from token#3" do
|
93
|
-
subject[3].
|
106
|
+
expect(subject[3]).to eq(escaped("token#3:token#4"))
|
94
107
|
end
|
95
108
|
end
|
96
109
|
|
@@ -101,12 +114,12 @@ describe Conjur::API do
|
|
101
114
|
let(:id) { :input_id }
|
102
115
|
|
103
116
|
it "#parse_role_id(id): calls parse_id(id, 'roles') and returns result" do
|
104
|
-
Conjur::API.
|
105
|
-
Conjur::API.parse_role_id(id).
|
117
|
+
expect(Conjur::API).to receive(:parse_id).with(id, 'roles').and_return(result)
|
118
|
+
expect(Conjur::API.parse_role_id(id)).to eq(result)
|
106
119
|
end
|
107
120
|
it "#parse_resource_id(id): calls parse_id(id, 'resources') and returns result" do
|
108
|
-
Conjur::API.
|
109
|
-
Conjur::API.parse_resource_id(id).
|
121
|
+
expect(Conjur::API).to receive(:parse_id).with(id, 'resources').and_return(result)
|
122
|
+
expect(Conjur::API.parse_resource_id(id)).to eq(result)
|
110
123
|
end
|
111
124
|
end
|
112
125
|
end
|
@@ -124,57 +137,81 @@ describe Conjur::API do
|
|
124
137
|
subject { api }
|
125
138
|
context "'ci' account" do
|
126
139
|
before {
|
127
|
-
Conjur::Configuration.
|
140
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:account).and_return 'ci'
|
128
141
|
}
|
129
142
|
context "in stage" do
|
130
143
|
before(:each) do
|
131
|
-
Conjur::Configuration.
|
144
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "stage"
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#host' do
|
148
|
+
subject { super().host }
|
149
|
+
it do
|
150
|
+
is_expected.to eq("https://authz-stage-conjur.herokuapp.com")
|
132
151
|
end
|
133
|
-
its "host" do
|
134
|
-
should == "https://authz-stage-conjur.herokuapp.com"
|
135
152
|
end
|
136
153
|
end
|
137
154
|
context "in ci" do
|
138
155
|
before(:each) do
|
139
156
|
# Looks at "ENV['CONJUR_STACK']" first, stub this out
|
140
|
-
ENV.
|
141
|
-
Conjur::Configuration.
|
157
|
+
allow(ENV).to receive(:[]).with('CONJUR_STACK').and_return nil
|
158
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "ci"
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#host' do
|
162
|
+
subject { super().host }
|
163
|
+
it do
|
164
|
+
is_expected.to eq("https://authz-ci-conjur.herokuapp.com")
|
142
165
|
end
|
143
|
-
its "host" do
|
144
|
-
should == "https://authz-ci-conjur.herokuapp.com"
|
145
166
|
end
|
146
167
|
end
|
147
168
|
context "when ENV['CONJUR_STACK'] is set to 'v12'" do
|
148
169
|
before do
|
149
|
-
Conjur::Configuration.
|
150
|
-
Conjur::Configuration.
|
170
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:stack).and_return "v12"
|
171
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "ci"
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#host' do
|
175
|
+
subject { super().host }
|
176
|
+
it { is_expected.to eq("https://authz-v12-conjur.herokuapp.com")}
|
151
177
|
end
|
152
|
-
its(:host){ should == "https://authz-v12-conjur.herokuapp.com"}
|
153
178
|
end
|
154
179
|
end
|
155
180
|
context "in production" do
|
156
181
|
before(:each) do
|
157
|
-
Conjur::Configuration.
|
182
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "production"
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#host' do
|
186
|
+
subject { super().host }
|
187
|
+
it do
|
188
|
+
is_expected.to eq("https://authz-v4-conjur.herokuapp.com")
|
158
189
|
end
|
159
|
-
its "host" do
|
160
|
-
should == "https://authz-v4-conjur.herokuapp.com"
|
161
190
|
end
|
162
191
|
end
|
163
192
|
context "in appliance" do
|
164
193
|
before(:each) do
|
165
|
-
Conjur::Configuration.
|
194
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "appliance"
|
195
|
+
end
|
196
|
+
|
197
|
+
describe '#host' do
|
198
|
+
subject { super().host }
|
199
|
+
it do
|
200
|
+
is_expected.to eq("http://localhost:5100")
|
166
201
|
end
|
167
|
-
its "host" do
|
168
|
-
should == "http://localhost:5100"
|
169
202
|
end
|
170
203
|
end
|
171
204
|
context "in named production version" do
|
172
205
|
before(:each) do
|
173
|
-
Conjur::Configuration.
|
174
|
-
Conjur::Configuration.
|
206
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:env).and_return "production"
|
207
|
+
allow_any_instance_of(Conjur::Configuration).to receive(:stack).and_return "waffle"
|
208
|
+
end
|
209
|
+
|
210
|
+
describe '#host' do
|
211
|
+
subject { super().host }
|
212
|
+
it do
|
213
|
+
is_expected.to eq("https://authz-waffle-conjur.herokuapp.com")
|
175
214
|
end
|
176
|
-
its "host" do
|
177
|
-
should == "https://authz-waffle-conjur.herokuapp.com"
|
178
215
|
end
|
179
216
|
end
|
180
217
|
end
|
@@ -187,49 +224,71 @@ describe Conjur::API do
|
|
187
224
|
|
188
225
|
shared_context logged_in: true do
|
189
226
|
let(:login) { "bob" }
|
190
|
-
let(:token) { { 'data' => login, 'timestamp' =>
|
191
|
-
let(:elapsed) { 0 }
|
227
|
+
let(:token) { { 'data' => login, 'timestamp' => Time.now.to_s } }
|
192
228
|
subject { api }
|
193
229
|
let(:api) { Conjur::API.new_from_token(token) }
|
194
230
|
let(:account) { 'some-account' }
|
195
|
-
before { Conjur::Core::API.
|
231
|
+
before { allow(Conjur::Core::API).to receive_messages conjur_account: account }
|
196
232
|
end
|
197
233
|
|
198
234
|
context "credential handling", logged_in: true do
|
199
235
|
context "from token" do
|
200
|
-
|
201
|
-
|
236
|
+
describe '#token' do
|
237
|
+
subject { super().token }
|
238
|
+
it { is_expected.to eq(token) }
|
239
|
+
end
|
240
|
+
|
241
|
+
describe '#credentials' do
|
242
|
+
subject { super().credentials }
|
243
|
+
it { is_expected.to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login }) }
|
244
|
+
end
|
202
245
|
end
|
246
|
+
|
203
247
|
context "from api key", logged_in: true do
|
204
248
|
let(:api_key) { "theapikey" }
|
205
249
|
let(:api) { Conjur::API.new_from_key(login, api_key) }
|
206
250
|
subject { api }
|
251
|
+
|
207
252
|
it("should authenticate to get a token") do
|
208
|
-
Conjur::API.
|
253
|
+
expect(Conjur::API).to receive(:authenticate).with(login, api_key).and_return token
|
209
254
|
|
210
|
-
api.instance_variable_get("@token").
|
211
|
-
api.token.
|
212
|
-
api.credentials.
|
255
|
+
expect(api.instance_variable_get("@token")).to eq(nil)
|
256
|
+
expect(api.token).to eq(token)
|
257
|
+
expect(api.credentials).to eq({ headers: { authorization: "Token token=\"#{Base64.strict_encode64(token.to_json)}\"" }, username: login })
|
258
|
+
end
|
259
|
+
|
260
|
+
context "with an expired token" do
|
261
|
+
it "fetches a new one" do
|
262
|
+
allow(Conjur::API).to receive(:authenticate).with(login, api_key).and_return token
|
263
|
+
expect(Time.parse(api.token['timestamp'])).to be_within(5.seconds).of(Time.now)
|
264
|
+
|
265
|
+
Timecop.travel Time.now + 6.minutes
|
266
|
+
new_token = token.merge "timestamp" => Time.now.to_s
|
267
|
+
|
268
|
+
expect(Conjur::API).to receive(:authenticate).with(login, api_key).and_return new_token
|
269
|
+
expect(api.token).to eq(new_token)
|
270
|
+
end
|
213
271
|
end
|
214
272
|
end
|
273
|
+
|
215
274
|
context "from logged-in RestClient::Resource" do
|
216
275
|
let(:token_encoded) { Base64.strict_encode64(token.to_json) }
|
217
276
|
let(:resource) { RestClient::Resource.new("http://example.com", { headers: { authorization: "Token token=\"#{token_encoded}\"" } })}
|
218
277
|
it "can construct a new API instance" do
|
219
278
|
api = resource.conjur_api
|
220
|
-
api.credentials[:headers][:authorization].
|
221
|
-
api.credentials[:username].
|
279
|
+
expect(api.credentials[:headers][:authorization]).to eq("Token token=\"#{token_encoded}\"")
|
280
|
+
expect(api.credentials[:username]).to eq("bob")
|
222
281
|
end
|
223
282
|
end
|
224
283
|
end
|
225
284
|
|
226
285
|
describe "#role_from_username", logged_in: true do
|
227
286
|
it "returns a user role when username is plain" do
|
228
|
-
api.role_from_username("plain-username").roleid.
|
287
|
+
expect(api.role_from_username("plain-username").roleid).to eq("#{account}:user:plain-username")
|
229
288
|
end
|
230
289
|
|
231
290
|
it "returns an appropriate role kind when username is qualified" do
|
232
|
-
api.role_from_username("host/foo/bar").roleid.
|
291
|
+
expect(api.role_from_username("host/foo/bar").roleid).to eq("#{account}:host:foo/bar")
|
233
292
|
end
|
234
293
|
end
|
235
294
|
|
@@ -237,7 +296,7 @@ describe Conjur::API do
|
|
237
296
|
context "when logged in as user" do
|
238
297
|
let(:login) { 'joerandom' }
|
239
298
|
it "returns a user role" do
|
240
|
-
api.current_role.roleid.
|
299
|
+
expect(api.current_role.roleid).to eq("#{account}:user:joerandom")
|
241
300
|
end
|
242
301
|
end
|
243
302
|
|
@@ -245,7 +304,7 @@ describe Conjur::API do
|
|
245
304
|
let(:host) { "somehost" }
|
246
305
|
let(:login) { "host/#{host}" }
|
247
306
|
it "returns a host role" do
|
248
|
-
api.current_role.roleid.
|
307
|
+
expect(api.current_role.roleid).to eq("#{account}:host:somehost")
|
249
308
|
end
|
250
309
|
end
|
251
310
|
end
|
data/spec/lib/asset_spec.rb
CHANGED
@@ -23,10 +23,10 @@ describe Conjur::ActsAsAsset do
|
|
23
23
|
|
24
24
|
shared_context "asset with role" do
|
25
25
|
before(:each) {
|
26
|
-
asset.
|
27
|
-
asset.
|
28
|
-
asset.
|
29
|
-
Conjur::Role.
|
26
|
+
allow(asset).to receive(:core_conjur_account).and_return(ACCOUNT)
|
27
|
+
allow(asset).to receive(:resource_kind).and_return(KIND)
|
28
|
+
allow(asset).to receive(:resource_id).and_return(ID)
|
29
|
+
allow(Conjur::Role).to receive(:new).and_return(role_base)
|
30
30
|
}
|
31
31
|
let(:role_base) {
|
32
32
|
double(:"[]" => role_instance)
|
@@ -38,21 +38,21 @@ describe Conjur::ActsAsAsset do
|
|
38
38
|
|
39
39
|
shared_examples_for "it obtains role via asset" do
|
40
40
|
it "account=asset.core_conjur_account" do
|
41
|
-
asset.
|
41
|
+
expect(asset).to receive(:core_conjur_account)
|
42
42
|
invoke
|
43
43
|
end
|
44
44
|
it "kind=asset.resource_kind" do
|
45
|
-
asset.
|
45
|
+
expect(asset).to receive(:resource_kind)
|
46
46
|
invoke
|
47
47
|
end
|
48
48
|
it "id=asset.resource_id" do
|
49
|
-
asset.
|
49
|
+
expect(asset).to receive(:resource_id)
|
50
50
|
invoke
|
51
51
|
end
|
52
52
|
|
53
53
|
it "obtains role as #{ACCOUNT}:@:#{KIND}/#{ID}/#{ROLE}" do
|
54
|
-
Conjur::Role.
|
55
|
-
role_base.
|
54
|
+
expect(Conjur::Role).to receive(:new).with("http://localhost:5100", {}).and_return role_base
|
55
|
+
expect(role_base).to receive(:[]).with("#{CGI.escape ACCOUNT}/roles/@/#{KIND}/#{ID}/#{CGI.escape ROLE}").and_return role_instance
|
56
56
|
|
57
57
|
invoke
|
58
58
|
end
|
@@ -63,7 +63,7 @@ describe Conjur::ActsAsAsset do
|
|
63
63
|
include_context "asset with role"
|
64
64
|
it_behaves_like "it obtains role via asset"
|
65
65
|
it 'calls role.grant_to(member,...)' do
|
66
|
-
role_instance.
|
66
|
+
expect(role_instance).to receive(:grant_to).with(MEMBER, anything)
|
67
67
|
invoke
|
68
68
|
end
|
69
69
|
end
|
@@ -73,7 +73,7 @@ describe Conjur::ActsAsAsset do
|
|
73
73
|
include_context "asset with role"
|
74
74
|
it_behaves_like "it obtains role via asset"
|
75
75
|
it 'calls role.revoke_from(member)' do
|
76
|
-
role_instance.
|
76
|
+
expect(role_instance).to receive(:revoke_from).with(MEMBER)
|
77
77
|
invoke
|
78
78
|
end
|
79
79
|
end
|
data/spec/lib/audit_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Conjur::API, api: :dummy do
|
|
12
12
|
let(:expected_url){ "#{Conjur::Audit::API.host}/#{expected_path}#{query}" }
|
13
13
|
|
14
14
|
def expect_request
|
15
|
-
RestClient::Request.
|
15
|
+
expect(RestClient::Request).to receive(:execute).with(
|
16
16
|
headers: credentials[:headers],
|
17
17
|
url: expected_url,
|
18
18
|
method: :get
|
@@ -28,7 +28,7 @@ describe Conjur::API, api: :dummy do
|
|
28
28
|
shared_examples_for "gets all visible events" do
|
29
29
|
it "GETs /" do
|
30
30
|
expect_request
|
31
|
-
api.audit(*full_args).
|
31
|
+
expect(api.audit(*full_args)).to eq(response)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -52,7 +52,7 @@ describe Conjur::API, api: :dummy do
|
|
52
52
|
shared_examples_for "gets roles feed" do
|
53
53
|
it "GETs roles/:role_id" do
|
54
54
|
expect_request
|
55
|
-
api.audit_role(*full_args).
|
55
|
+
expect(api.audit_role(*full_args)).to eq(response)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -83,7 +83,7 @@ describe Conjur::API, api: :dummy do
|
|
83
83
|
shared_examples_for "gets the resource feed" do
|
84
84
|
it "GETS resources/:resource_id" do
|
85
85
|
expect_request
|
86
|
-
api.audit_resource(*full_args).
|
86
|
+
expect(api.audit_resource(*full_args)).to eq(response)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -13,11 +13,11 @@ describe Conjur::BuildFromResponse do
|
|
13
13
|
|
14
14
|
before do
|
15
15
|
subject.extend Conjur::BuildFromResponse
|
16
|
-
subject.
|
17
|
-
constructed.
|
16
|
+
expect(subject).to receive(:new).with(location, credentials).and_return constructed
|
17
|
+
expect(constructed).to receive(:attributes=).with attrs
|
18
18
|
|
19
19
|
constructed.extend Conjur::LogSource
|
20
|
-
constructed.
|
20
|
+
allow(constructed).to receive_messages username: 'whatever'
|
21
21
|
end
|
22
22
|
|
23
23
|
it "passes the location credentials and attributes" do
|
@@ -26,23 +26,23 @@ describe Conjur::BuildFromResponse do
|
|
26
26
|
|
27
27
|
context "with a resource(-ish) class" do
|
28
28
|
before do
|
29
|
-
constructed.
|
29
|
+
allow(constructed).to receive_messages resource_kind: 'chunky', resource_id: 'bacon'
|
30
30
|
end
|
31
31
|
|
32
32
|
it "logs creation correctly" do
|
33
33
|
subject.build_from_response response, credentials
|
34
|
-
log.
|
34
|
+
expect(log).to match(/Created chunky bacon/)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
context "with a id(-ish) class" do
|
39
39
|
before do
|
40
|
-
constructed.
|
40
|
+
allow(constructed).to receive_messages id: 'bacon'
|
41
41
|
end
|
42
42
|
|
43
43
|
it "logs creation correctly" do
|
44
44
|
subject.build_from_response response, credentials
|
45
|
-
log.
|
45
|
+
expect(log).to match(/Created some bacon/)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|