conjur-rack 1.4.0 → 5.0.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.
@@ -3,107 +3,179 @@ require 'spec_helper'
3
3
  require 'conjur/rack/authenticator'
4
4
 
5
5
  describe Conjur::Rack::Authenticator do
6
- let(:app) { double(:app) }
7
- let(:options) { {} }
8
- let(:authenticator) { Conjur::Rack::Authenticator.new(app, options) }
9
- let(:call) { authenticator.call env }
10
-
11
- context "#call" do
12
- context "with Conjur authorization" do
13
- before{ stub_const 'Slosilo', Module.new }
14
- let(:env) {
15
- {
16
- 'HTTP_AUTHORIZATION' => "Token token=\"#{basic_64}\""
17
- }.tap do |e|
18
- e['HTTP_X_CONJUR_PRIVILEGE'] = privilege if privilege
19
- e['HTTP_X_FORWARDED_FOR'] = remote_ip if remote_ip
20
- end
6
+ include_context "with authenticator"
7
+
8
+ describe "#call" do
9
+ context "to an unprotected path" do
10
+ let(:except) { [ /^\/foo/ ] }
11
+ let(:env) { { 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo/bar' } }
12
+ before {
13
+ options[:except] = except
14
+ expect(app).to receive(:call).with(env).and_return app
21
15
  }
22
- let(:basic_64) { Base64.strict_encode64(token.to_json) }
23
- let(:token) { { "data" => "foobar" } }
24
- let(:sample_account) { "someacc" }
25
- let(:privilege) { nil }
26
- let(:remote_ip) { nil }
27
-
28
- context "of a valid token" do
29
-
30
- before(:each) {
31
- Slosilo.stub token_signer: 'authn:'+sample_account
32
- }
33
-
34
- it 'launches app' do
35
- app.should_receive(:call).with(env).and_return app
36
- call.should == app
16
+ context "without authorization" do
17
+ it "proceeds" do
18
+ expect(call).to eq(app)
19
+ expect(Conjur::Rack.identity?).to be(false)
20
+ end
21
+ end
22
+ context "with authorization" do
23
+ include_context "with authorization"
24
+ it "ignores the authorization" do
25
+ expect(call).to eq(app)
26
+ expect(Conjur::Rack.identity?).to be(false)
37
27
  end
28
+ end
29
+ end
38
30
 
39
- context 'Authable provides module method conjur_user' do
40
- let(:stubuser) { "some value" }
41
- before {
42
- app.stub(:call) { Conjur::Rack.user }
43
- }
44
-
45
- context 'when called in app context' do
46
- let(:invoke) {
47
- Conjur::Rack::User.should_receive(:new).
48
- with(token, sample_account, privilege, remote_ip).
49
- and_return(stubuser)
50
- Conjur::Rack.should_receive(:user).and_call_original
51
- call
52
- }
53
-
54
- shared_examples_for 'returns User built from token' do
55
- specify {
56
- invoke.should == stubuser
57
- }
58
- end
59
-
60
- it_should_behave_like 'returns User built from token'
61
-
62
- context 'with X-Conjur-Privilege' do
63
- let(:privilege) { "sudo" }
64
- it_should_behave_like 'returns User built from token'
31
+ context "to a protected path" do
32
+ let(:env) { { 'SCRIPT_NAME' => '/pathname' } }
33
+ context "without authorization" do
34
+ it "returns a 401 error" do
35
+ expect(call).to return_http 401, "Authorization missing"
36
+ end
37
+ end
38
+ context "with Conjur authorization" do
39
+ include_context "with authorization"
40
+
41
+ context "with CIDR restriction" do
42
+ let(:claims) { { 'sub' => 'test-user', 'cidr' => %w(192.168.2.0/24 2001:db8::/32) } }
43
+ let(:token) { Slosilo::JWT.new(claims) }
44
+ before do
45
+ allow(subject).to receive_messages \
46
+ parsed_token: token,
47
+ http_remote_ip: remote_ip
48
+ end
49
+
50
+ %w(10.0.0.2 fdda:5cc1:23:4::1f).each do |addr|
51
+ context "with address #{addr} out of range" do
52
+ let(:remote_ip) { addr }
53
+ it "returns 403" do
54
+ expect(call).to return_http 403, "IP address rejected"
55
+ end
65
56
  end
66
-
67
- context 'with X-Forwarded-For' do
68
- let(:remote_ip) { "66.0.0.1" }
69
- it_should_behave_like 'returns User built from token'
57
+ end
58
+
59
+ %w(192.168.2.3 2001:db8::22).each do |addr|
60
+ context "with address #{addr} in range" do
61
+ let(:remote_ip) { addr }
62
+ it "passes the request" do
63
+ expect(call.login).to eq 'test-user'
64
+ end
70
65
  end
71
66
  end
67
+ end
72
68
 
73
- context 'called out of app context' do
74
- it { lambda { Conjur::Rack.user }.should raise_error }
69
+ context "of a valid token" do
70
+ it 'launches app' do
71
+ expect(app).to receive(:call).with(env).and_return app
72
+ expect(call).to eq(app)
73
+ end
74
+ end
75
+ context "of an invalid token" do
76
+ it "returns a 401 error" do
77
+ allow(Slosilo).to receive(:token_signer).and_return(nil)
78
+ expect(call).to return_http 401, "Unauthorized: Invalid token"
79
+ end
80
+ end
81
+ context "of a token invalid for authn" do
82
+ it "returns a 401 error" do
83
+ allow(Slosilo).to receive(:token_signer).and_return('a-totally-different-key')
84
+ expect(call).to return_http 401, "Unauthorized: Invalid token"
85
+ end
86
+ end
87
+ context "of 'own' token" do
88
+ it "returns ENV['CONJUR_ACCOUNT']" do
89
+ expect(ENV).to receive(:[]).with("CONJUR_ACCOUNT").and_return("test-account")
90
+ expect(app).to receive(:call) do |*args|
91
+ expect(Conjur::Rack.identity?).to be(true)
92
+ expect(Conjur::Rack.user.account).to eq('test-account')
93
+ :done
94
+ end
95
+ allow(Slosilo).to receive(:token_signer).and_return('own')
96
+ expect(call).to eq(:done)
97
+ end
98
+ it "requires ENV['CONJUR_ACCOUNT']" do
99
+ expect(ENV).to receive(:[]).with("CONJUR_ACCOUNT").and_return(nil)
100
+ allow(Slosilo).to receive(:token_signer).and_return('own')
101
+ expect(call).to return_http 401, "Unauthorized: Invalid token"
75
102
  end
76
103
  end
77
104
  end
78
- context "of an invalid token" do
79
- it "returns a 401 error" do
80
- Slosilo.stub token_signer: nil
81
- call.should == [401, {"Content-Type"=>"text/plain", "Content-Length"=>"26"}, ["Unathorized: Invalid token"]]
105
+
106
+ context "with junk in token" do
107
+ let(:env) { { 'HTTP_AUTHORIZATION' => 'Token token="open sesame"' } }
108
+ it "returns 401" do
109
+ expect(call).to return_http 401, "Malformed authorization token"
82
110
  end
83
111
  end
84
- context "of a token invalid for authn" do
85
- it "returns a 401 error" do
86
- Slosilo.stub token_signer: 'a-totally-different-key'
87
- call.should == [401, {"Content-Type"=>"text/plain", "Content-Length"=>"26"}, ["Unathorized: Invalid token"]]
112
+
113
+ context "with JSON junk in token" do
114
+ let(:env) { { 'HTTP_AUTHORIZATION' => 'Token token="eyJmb28iOiAiYmFyIn0="' } }
115
+ before do
116
+ allow(Slosilo).to receive(:token_signer).and_return(nil)
117
+ end
118
+
119
+ it "returns 401" do
120
+ expect(call).to return_http 401, "Unauthorized: Invalid token"
88
121
  end
89
122
  end
90
123
  end
91
- end
92
- context "without authorization" do
93
- context "to a protected path" do
94
- let(:env) { { 'SCRIPT_NAME' => '/pathname' } }
95
- it "returns a 401 error" do
96
- call.should == [401, {"Content-Type"=>"text/plain", "Content-Length"=>"21"}, ["Authorization missing"]]
124
+ context "to an optional path" do
125
+ let(:optional) { [ /^\/foo/ ] }
126
+ let(:env) { { 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo/bar' } }
127
+ before {
128
+ options[:optional] = optional
129
+ }
130
+ context "without authorization" do
131
+ it "proceeds" do
132
+ expect(app).to receive(:call) do |*args|
133
+ expect(Conjur::Rack.identity?).to be(false)
134
+ :done
135
+ end
136
+ expect(call).to eq(:done)
137
+ end
138
+ end
139
+ context "with authorization" do
140
+ include_context "with authorization"
141
+ it "processes the authorization" do
142
+ expect(app).to receive(:call) do |*args|
143
+ expect(Conjur::Rack.identity?).to be(true)
144
+ :done
145
+ end
146
+ expect(call).to eq(:done)
147
+ end
97
148
  end
98
149
  end
99
- context "to an unprotected path" do
100
- let(:except) { [ /^\/foo/ ] }
101
- let(:env) { { 'SCRIPT_NAME' => '', 'PATH_INFO' => '/foo/bar' } }
102
- it "proceeds" do
103
- options[:except] = except
104
- app.should_receive(:call).with(env).and_return app
105
- call.should == app
150
+
151
+ RSpec::Matchers.define :return_http do |status, message|
152
+ match do |actual|
153
+ status, headers, body = actual
154
+ expect(status).to eq status
155
+ expect(headers).to eq "Content-Type" => "text/plain", "Content-Length" => message.length.to_s
156
+ expect(body.join).to eq message
106
157
  end
107
158
  end
108
159
  end
160
+
161
+ # protected internal methods
162
+
163
+ describe '#verify_authorization_and_get_identity' do
164
+ it "accepts JWT tokens without CIDR restrictions" do
165
+ mock_jwt sub: 'user'
166
+ expect { subject.send :verify_authorization_and_get_identity }.to_not raise_error
167
+ end
168
+
169
+ it "rejects JWT tokens with unrecognized claims" do
170
+ mock_jwt extra: 'field'
171
+ expect { subject.send :verify_authorization_and_get_identity }.to raise_error \
172
+ Conjur::Rack::Authenticator::AuthorizationError
173
+ end
174
+
175
+ def mock_jwt claims
176
+ token = Slosilo::JWT.new(claims).add_signature(alg: 'none') {}
177
+ allow(subject).to receive(:parsed_token) { token }
178
+ allow(Slosilo).to receive(:token_signer).with(token).and_return 'authn:test'
179
+ end
180
+ end
109
181
  end
@@ -17,21 +17,21 @@ describe Conjur::Rack::PathPrefix do
17
17
  context "/api/hosts" do
18
18
  let(:path) { "/api/hosts" }
19
19
  it "matches" do
20
- app.should_receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app
20
+ expect(app).to receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app
21
21
  call
22
22
  end
23
23
  end
24
24
  context "/api" do
25
25
  let(:path) { "/api" }
26
26
  it "doesn't erase the path completely" do
27
- app.should_receive(:call).with({ 'PATH_INFO' => '/' }).and_return app
27
+ expect(app).to receive(:call).with({ 'PATH_INFO' => '/' }).and_return app
28
28
  call
29
29
  end
30
30
  end
31
31
  context "with non-matching prefix" do
32
32
  let(:path) { "/hosts" }
33
33
  it "doesn't match" do
34
- app.should_receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app
34
+ expect(app).to receive(:call).with({ 'PATH_INFO' => '/hosts' }).and_return app
35
35
  call
36
36
  end
37
37
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'conjur/rack/user'
2
3
 
3
4
  describe Conjur::Rack::User do
4
5
  let(:login){ 'admin' }
@@ -6,41 +7,50 @@ describe Conjur::Rack::User do
6
7
  let(:account){ 'acct' }
7
8
  let(:privilege) { nil }
8
9
  let(:remote_ip) { nil }
10
+ let(:audit_roles) { nil }
11
+ let(:audit_resources) { nil }
9
12
 
10
- subject{ described_class.new token, account, privilege, remote_ip }
13
+ subject(:user) {
14
+ described_class.new(token, account,
15
+ :privilege => privilege,
16
+ :remote_ip => remote_ip,
17
+ :audit_roles => audit_roles,
18
+ :audit_resources => audit_resources
19
+ )
20
+ }
11
21
 
12
- its(:token){ should == token }
13
- its(:account){ should == account }
14
- its(:conjur_account){ should == account }
15
- its(:login){ should == token['data'] }
16
-
17
- it "aliases setter for account to conjur_account" do
18
- subject.conjur_account = "changed!"
19
- subject.account.should == "changed!"
20
- end
21
-
22
- describe '#new_assocation' do
23
- let(:associate){ Class.new }
24
- let(:params){{foo: 'bar'}}
25
- it "calls cls.new with params including userid: login" do
26
- associate.should_receive(:new).with(params.merge(userid: subject.login))
27
- subject.new_association(associate, params)
28
- end
22
+ it 'provides field accessors' do
23
+ expect(user.token).to eq token
24
+ expect(user.account).to eq account
25
+ expect(user.conjur_account).to eq account
26
+ expect(user.login).to eq login
29
27
  end
30
28
 
31
29
  describe '#roleid' do
32
30
  let(:login){ tokens.join('/') }
33
- context "when login contains one token 'foobar'" do
34
- let(:tokens){ ['foobar'] }
35
- its(:roleid){ should == "#{account}:user:#{login}" }
31
+
32
+ context "when login contains one token" do
33
+ let(:tokens) { %w(foobar) }
34
+
35
+ it "is expanded to account:user:token" do
36
+ expect(subject.roleid).to eq "#{account}:user:foobar"
37
+ end
36
38
  end
37
- context "when login contains tokens ['foo', 'bar']" do
38
- let(:tokens){ ["foos", "bar"] }
39
- its(:roleid){ should == "#{account}:#{tokens[0]}:#{tokens[1]}"}
39
+
40
+ context "when login contains two tokens" do
41
+ let(:tokens) { %w(foo bar) }
42
+
43
+ it "is expanded to account:first:second" do
44
+ expect(subject.roleid).to eq "#{account}:foo:bar"
45
+ end
40
46
  end
41
- context "when login contains tokens ['foo','bar','baz']" do
42
- let(:tokens){ ['foo', 'bar', 'baz'] }
43
- its(:roleid){ should == "#{account}:#{tokens[0]}:#{tokens[1]}/#{tokens[2]}" }
47
+
48
+ context "when login contains three tokens" do
49
+ let(:tokens) { %w(foo bar baz) }
50
+
51
+ it "is expanded to account:first:second/third" do
52
+ expect(subject.roleid).to eq "#{account}:foo:bar/baz"
53
+ end
44
54
  end
45
55
  end
46
56
 
@@ -48,34 +58,46 @@ describe Conjur::Rack::User do
48
58
  let(:roleid){ 'the role id' }
49
59
  let(:api){ double('conjur api') }
50
60
  before do
51
- subject.stub(:roleid).and_return roleid
52
- subject.stub(:api).and_return api
61
+ allow(subject).to receive(:roleid).and_return roleid
62
+ allow(subject).to receive(:api).and_return api
53
63
  end
54
64
 
55
65
  it 'passes roleid to api.role' do
56
- api.should_receive(:role).with(roleid).and_return 'the role'
57
- subject.role.should == 'the role'
66
+ expect(api).to receive(:role).with(roleid).and_return 'the role'
67
+ expect(subject.role).to eq('the role')
58
68
  end
59
69
  end
60
70
 
61
71
  describe "#global_reveal?" do
72
+ let(:api){ double "conjur-api" }
73
+ before { allow(subject).to receive(:api).and_return(api) }
74
+
62
75
  context "with global privilege" do
63
76
  let(:privilege) { "reveal" }
64
- let(:api){ Conjur::API.new_from_token "the-token" }
65
- before do
66
- subject.stub(:api).and_return api
77
+
78
+ context "when not supported" do
79
+ before { expect(api).not_to respond_to :global_privilege_permitted? }
80
+ it "simply returns false" do
81
+ expect(subject.global_reveal?).to be false
82
+ end
67
83
  end
68
- it "checks the API function global_privilege_permitted?" do
69
- api.should_receive(:resource).with("!:!:conjur").and_return resource = double(:resource)
70
- resource.should_receive(:permitted?).with("reveal").and_return true
71
- expect(subject.global_reveal?).to be_true
72
- # The result is cached
73
- subject.global_reveal?
84
+
85
+ context "when supported" do
86
+ before do
87
+ allow(api).to receive(:global_privilege_permitted?).with('reveal') { true }
88
+ end
89
+ it "checks the API function global_privilege_permitted?" do
90
+ expect(subject.global_reveal?).to be true
91
+ # The result is cached
92
+ expect(api).not_to receive :global_privilege_permitted?
93
+ subject.global_reveal?
94
+ end
74
95
  end
75
96
  end
97
+
76
98
  context "without a global privilege" do
77
- it "simply returns nil" do
78
- expect(subject.global_reveal?).to be_false
99
+ it "simply returns false" do
100
+ expect(subject.global_reveal?).to be false
79
101
  end
80
102
  end
81
103
  end
@@ -84,38 +106,116 @@ describe Conjur::Rack::User do
84
106
  context "when given a class" do
85
107
  let(:cls){ double('API class') }
86
108
  it "calls cls.new_from_token with its token" do
87
- cls.should_receive(:new_from_token).with(token).and_return 'the api'
88
- subject.api(cls).should == 'the api'
109
+ expect(cls).to receive(:new_from_token).with(token).and_return 'the api'
110
+ expect(subject.api(cls)).to eq('the api')
89
111
  end
90
112
  end
113
+
91
114
  context 'when not given args' do
92
- shared_examples_for "builds the api" do
93
- specify {
94
- subject.api.should == 'the api'
95
- }
115
+ let(:api) { double :api }
116
+ before do
117
+ allow(Conjur::API).to receive(:new_from_token).with(token).and_return(api)
96
118
  end
97
-
98
- context "with no extra args" do
99
- before {
100
- Conjur::API.should_receive(:new_from_token).with(token).and_return 'the api'
101
- }
102
- it_should_behave_like "builds the api"
119
+
120
+ it "builds the api from token" do
121
+ expect(subject.api).to eq api
103
122
  end
123
+
104
124
  context "with remote_ip" do
105
125
  let(:remote_ip) { "the-ip" }
106
- before {
107
- Conjur::API.should_receive(:new_from_token).with(token, 'the-ip').and_return 'the api'
108
- }
109
- it_should_behave_like "builds the api"
126
+ it "passes the IP to the API constructor" do
127
+ expect(Conjur::API).to receive(:new_from_token).with(token, 'the-ip').and_return(api)
128
+ expect(subject.api).to eq api
129
+ end
110
130
  end
131
+
111
132
  context "with privilege" do
112
- let(:privilege) { "sudo" }
113
- before {
114
- Conjur::API.should_receive(:new_from_token).with(token).and_return api = double(:api)
115
- expect(api).to receive(:with_privilege).with("sudo").and_return('the api')
116
- }
117
- it_should_behave_like "builds the api"
133
+ let(:privilege) { "elevate" }
134
+ it "applies the privilege on the API object" do
135
+ expect(api).to receive(:with_privilege).with("elevate").and_return "privileged api"
136
+ expect(subject.api).to eq "privileged api"
137
+ end
118
138
  end
139
+
140
+ context "when audit supported" do
141
+ before do
142
+ # If we're testing on an API version that doesn't
143
+ # support audit this method will be missing, so stub.
144
+ unless Conjur::API.respond_to? :decode_audit_ids
145
+ # not exactly a faithful reimplementation, but good enough for here
146
+ allow(Conjur::API).to receive(:decode_audit_ids) {|x|[x]}
147
+ end
148
+ end
149
+
150
+ context "with audit resource" do
151
+ let (:audit_resources) { 'food:bacon' }
152
+ it "applies the audit resource on the API object" do
153
+ expect(api).to receive(:with_audit_resources).with(['food:bacon']).and_return('the api')
154
+ expect(subject.api).to eq 'the api'
155
+ end
156
+ end
157
+
158
+ context "with audit roles" do
159
+ let (:audit_roles) { 'user:cook' }
160
+ it "applies the audit role on the API object" do
161
+ expect(api).to receive(:with_audit_roles).with(['user:cook']).and_return('the api')
162
+ expect(subject.api).to eq 'the api'
163
+ end
164
+ end
165
+ end
166
+
167
+ context "when audit not supported" do
168
+ before do
169
+ expect(api).not_to respond_to :with_audit_resources
170
+ expect(api).not_to respond_to :with_audit_roles
171
+ end
172
+ let (:audit_resources) { 'food:bacon' }
173
+ let (:audit_roles) { 'user:cook' }
174
+ it "ignores audit roles and resources" do
175
+ expect(subject.api).to eq api
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ context "with invalid type payload" do
182
+ let(:token){ { "data" => :alice } }
183
+ it "raises an error on trying to access the content" do
184
+ expect{ subject.login }.to raise_error("Expecting String or Hash token data, got Symbol")
185
+ end
186
+ end
187
+
188
+ context "with hash payload" do
189
+ let(:token){ { "data" => { "login" => "alice", "capabilities" => { "fry" => "bacon" } } } }
190
+
191
+ it "processes the login and attributes" do
192
+ original_token = token.deep_dup
193
+
194
+ expect(subject.login).to eq('alice')
195
+ expect(subject.attributes).to eq({"capabilities" => { "fry" => "bacon" }})
196
+
197
+ expect(token).to eq original_token
198
+ end
199
+ end
200
+
201
+ context "with JWT token" do
202
+ let(:token) { {"protected"=>"eyJhbGciOiJ0ZXN0IiwidHlwIjoiSldUIn0=",
203
+ "payload"=>"eyJzdWIiOiJhbGljZSIsImlhdCI6MTUwNDU1NDI2NX0=",
204
+ "signature"=>"dGVzdHNpZw=="} }
205
+
206
+ it "processes the login and attributes" do
207
+ original_token = token.deep_dup
208
+
209
+ expect(subject.login).to eq('alice')
210
+
211
+ # TODO: should we only pass unrecognized attrs here?
212
+ expect(subject.attributes).to eq \
213
+ 'alg' => 'test',
214
+ 'iat' => 1504554265,
215
+ 'sub' => 'alice',
216
+ 'typ' => 'JWT'
217
+
218
+ expect(token).to eq original_token
119
219
  end
120
220
  end
121
- end
221
+ end
data/spec/rack_spec.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'conjur/rack'
3
+
4
+ describe Conjur::Rack do
5
+ describe '.user' do
6
+ include_context "with authorization"
7
+ let(:stubuser) { double :stubuser }
8
+ before do
9
+ allow(Conjur::Rack::User).to receive(:new)
10
+ .with(token, 'someacc', {:privilege => privilege, :remote_ip => remote_ip, :audit_roles => audit_roles, :audit_resources => audit_resources})
11
+ .and_return(stubuser)
12
+ end
13
+
14
+ context 'when called in app context' do
15
+ shared_examples_for :returns_user do
16
+ it "returns user built from token" do
17
+ expect(call).to eq stubuser
18
+ end
19
+ end
20
+
21
+ include_examples :returns_user
22
+
23
+ context 'with X-Conjur-Privilege' do
24
+ let(:privilege) { "elevate" }
25
+ include_examples :returns_user
26
+ end
27
+
28
+ context 'with X-Forwarded-For' do
29
+ let(:remote_ip) { "66.0.0.1" }
30
+ include_examples :returns_user
31
+ end
32
+
33
+ context 'with Conjur-Audit-Roles' do
34
+ let (:audit_roles) { 'user%3Acook' }
35
+ include_examples :returns_user
36
+ end
37
+
38
+ context 'with Conjur-Audit-Resources' do
39
+ let (:audit_resources) { 'food%3Abacon' }
40
+ include_examples :returns_user
41
+ end
42
+
43
+ end
44
+
45
+ it "raises error if called out of app context" do
46
+ expect { Conjur::Rack.user }.to raise_error('No Conjur identity for current request')
47
+ end
48
+ end
49
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,8 +4,44 @@ $:.unshift File.join(File.dirname(__FILE__), "lib")
4
4
 
5
5
  # Allows loading of an environment config based on the environment
6
6
  require 'rspec'
7
+ require 'rspec/its'
7
8
  require 'securerandom'
9
+ require 'slosilo'
8
10
 
9
11
  RSpec.configure do |config|
10
12
  end
11
13
 
14
+ RSpec.shared_context "with authenticator" do
15
+ let(:options) { {} }
16
+ let(:app) { double(:app) }
17
+ subject(:authenticator) { Conjur::Rack::Authenticator.new(app, options) }
18
+ let(:call) { authenticator.call env }
19
+ end
20
+
21
+ RSpec.shared_context "with authorization" do
22
+ include_context "with authenticator"
23
+ let(:token_signer) { "authn:someacc" }
24
+ let(:audit_resources) { nil }
25
+ let(:privilege) { nil }
26
+ let(:remote_ip) { nil }
27
+ let(:audit_roles) { nil }
28
+
29
+ before do
30
+ allow(app).to receive(:call) { Conjur::Rack.user }
31
+ allow(Slosilo).to receive(:token_signer).and_return(token_signer)
32
+ end
33
+
34
+ let(:env) do
35
+ {
36
+ 'HTTP_AUTHORIZATION' => "Token token=\"#{basic_64}\""
37
+ }.tap do |e|
38
+ e['HTTP_X_CONJUR_PRIVILEGE'] = privilege if privilege
39
+ e['HTTP_X_FORWARDED_FOR'] = remote_ip if remote_ip
40
+ e['HTTP_CONJUR_AUDIT_ROLES'] = audit_roles if audit_roles
41
+ e['HTTP_CONJUR_AUDIT_RESOURCES'] = audit_resources if audit_resources
42
+ end
43
+ end
44
+
45
+ let(:basic_64) { Base64.strict_encode64(token.to_json) }
46
+ let(:token) { { "data" => "foobar" } }
47
+ end