Module: Xolo::Server::Helpers::Auth

Defined in:
lib/xolo/server/helpers/auth.rb

Constant Summary collapse

NO_AUTH_ROUTES =

these routes don’t need an auth’d session

[
  '/ping',
  '/auth/login',
  '/default_min_os'
].freeze
NO_AUTH_PREFIXES =

these route prefixes don’t need an auth’d session

[
  '/ping/'
].freeze
INTERNAL_ROUTES =

these routes are expected to be called by the xolo server itself and will have the internal_auth_token in the headers and will come from IPV4_LOOPBACK

We use routes like this for internal tasks that require a server-request context.

[
  '/maint/cleanup-internal'
].freeze
SERVER_ADMIN_ROUTES =

these routes must

[
  '/maint/threads',
  '/maint/state',
  '/maint/cleanup',
  '/maint/update-client-data',
  '/maint/rotate-logs',
  '/maint/set-log-level',
  '/maint/shutdown-server'
].freeze
IPV4_LOOPBACK =

The loopback address for IPV4, aka ‘localhost’

'127.0.0.1'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(includer) ⇒ Object

when this module is included



65
66
67
# File 'lib/xolo/server/helpers/auth.rb', line 65

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

.internal_auth_token_headerString

If a request comes in from one of our known IP addresses with a valid internal_auth_toke in the headers, then the request is allowed.

This allows the xolo server to send requests to itself without needing to authenticate, as is needed for some kinds of maintenance tasks such as cleanup.

The token value is generated anew at startup and is a long random string, it is only available to the xolo server itself from its memory, and is never stored.

Returns:

  • (String)

    The internal_auth_token to be used in the Authorization header of requests



82
83
84
# File 'lib/xolo/server/helpers/auth.rb', line 82

def self.internal_auth_token_header
  @internal_auth_token_header ||= "Bearer #{SecureRandom.hex(64)}"
end

Instance Method Details

#allowed_to_release_to_all?(admin_name) ⇒ Boolean

is the given username a member of the release_to_all_approval_group? If not, they are not allowed to set a title’s release_groups to ‘all’.

Parameters:

  • admin_name (String)

    The jamf acct name of the person

Returns:

  • (Boolean)

    Is the admin allowed to set release_groups to all?



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/xolo/server/helpers/auth.rb', line 189

def allowed_to_release_to_all?(admin_name)
  log_debug "Checking if '#{admin_name}' is allowed to release to all"

  groupname = Xolo::Server.config.release_to_all_jamf_group
  if groupname.pix_empty?
    log_debug 'No release_to_all_jamf_group defined, allowing all admins to release to all'
    return true
  end

  if user_in_jamf_acct_group?(groupname, admin_name)
    log_debug "'#{admin_name}' is allowed to release to all"
    true
  else
    log_debug "'#{admin_name}' is not allowed to release to all"
    false
  end
ensure
  jamf_cnx&.disconnect
end

#authenticated_via_jamf?(admin, pw) ⇒ Boolean

Try to authenticate the jamf user trying to log in to xolo

Parameters:

  • admin (String)

    The jamf acct name of the person seeking access

  • pw (String)

    The password for the jamf acct

Returns:

  • (Boolean)

    Did the password work for the user?



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/xolo/server/helpers/auth.rb', line 234

def authenticated_via_jamf?(admin, pw)
  log_debug "Checking Jamf authentication for admin '#{admin}'"
   = Jamf::Connection.new(
    host: Xolo::Server.config.jamf_hostname,
    port: Xolo::Server.config.jamf_port,
    verify_cert: Xolo::Server.config.jamf_verify_cert,
    open_timeout: Xolo::Server.config.jamf_open_timeout,
    timeout: Xolo::Server.config.jamf_timeout,
    user: admin,
    pw: pw
  )
  .disconnect
  true
rescue Jamf::AuthenticationError
  false
end

#internal_ip_ok?Boolean

Returns Is the request coming from one of our known IP addresses?.

Returns:

  • (Boolean)

    Is the request coming from one of our known IP addresses?



119
120
121
122
123
# File 'lib/xolo/server/helpers/auth.rb', line 119

def internal_ip_ok?
  # server_ip_addresses.include? request.ip
  # always require the request to come from the loopback address
  request.ip == Xolo::Server::Helpers::Auth::IPV4_LOOPBACK
end

#internal_token_ok?Boolean

Returns Is the internal_auth_token in the headers of the request?.

