Class: RightScale::LoginPolicyFactory
- Inherits:
-
Object
- Object
- RightScale::LoginPolicyFactory
- Defined in:
- lib/right_infrastructure_agent/login_policy_factory.rb
Constant Summary collapse
- INVALID_USERNAME_CHARS =
Regexp used to substitute sequences of non-username-friendly characters with a humble underscore. Technically we are more strict than the POSIX standard allows (a username could have any character in his name that is a valid filename character), but we want to have sane and legal usernames.
/[^a-z0-9_]+/
- OLD_PUBLIC_KEY_BOUNDARY_AGE =
Number of seconds before a public key is considered old
24 * 60 * 60
Class Method Summary collapse
-
.policy_for_account(account, terse = false) ⇒ Object
Create LoginPolicy for given account, including all users that are authorized to login, their public keys, etc.
-
.policy_for_instance(instance, audit_id, terse = false) ⇒ Object
Create LoginPolicy for given instance, including all users that are authorized to login, their public keys, etc.
- .users_with_role(account, role) ⇒ Object
Class Method Details
.policy_for_account(account, terse = false) ⇒ Object
Create LoginPolicy for given account, including all users that are authorized to login, their public keys, etc. The policy is based on Permissions, UserCredentials and Settings of the account and is uniform across all instances of the account. Optionally omit public keys that have not been updated recently with the expectation that the receiver of this policy instead uses the fingerprint to determine whether it needs to request the update.
Parameters
- account(Account)
-
Account that login policy should be built for
- terse(Boolean)
-
Whether to omit a public key from the policy if it was created
more than OLD_PUBLIC_KEY_BOUNDARY_AGE seconds ago
Return
policy(RightScale::LoginPolicy) Policy specifying which users may login & some related metadata
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/right_infrastructure_agent/login_policy_factory.rb', line 36 def self.policy_for_account(account, terse = false) # Find all users who are allowed and able to do managed login. Simultaneously build some indices # of timestamps authorizing perms, which will be used presently to create the policy object. # Build the policy and its list of users old_cred_boundary = Time.now - OLD_PUBLIC_KEY_BOUNDARY_AGE = Time.at(0) policy = LoginPolicy.new policy.exclusive = account.setting('managed_login_mandatory') # Do this as a closure around the timestamp and cred boundaries instead # of a method to avoid having to pass them back and forth constantly. create_login_user = Proc.new do |u, is_superuser| cred_updated_at = Time.parse(u.cred_updated_at) = [, Time.parse(u.perm_updated_at), cred_updated_at].max # Currently there is only one public key per user but in the future there may be more # There should always be the exact number of fingerprints public_keys = [u.cred_public_value] processed_keys = [] public_key_fingerprints = [u.cred_public_fingerprint] processed_fingerprints = [] if terse && cred_updated_at < old_cred_boundary processed_keys = public_keys.map { |k| nil } processed_fingerprints = public_key_fingerprints else # Post-process the public keys to make sure they are well-formed AND contain a comment # at the end of the line. Technically the comment is optional, but a bug in RightImage # 5.1.1 - 5.6 makes the comment mandatory else the instance has heinous problems # when trying to update its managed login policy. public_keys.zip(public_key_fingerprints).each do |(k, f)| if (components = LoginPolicy.parse_public_key(k)) components[3] ||= u.email processed_keys << components.compact.join(' ') processed_fingerprints << f else # In case this is some malformed or other weird key, omit its value end end end uuid = u.id.to_s username = u.email.split('@', 2).first.downcase.gsub(INVALID_USERNAME_CHARS,'_') common_name = u.email superuser = is_superuser expires_at = u.perm_deleted_at.nil? ? nil : Time.parse(u.perm_deleted_at) LoginUser.new(uuid, username, public_key = nil, common_name, superuser, expires_at, processed_keys, profiled_data = nil, processed_fingerprints) end # Get list of all super users superusers = users_with_role(account, 'server_superuser') # Build all users conditionally on inclusion of superusers list policy.users = users_with_role(account, 'server_login').map do |u| create_login_user.call(u, (superusers && superusers.include?(u)) || false ) end policy.created_at = return policy end |
.policy_for_instance(instance, audit_id, terse = false) ⇒ Object
Create LoginPolicy for given instance, including all users that are authorized to login, their public keys, etc. Currently this just delegates to #policy_for_account since all instances of a given account have the same policy at a given time. This may change in the future, however.
Parameters
- instance(Ec2Instance)
-
Instance that login policy should be built for
- audit_id(Integer)
-
Audit identifier
- terse(Boolean)
-
Whether to omit a public key from the policy if it was created
more than OLD_PUBLIC_KEY_BOUNDARY_AGE seconds ago
Return
policy(RightScale::LoginPolicy) Policy specifying which users may login & some related metadata
114 115 116 117 118 |
# File 'lib/right_infrastructure_agent/login_policy_factory.rb', line 114 def self.policy_for_instance(instance, audit_id, terse = false) policy = policy_for_account(instance.account, terse) policy.audit_id = audit_id return policy end |
.users_with_role(account, role) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/right_infrastructure_agent/login_policy_factory.rb', line 120 def self.users_with_role(account, role) User.all( :select => "`users`.*, `user_credentials`.public_value as cred_public_value, " + "`user_credentials`.updated_at as cred_updated_at, " + "`user_credentials`.public_value_fingerprint as cred_public_fingerprint, " + "`permissions`.updated_at as perm_updated_at, " + "`permissions`.deleted_at as perm_deleted_at", :joins => [:user_credential, :permissions], :conditions => ["permissions.account_id = ? " + "AND permissions.role_id = ? " + "AND (permissions.deleted_at IS NULL OR permissions.deleted_at > ?) " + "AND user_credentials.public_value IS NOT NULL " + "AND user_credentials.public_value <> ''", account.id, Role[role], Time.now.utc ]) end |