right_infrastructure_agent 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +10 -0
- data/README.rdoc +65 -0
- data/Rakefile +86 -0
- data/lib/right_infrastructure_agent.rb +26 -0
- data/lib/right_infrastructure_agent/command_constants.rb +34 -0
- data/lib/right_infrastructure_agent/global_object_replicator_sink.rb +337 -0
- data/lib/right_infrastructure_agent/global_object_replicator_source.rb +117 -0
- data/lib/right_infrastructure_agent/infrastructure_auth_client.rb +88 -0
- data/lib/right_infrastructure_agent/infrastructure_helpers.rb +85 -0
- data/lib/right_infrastructure_agent/login_policy_factory.rb +137 -0
- data/lib/right_infrastructure_agent/models_helper.rb +483 -0
- data/lib/right_infrastructure_agent/rainbows_agent_controller.rb +192 -0
- data/lib/right_infrastructure_agent/scripts/infrastructure_agent_deployer.rb +278 -0
- data/right_infrastructure_agent.gemspec +54 -0
- data/spec/global_object_replicator_sink_spec.rb +305 -0
- data/spec/global_object_replicator_source_spec.rb +113 -0
- data/spec/infrastructure_auth_client_spec.rb +140 -0
- data/spec/infrastructure_helpers_spec.rb +80 -0
- data/spec/login_policy_factory_spec.rb +279 -0
- data/spec/models_helper_spec.rb +546 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +85 -0
- metadata +116 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
25
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'right_infrastructure_agent', 'infrastructure_auth_client'))
|
26
|
+
|
27
|
+
describe RightScale::InfrastructureAuthClient do
|
28
|
+
|
29
|
+
include FlexMock::ArgumentTypes
|
30
|
+
|
31
|
+
class GlobalSessionTestDirectory
|
32
|
+
def initialize(configuration, authorities)
|
33
|
+
end
|
34
|
+
|
35
|
+
def configuration
|
36
|
+
{"cookie" => {"name" => "yum"}}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
before(:each) do
|
41
|
+
@log = flexmock(RightScale::Log)
|
42
|
+
@log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
|
43
|
+
@log.should_receive(:warning).by_default.and_return { |m| raise RightScale::Log.format(*m) }
|
44
|
+
|
45
|
+
@config_dir = "/tmp"
|
46
|
+
@global_session_timeout = 3600
|
47
|
+
@global_session_client_timeout = (@global_session_timeout * 8) / 10
|
48
|
+
@global_session_config = flexmock("global_session configuration")
|
49
|
+
@global_session_config.should_receive(:[]).with("directory").and_return("GlobalSessionTestDirectory").by_default
|
50
|
+
@global_session_config.should_receive(:[]).with("timeout").and_return(@global_session_timeout).by_default
|
51
|
+
flexmock(GlobalSession::Configuration).should_receive(:new).and_return(@global_session_config).by_default
|
52
|
+
@global_session_dir = GlobalSessionTestDirectory.new(@global_session_config, "authorities")
|
53
|
+
@global_session = flexmock("global session")
|
54
|
+
@global_session.should_receive(:[]=).by_default
|
55
|
+
@global_session.should_receive(:directory).and_return(@global_session_dir).by_default
|
56
|
+
@global_session.should_receive(:to_s).and_return("session").by_default
|
57
|
+
flexmock(GlobalSession::Session).should_receive(:new).and_return(@global_session).by_default
|
58
|
+
|
59
|
+
@client_name = "agent"
|
60
|
+
@router_url = "http://router.com"
|
61
|
+
@agent_id = "rs-agent-1-1"
|
62
|
+
@options = {:agent_id => @agent_id}
|
63
|
+
end
|
64
|
+
|
65
|
+
context :initialize do
|
66
|
+
it "creates global session directory" do
|
67
|
+
flexmock(GlobalSession::Configuration).should_receive(:new).and_return(@global_session_config).once
|
68
|
+
client = RightScale::InfrastructureAuthClient.new(@client_name, @router_url, @config_dir, @options)
|
69
|
+
client.instance_variable_get(:@global_session_dir).is_a?(GlobalSessionTestDirectory).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "sets timeout at 80% of actual global session timeout" do
|
73
|
+
@global_session_config.should_receive(:[]).with("directory").and_return("GlobalSessionTestDirectory").once
|
74
|
+
@global_session_config.should_receive(:[]).with("timeout").and_return(@global_session_timeout).once
|
75
|
+
client = RightScale::InfrastructureAuthClient.new(@client_name, @router_url, @config_dir, @options)
|
76
|
+
client.instance_variable_get(:@global_session_timeout).should == @global_session_client_timeout
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context :headers do
|
81
|
+
before(:each) do
|
82
|
+
@client = RightScale::InfrastructureAuthClient.new(@client_name, @router_url, @config_dir, @options)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "raises if not authorized" do
|
86
|
+
@client.send(:state=, :unauthorized)
|
87
|
+
lambda { @client.headers }.should raise_error(RightScale::Exceptions::Unauthorized)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns headers" do
|
91
|
+
@client.headers.should == {"Authorization" => "Bearer session"}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context :auth_header do
|
96
|
+
before(:each) do
|
97
|
+
@client = RightScale::InfrastructureAuthClient.new(@client_name, @router_url, @config_dir, @options)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "raises if not authorized" do
|
101
|
+
@client.send(:state=, :unauthorized)
|
102
|
+
lambda { @client.auth_header }.should raise_error(RightScale::Exceptions::Unauthorized)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "returns authorization header" do
|
106
|
+
@client.auth_header.should == {"Authorization" => "Bearer session"}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context :infrastructure_session do
|
111
|
+
before(:each) do
|
112
|
+
@client = RightScale::InfrastructureAuthClient.new(@client_name, @router_url, @config_dir, @options)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "creates session and stores in cache" do
|
116
|
+
now = Time.now
|
117
|
+
flexmock(Time).should_receive(:now).and_return(now)
|
118
|
+
flexmock(GlobalSession::Session).should_receive(:new).and_return(@global_session).once
|
119
|
+
@client.send(:infrastructure_session).should == "session"
|
120
|
+
@client.instance_variable_get(:@cached_infrastructure_session).should == {:session => "session", :created_at => now}
|
121
|
+
end
|
122
|
+
|
123
|
+
it "retrieves existing session from cache" do
|
124
|
+
flexmock(GlobalSession::Session).should_receive(:new).and_return(@global_session).once
|
125
|
+
@client.send(:infrastructure_session).should == "session"
|
126
|
+
@client.send(:infrastructure_session).should == "session"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "creates a new session if session timed out" do
|
130
|
+
now = Time.now
|
131
|
+
later = now + @global_session_client_timeout
|
132
|
+
flexmock(Time).should_receive(:now).and_return(now, later)
|
133
|
+
flexmock(GlobalSession::Session).should_receive(:new).and_return(@global_session).twice
|
134
|
+
@client.send(:infrastructure_session).should == "session"
|
135
|
+
@client.instance_variable_get(:@cached_infrastructure_session).should == {:session => "session", :created_at => now}
|
136
|
+
@client.send(:infrastructure_session).should == "session"
|
137
|
+
@client.instance_variable_get(:@cached_infrastructure_session).should == {:session => "session", :created_at => later}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2011-2013 RightScale, Inc, All Rights Reserved Worldwide.
|
3
|
+
#
|
4
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
5
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
6
|
+
# reproduction, modification, or disclosure of this program is
|
7
|
+
# strictly prohibited. Any use of this program by an authorized
|
8
|
+
# licensee is strictly subject to the terms and conditions,
|
9
|
+
# including confidentiality obligations, set forth in the applicable
|
10
|
+
# License Agreement between RightScale.com, Inc. and the licensee.
|
11
|
+
#++
|
12
|
+
|
13
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
14
|
+
|
15
|
+
describe RightScale::InfrastructureHelpers do
|
16
|
+
|
17
|
+
include RightScale::InfrastructureHelpers
|
18
|
+
|
19
|
+
context :render_nothing do
|
20
|
+
|
21
|
+
it "renders nothing" do
|
22
|
+
flexmock(self).should_receive(:render).with(:nothing => true, :status => :no_content).once
|
23
|
+
render_nothing.should be_true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context :format_error do
|
28
|
+
|
29
|
+
it "formats exception" do
|
30
|
+
format_error("This is", ArgumentError.new("bad"), :no_trace).should == "This is (ArgumentError: bad)"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "formats error message" do
|
34
|
+
format_error("This is", "bad").should == "This is (bad)"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context :to_int_or_nil do
|
39
|
+
|
40
|
+
class ExtendedString < String
|
41
|
+
def blank?
|
42
|
+
self.empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "converts string to integer" do
|
47
|
+
to_int_or_nil(ExtendedString.new("123")).should == 123
|
48
|
+
end
|
49
|
+
|
50
|
+
it "converts empty string to nil" do
|
51
|
+
to_int_or_nil(ExtendedString.new("")).should == nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it "converts nil to nil" do
|
55
|
+
flexmock(NilClass).should_receive(:blank?).and_return(true)
|
56
|
+
to_int_or_nil(nil).should == nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context :to_bool do
|
61
|
+
|
62
|
+
it "converts nil to false" do
|
63
|
+
to_bool(nil).should == false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "converts false to false" do
|
67
|
+
to_bool(false).should == false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "converts 'false' to false" do
|
71
|
+
to_bool("false").should == false
|
72
|
+
end
|
73
|
+
|
74
|
+
it "converts anything else to true" do
|
75
|
+
to_bool("anything else").should == true
|
76
|
+
to_bool("true").should == true
|
77
|
+
to_bool(true).should == true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
# Copyright (c) 2009-2014 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and the licensee.
|
10
|
+
|
11
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
|
12
|
+
require 'right_agent/core_payload_types'
|
13
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'right_infrastructure_agent', 'login_policy_factory'))
|
14
|
+
|
15
|
+
# LoginPolicyFactory is shared between library and right_api, which is why it lives here.
|
16
|
+
# By creating a mock world of RightScale models, we allow this spec to run independently
|
17
|
+
# of the Rails web apps.
|
18
|
+
class Account; end unless defined?(Account)
|
19
|
+
class User; end unless defined?(User)
|
20
|
+
class Ec2Instance ; end unless defined?(Ec2Instance)
|
21
|
+
class Role
|
22
|
+
def self.[](role)
|
23
|
+
role.hash
|
24
|
+
end
|
25
|
+
end unless defined?(Role)
|
26
|
+
module Biz
|
27
|
+
module ResourceUuidMixin
|
28
|
+
def self.obfuscate_id(object)
|
29
|
+
object.to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module MockHelper
|
35
|
+
def months_ago(months)
|
36
|
+
Time.now - (24 * 60 * 60 * 30 * months)
|
37
|
+
end
|
38
|
+
|
39
|
+
def mock_account_and_users(num_users)
|
40
|
+
account = flexmock(:model, Account)
|
41
|
+
account.should_receive(:setting).with('managed_login_mandatory').and_return(false).by_default
|
42
|
+
|
43
|
+
users = []
|
44
|
+
(0...num_users).each do
|
45
|
+
user = flexmock(:model, User,
|
46
|
+
:id=>rand(2**16),
|
47
|
+
:account=>account,
|
48
|
+
:email=>"user#{rand(2**16)}@rightscale.com")
|
49
|
+
users << user
|
50
|
+
end
|
51
|
+
|
52
|
+
flexmock(User).should_receive(:all).and_return(users)
|
53
|
+
return [account] + users
|
54
|
+
end
|
55
|
+
|
56
|
+
def mock_instance(account)
|
57
|
+
instance = flexmock(:model, Ec2Instance, :account=>account)
|
58
|
+
instance.should_receive(:managed_login_allowed?).and_return(false).by_default
|
59
|
+
return instance
|
60
|
+
end
|
61
|
+
|
62
|
+
def mock_login_permission(account, user, expires_at = nil, updated_at = nil)
|
63
|
+
updated_at ||= months_ago(1)
|
64
|
+
|
65
|
+
user.should_receive(:perm_updated_at).and_return(updated_at.to_s)
|
66
|
+
user.should_receive(:perm_deleted_at).and_return((expires_at.to_s unless expires_at.nil?))
|
67
|
+
end
|
68
|
+
|
69
|
+
def mock_credential(user, public_key = nil, public_key_fingerprint = nil, updated_at = nil)
|
70
|
+
updated_at ||= months_ago(1)
|
71
|
+
|
72
|
+
user.should_receive(:cred_updated_at).and_return(updated_at.to_s)
|
73
|
+
user.should_receive(:cred_public_value).and_return(public_key)
|
74
|
+
user.should_receive(:cred_public_fingerprint).and_return(public_key_fingerprint)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe RightScale::LoginPolicyFactory do
|
79
|
+
include MockHelper
|
80
|
+
|
81
|
+
def hours_ago(hours)
|
82
|
+
Time.now - (60 * 60 * hours)
|
83
|
+
end
|
84
|
+
|
85
|
+
def days_ago(days)
|
86
|
+
Time.now - (24 * 60 * 60 * days)
|
87
|
+
end
|
88
|
+
|
89
|
+
context :policy_for_instance do
|
90
|
+
context 'handling oddly-formatted keys' do
|
91
|
+
before(:each) do
|
92
|
+
@account, @user = mock_account_and_users(1)
|
93
|
+
@instance = mock_instance(@account)
|
94
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should add a comment for keys that are missing it' do
|
98
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234')
|
99
|
+
@permission = mock_login_permission(@account, @user, nil)
|
100
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
101
|
+
@policy.users.size.should == 1
|
102
|
+
components = RightScale::LoginPolicy.parse_public_key(@policy.users[0].public_keys.first)
|
103
|
+
components[3].should_not be_nil # email should be substituted in
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'calculating policy for a given user' do
|
108
|
+
before(:each) do
|
109
|
+
@account, @user = mock_account_and_users(1)
|
110
|
+
@instance = mock_instance(@account)
|
111
|
+
end
|
112
|
+
|
113
|
+
context "for all users" do
|
114
|
+
before(:each) do
|
115
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234 joe@joebob.com', 'sha1')
|
116
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
117
|
+
@permission = mock_login_permission(@account, @user, nil)
|
118
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
119
|
+
@policy.users.size.should == 1
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should specify the user's UUID" do
|
123
|
+
@policy.users[0].uuid.should == @user.id.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should specify a preferred username" do
|
127
|
+
@policy.users[0].username.should_not be_nil
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should include a single public key for pre-5.5 instances" do
|
131
|
+
@policy.users[0].public_key.should == 'ssh-rsa abcd1234 joe@joebob.com'
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should include a collection of public keys for modern instances" do
|
135
|
+
@policy.users[0].public_keys.should == ['ssh-rsa abcd1234 joe@joebob.com']
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should include a collection of public key fingerprints for modern instances" do
|
139
|
+
@policy.users[0].public_key_fingerprints.should == ['sha1']
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should specify a common name" do
|
143
|
+
@policy.users[0].username.should_not be_nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "for users not recently updated" do
|
148
|
+
before(:each) do
|
149
|
+
@permission = mock_login_permission(@account, @user, nil)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not be terse by default" do
|
153
|
+
@t = days_ago(1)
|
154
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234 joe@joebob.com', 'sha1', @t)
|
155
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
156
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
157
|
+
@policy.users[0].public_keys.should == ['ssh-rsa abcd1234 joe@joebob.com']
|
158
|
+
@policy.users[0].public_key_fingerprints.should == ['sha1']
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should not omit public keys if credential is considered new when requested to be terse" do
|
162
|
+
@t = hours_ago(23)
|
163
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234 joe@joebob.com', 'sha1', @t)
|
164
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
165
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234, true)
|
166
|
+
@policy.users[0].public_keys.should == ['ssh-rsa abcd1234 joe@joebob.com']
|
167
|
+
@policy.users[0].public_key_fingerprints.should == ['sha1']
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should omit public keys that are considered old if requested to be terse" do
|
171
|
+
@t = days_ago(1)
|
172
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234 joe@joebob.com', 'sha1', @t)
|
173
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
174
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234, true)
|
175
|
+
@policy.users[0].public_keys.should == [nil]
|
176
|
+
@policy.users[0].public_key_fingerprints.should == ['sha1']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "for users with temporary access" do
|
181
|
+
before(:each) do
|
182
|
+
@user_credential = mock_credential(@user, 'ssh-rsa abcd1234 joe@joebob.com', 'sha1')
|
183
|
+
@instance.should_receive(:managed_login_allowed?).with(@user, @account).and_return(true)
|
184
|
+
@t = Time.at((Time.now + 24 * 60 * 60).to_i)
|
185
|
+
@permission = mock_login_permission(@account, @user, @t)
|
186
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
187
|
+
@policy.users.size.should == 1
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should specify the expiry time" do
|
191
|
+
@policy.users[0].expires_at.to_i.should == @t.to_i
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'calculating users' do
|
198
|
+
before(:each) do
|
199
|
+
@account, @u_ok = mock_account_and_users(1)
|
200
|
+
mock_login_permission(@account, @u_ok)
|
201
|
+
mock_credential(@u_ok, 'moo')
|
202
|
+
|
203
|
+
@instance = mock_instance(@account)
|
204
|
+
@instance.should_receive(:managed_login_allowed?).with(@u_ok, @account).and_return(true)
|
205
|
+
|
206
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
207
|
+
@policy.users.size.should == 1
|
208
|
+
@policy.users.detect { |u| u.common_name == @u_ok.email }.should_not be_nil
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should include users that satisfy all criteria' do
|
212
|
+
@policy.users.detect { |u| u.common_name == @u_ok.email }.should_not be_nil
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'calculating created_at' do
|
217
|
+
before(:each) do
|
218
|
+
@account, @user1, @user2 = mock_account_and_users(2)
|
219
|
+
|
220
|
+
@instance = mock_instance(@account)
|
221
|
+
@instance.should_receive(:managed_login_allowed?).with(@user1, @account).and_return(true)
|
222
|
+
@instance.should_receive(:managed_login_allowed?).with(@user2, @account).and_return(true)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should match a UserCredential.updated_at that is most recent within scope' do
|
226
|
+
@t = days_ago(1)
|
227
|
+
mock_login_permission(@account, @user1)
|
228
|
+
mock_login_permission(@account, @user2)
|
229
|
+
mock_credential(@user1, 'moo', 'sha', days_ago(2))
|
230
|
+
mock_credential(@user2, 'moo', 'sha', @t)
|
231
|
+
|
232
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
233
|
+
@policy.created_at.to_s.should == @t.to_s
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should match a Permission.updated_at that is most recent within scope' do
|
237
|
+
@t = days_ago(1)
|
238
|
+
mock_login_permission(@account, @user1, nil, days_ago(2))
|
239
|
+
mock_login_permission(@account, @user2, nil, @t)
|
240
|
+
mock_credential(@user1, 'moo')
|
241
|
+
mock_credential(@user2, 'moo')
|
242
|
+
|
243
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
244
|
+
@policy.created_at.to_s.should == @t.to_s
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'calculating exclusive' do
|
249
|
+
before(:each) do
|
250
|
+
@account, @user = mock_account_and_users(1)
|
251
|
+
mock_credential(@user, 'moo')
|
252
|
+
mock_login_permission(@account, @user, nil, days_ago(2))
|
253
|
+
@instance = mock_instance(@account)
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should be exclusive if Managed SSH is mandatory for the account' do
|
257
|
+
@account.should_receive(:setting).with('managed_login_mandatory').and_return(true)
|
258
|
+
|
259
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
260
|
+
@policy.exclusive.should == true
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'should not be exclusive if Managed SSH is optional for the account' do
|
264
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
265
|
+
@policy.exclusive.should == false
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'should use the audit_id passed in by the caller' do
|
270
|
+
@account, @user = mock_account_and_users(1)
|
271
|
+
@instance = mock_instance(@account)
|
272
|
+
mock_credential(@user, 'moo')
|
273
|
+
mock_login_permission(@account, @user, nil, days_ago(2))
|
274
|
+
|
275
|
+
@policy = RightScale::LoginPolicyFactory.policy_for_instance(@instance, 1234)
|
276
|
+
@policy.audit_id.should == 1234
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|