Merge branch 'master' into 6384-libpam-arvados
[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 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" % (str(e)))
25
26     try:
27         arv = arvados.api('v1',host=arvados_api_host, token=token, cache=None)
28     except Exception as e:
29         auth_log(str(e))
30         return False
31
32     try:
33         matches = arv.virtual_machines().list(filters=[['hostname','=',hostname]]).execute()['items']
34     except Exception as e:
35         auth_log(str(e))
36         return False
37
38
39     if len(matches) != 1:
40         auth_log("libpam_arvados could not determine vm uuid for '%s'" % hostname)
41         return False
42
43     this_vm_uuid = matches[0]['uuid']
44     auth_log("this_vm_uuid: %s" % this_vm_uuid)
45     client_user_uuid = arv.users().current().execute()['uuid']
46
47     filters = [
48             ['link_class','=','permission'],
49             ['name','=','can_login'],
50             ['head_uuid','=',this_vm_uuid],
51             ['tail_uuid','=',client_user_uuid]]
52
53     for l in arv.links().list(filters=filters).execute()['items']:
54          if requested_username == l['properties']['username']:
55              return  True
56     return False
57
58
59 def pam_sm_authenticate(pamh, flags, argv):
60  try:
61   user = pamh.get_user()
62  except pamh.exception, e:
63   return e.pam_result
64
65  if not user:
66   return pamh.PAM_USER_UNKNOWN
67
68  try:
69   resp = pamh.conversation(pamh.Message(pamh.PAM_PROMPT_ECHO_OFF, ''))
70  except pamh.exception, e:
71   return e.pam_result
72
73  try:
74   check = check_arvados_token(user, resp.resp)
75  except Exception as e:
76   auth_log(str(e))
77   return False
78
79  if not check:
80   auth_log("Auth failed Remote Host: %s (%s:%s)" % (pamh.rhost, user, resp.resp))
81   return pamh.PAM_AUTH_ERR
82
83  auth_log("Success! Remote Host: %s (%s:%s)" % (pamh.rhost, user, resp.resp))
84  return pamh.PAM_SUCCESS
85
86 def pam_sm_setcred(pamh, flags, argv):
87  return pamh.PAM_SUCCESS
88
89 def pam_sm_acct_mgmt(pamh, flags, argv):
90  return pamh.PAM_SUCCESS
91
92 def pam_sm_open_session(pamh, flags, argv):
93  return pamh.PAM_SUCCESS
94
95 def pam_sm_close_session(pamh, flags, argv):
96  return pamh.PAM_SUCCESS
97
98 def pam_sm_chauthtok(pamh, flags, argv):
99  return pamh.PAM_SUCCESS