Module: Xolo::Admin::Credentials

Defined in:
lib/xolo/admin/credentials.rb

Overview

Personal credentials for users of ‘xadm’, stored in the login keychain

Constant Summary collapse

SEC_COMMAND =

The security command

'/usr/bin/security'
SEC_STATUS_NO_GUI_ERROR =

exit status when the login keychain can’t be accessed because we aren’t in a GUI session

36
SEC_STATUS_AUTH_ERROR =

exit status when the keychain password provided is incorrect

51
SEC_STATUS_NOT_FOUND_ERROR =

exit status when the desired item isn’t found in the keychain

44
XOLO_CREDS_KIND =

The ‘kind’ of item in the keychain

'Xolo::Admin::Password'
XOLO_CREDS_SVC =

the Service for the generic ‘Xolo::Admin::Credentials’ keychain entry

'com.pixar.xolo.password'
XOLO_CREDS_LBL =

the Label for the generic ‘Xolo::Admin::Credentials’ keychain entry

'Xolo Admin Password'
XOLO_CREDS_LBL_OLD =

Pre v2.0.0, the label was different. We need to check for the old one when fetching the password and if it’s there, update it to the new one. TODO: Remove this in 2.1.0 or other appropriate future version, once we can be sure most users have updated to 2.0.0 or later.

'"Xolo Admin Password"'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(includer) ⇒ Object

when this module is included



55
56
57
# File 'lib/xolo/admin/credentials.rb', line 55

def self.included(includer)
  Xolo.verbose_include includer, self
end

Instance Method Details

#delete_pwvoid

This method returns an undefined value.

delete the xolo admin password from the login keychain



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/xolo/admin/credentials.rb', line 161

def delete_pw
  cmd = ['delete-generic-password']
  cmd << '-s'
  cmd << XOLO_CREDS_SVC
  cmd << '-l'
  cmd << XOLO_CREDS_LBL

  run_security(cmd.map { |i| security_escape i }.join(' '))
rescue Xolo::NoSuchItemError
  nil
rescue RuntimeError => e
  raise e unless e.to_s == 'No matching keychain item was found'

  nil
end

#fetch_and_update_pw_if_necessaryObject

TEMPORARY - update the label of the existing keychain item if it has the old label but not the new one, to avoid prompting users to re-enter their password when we change the label in 2.0.0 TODO: Remove this in 2.1.0 or other appropriate future version, once we can be sure most users have updated to 2.0.0 or later.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/xolo/admin/credentials.rb', line 102

def fetch_and_update_pw_if_necessary
  cmd = ['find-generic-password']
  cmd << '-s'
  cmd << XOLO_CREDS_SVC
  cmd << '-l'
  cmd << XOLO_CREDS_LBL_OLD
  cmd << '-w'
  pw = run_security(cmd.map { |i| security_escape i }.join(' '))

  if @security_exit_status.exitstatus == Xolo::Core::SecurityCmd::SEC_STATUS_NOT_FOUND_ERROR
    raise Xolo::NoSuchItemError, "No xolo admin password. Please run 'xadm config'"
  end

  # then delete the old item with the old label
  cmd = ['delete-generic-password']
  cmd << '-s'
  cmd << XOLO_CREDS_SVC
  cmd << '-l'
  cmd << XOLO_CREDS_LBL_OLD
  run_security(cmd.map { |i| security_escape i }.join(' '))

  # if we found the password with the old label, update it to the new label
  store_pw(ENV['USER'], pw)

  pw
end

#fetch_pwString

If the keychain is not accessible, prompt for the password

Returns:

  • (String)

    Get the admin’s password from the login keychain



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
# File 'lib/xolo/admin/credentials.rb', line 68

def fetch_pw
  return config.data_from_command_file_or_string(config.pw, enforce_secure_mode: true) if config.no_gui

  cmd = ['find-generic-password']
  cmd << '-s'
  cmd << XOLO_CREDS_SVC
  cmd << '-l'
  cmd << XOLO_CREDS_LBL
  cmd << '-w'
  run_security(cmd.map { |i| security_escape i }.join(' '))

# TEMPORARY - check for the old label if we didn't find the password with the new label, and if we find it with the old label, update it to the new label
# TODO: Remove this in 2.1.0 or other appropriate future version,
# once we can be sure most users have updated to 2.0.0 or later.
rescue Xolo::NoSuchItemError
  fetch_and_update_pw_if_necessary

# If we can't access the keychain, prompt for the password. This is usually
# when we're running in a non-GUI session, e.g. via ssh.
rescue Xolo::KeychainError
  raise unless @security_exit_status.exitstatus == Xolo::Core::SecurityCmd::SEC_STATUS_NO_GUI_ERROR
  raise unless STDOUT.isatty

  question = "Keychain not accessible.\nPlease enter the xolo admin password for #{config.admin}: "
  highline_cli.ask(question) do |q|
    q.echo = false
  end
end

#store_pw(acct, pw) ⇒ String

Store an item in the default keychain

Parameters:

  • acct (String)

    The username for the password. xadm doesn’t use this, it uses the admin name from the configuration. But the keychain item requires a value here.

  • pw (String)

    The password to store

Returns:

  • (String)

    the location where the password is stored



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/xolo/admin/credentials.rb', line 139

def store_pw(acct, pw)
  # delete the item first if its there
  delete_pw

  cmd = ['add-generic-password']
  cmd <<  '-a'
  cmd <<  acct
  cmd << '-s'
  cmd << XOLO_CREDS_SVC
  cmd << '-w'
  cmd << pw
  cmd << '-l'
  cmd << XOLO_CREDS_LBL
  cmd << '-D'
  cmd << XOLO_CREDS_KIND

  run_security(cmd.map { |i| security_escape i }.join(' '))
end