Returns:

  • (Boolean)

    Is the internal_auth_token in the headers of the request?



113
114
115
# File 'lib/xolo/server/helpers/auth.rb', line 113

def internal_token_ok?
  request.env['HTTP_AUTHORIZATION'] == Xolo::Server::Helpers::Auth.internal_auth_token_header
end

#member_of_admin_jamf_group?(admin_name) ⇒ Boolean

is the given username a member of the admin_jamf_group? or the server_admin_jamf_group? If not, they are not allowed to talk to the xolo server.

Parameters:

  • admin_name (String)

    The jamf acct name of the person seeking access

Returns:

  • (Boolean)

    Is the admin a member of the admin_jamf_group?



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/xolo/server/helpers/auth.rb', line 139

def member_of_admin_jamf_group?(admin_name)
  log_info "Checking if '#{admin_name}' is allowed to access the Xolo server"

  groupname = Xolo::Server.config.admin_jamf_group
  return true if user_in_jamf_acct_group?(groupname, admin_name)

  # if they're not in the admin group, check the server_admin group
  return true if member_of_server_admin_jamf_group?(admin_name)

  log_info "'#{admin_name}' is not a member of the admin_jamf_group or the server_admin_jamf_group"
  false
end

#member_of_server_admin_jamf_group?(admin_name) ⇒ Boolean

is the given username a member of the server_admin_jamf_group? they must be in order to access the server admin routes

Parameters:

  • admin_name (String)

    The jamf acct name of the person seeking access

Returns:

  • (Boolean)

    Is the admin a member of the server_admin_jamf_group?



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/xolo/server/helpers/auth.rb', line 159

def member_of_server_admin_jamf_group?(admin_name)
  return false unless Xolo::Server.config.server_admin_jamf_group

  log_info "Checking if '#{admin_name}' is allowed to access server admin routes"

  groupname = Xolo::Server.config.server_admin_jamf_group
  return true if user_in_jamf_acct_group?(groupname, admin_name)

  log_info "'#{admin_name}' is not a member of the server_admin_jamf_group '#{groupname}'"
  false
end

#server_ip_addressesArray<String>

Returns The IP addresses of this server.

Returns:

  • (Array<String>)

    The IP addresses of this server



127
128
129
# File 'lib/xolo/server/helpers/auth.rb', line 127

def server_ip_addresses
  Socket.ip_address_list.map(&:ip_address)
end

#user_in_jamf_acct_group?(groupname, username) ⇒ Boolean

check to see if a username is a member of a Jamf AccountGroup either from Jamf or from LDAP

Returns:

  • (Boolean)


211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/xolo/server/helpers/auth.rb', line 211

def user_in_jamf_acct_group?(groupname, username)
  log_debug "Checking if '#{username}' is a member of the Jamf AccountGroup '#{groupname}'"

  # This isn't well implemented in ruby-jss, so use c_get directly
  jgroup = jamf_cnx.c_get("accounts/groupname/#{groupname}")[:group]

  if jgroup[:ldap_server]
    Jamf::LdapServer.check_membership jgroup[:ldap_server][:id], username, groupname, cnx: jamf_cnx
  else
    jgroup[:members].any? { |m| m[:name] == username }
  end
rescue Jamf::NoSuchItemError
  false
end

#valid_internal_auth_token?Boolean

Is the internal_auth_token in the headers of the request? and is the request coming from one of our known IP addresses?

Returns:

  • (Boolean)

    Is this a valid request from the xolo server itself?



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/xolo/server/helpers/auth.rb', line 95

def valid_internal_auth_token?
  log_info "Checking internal auth token from #{request.ip}"

  if !internal_ip_ok?
    warning = "Invalid IP address for internal request: #{request.ip}"
  elsif !internal_token_ok?
    warning = "Invalid internal auth token '#{request.env['HTTP_AUTHORIZATION']}' from #{request.ip}"
  else
    log_info "Internal request for #{request.path} is valid"
    return true
  end

  log_warn "WARNING: #{warning}"
  halt 403, { status: 403, error: 'You do not have access to this resource' }
end

#valid_server_admin?Boolean

is the session a member of the server_admin_jamf_group, and has a valid session?

Returns:

  • (Boolean)


176
177
178
179
180
# File 'lib/xolo/server/helpers/auth.rb', line 176

def valid_server_admin?
  return true if session[:authenticated] && member_of_server_admin_jamf_group?(session[:admin])

  halt 403, { status: 403, error: 'You do not have access to that resource.' }
end