Merge branch '5898-listen-race' refs #5898
[arvados.git] / sdk / pam / arvados_pam.py
1 import syslog
2 import sys
3 sys.argv=['']
4 import arvados
5 import os
6
7 def auth_log(msg):
8  """Send errors to default auth log"""
9  syslog.openlog(facility=syslog.LOG_AUTH)
10  #syslog.openlog()
11  syslog.syslog("libpam python Logged: " + msg)
12  syslog.closelog()
13
14
15 def check_arvados_token(requested_username, token):
16     auth_log("%s %s" % (requested_username, token))
17
18     try:
19         f=file('/etc/default/arvados_pam')
20         config=dict([l.split('=') for l in f.readlines() if not l.startswith('#') or l.strip()==""])
21         arvados_api_host=config['ARVADOS_API_HOST'].strip()
22         hostname=config['HOSTNAME'].strip()
23     except Exception as e:
24         auth_log("problem getting default values  %s" % e)
25         return False
26
27     try:
28         arv = arvados.api('v1',host=arvados_api_host, token=token, cache=None)
29     except Exception as e:
30         auth_log(str(e))
31         return False
32
33     try:
34         matches = arv.virtual_machines().list(filters=[['hostname','=',hostname]]).execute()['items']
35     except Exception as e:
36         auth_log(str(e))
37         return False
38
39
40     if len(matches) != 1:
41         auth_log("libpam_arvados could not determine vm uuid for '%s'" % hostname)
42         return False
43
44     this_vm_uuid = matches[0]['uuid']
45     auth_log("this_vm_uuid: %s" % this_vm_uuid)
46     client_user_uuid = arv.users().current().execute()['uuid']
47
48     filters = [
49             ['link_class','=','permission'],
50             ['name','=','can_login'],
51             ['head_uuid','=',this_vm_uuid],
52             ['tail_uuid','=',client_user_uuid]]
53
54     for l in arv.links().list(filters=filters).execute()['items']:
55          if requested_username == l['properties']['username']:
56              return  True
57     return False
58
59
60 def pam_sm_authenticate(pamh, flags, argv):
61  try:
62   user = pamh.get_user()
63  except pamh.exception, e:
64   return e.pam_result
65
66  if not user:
67   return pamh.PAM_USER_UNKNOWN
68
69  try:
70   resp = pamh.conversation(pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, ''))
71  except pamh.exception, e:
72   return e.pam_result
73
74  try:
75   check = check_arvados_token(user, resp.resp)
76  except Exception as e:
77   auth_log(str(e))
78   return False
79
80  if not check:
81   auth_log("Auth failed Remote Host: %s (%s:%s)" % (pamh.rhost, user, resp.resp))
82   return pamh.PAM_AUTH_ERR
83
84  auth_log("Success! Remote Host: %s (%s:%s)" % (pamh.rhost, user, resp.resp))
85  return pamh.PAM_SUCCESS
86
87 def pam_sm_setcred(pamh, flags, argv):
88  return pamh.PAM_SUCCESS
89
90 def pam_sm_acct_mgmt(pamh, flags, argv):
91  return pamh.PAM_SUCCESS
92
93 def pam_sm_open_session(pamh, flags, argv):
94  return pamh.PAM_SUCCESS
95
96 def pam_sm_close_session(pamh, flags, argv):
97  return pamh.PAM_SUCCESS
98
99 def pam_sm_chauthtok(pamh, flags, argv):
100  return pamh.PAM_SUCCESS