forked from xapi-project/xen-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
extauth-hook-AD.py
executable file
·155 lines (131 loc) · 5.42 KB
/
extauth-hook-AD.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
100
101
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python
#
# extauth-hook-AD.py
#
# This module can be called directly as a plugin. It handles
# Active Directory being enabled or disabled as the hosts external_auth_type,
# or subjects being added or removed while AD is the external_auth_type,
# or xapi starting or stopping while AD is the external_auth_type.
#
# Alternatively, the extauth-hook module can be called, which will
# dispatch to the correct extauth-hook-<type>.py module automatically.
import XenAPIPlugin
import XenAPI
import sys
import os
import getopt
import tempfile
import commands
import syslog
etc_pamd_sshd_start_boilerplate = """#%PAM-1.0
auth required pam_env.so
auth sufficient pam_unix.so try_first_pass nullok
auth sufficient pam_lsass.so try_first_pass
auth required pam_deny.so
session optional pam_keyinit.so force revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so
session required pam_loginuid.so
session sufficient pam_lsass.so
account required pam_nologin.so
account required pam_lsass.so unknown_ok
# Start of list of allowed AD groups and users
"""
etc_pamd_sshd_end_boilerplate = """
# End of list of allowed AD groups and users
account required pam_unix.so
"""
etc_pamd_sshd_ad_disabled = """#%PAM-1.0
auth include system-auth
account required pam_nologin.so
account include system-auth
password include system-auth
session optional pam_keyinit.so force revoke
session include system-auth
session required pam_loginuid.so
"""
def log_err(err):
print >>sys.stderr, err
syslog.syslog(syslog.LOG_USER | syslog.LOG_ERR, "%s: %s" % (sys.argv[0], err))
class PamSshConfig:
def __init__(self):
# Create a temporary file for staging, and start it off
self.temp_fd, self.temp_fname = tempfile.mkstemp(prefix="sshd-", dir="/etc/pam.d")
os.write(self.temp_fd, etc_pamd_sshd_start_boilerplate)
self.installed = False
def install(self):
# Complete the temporary file and move it to /etc/pam.d/sshd
os.write(self.temp_fd, etc_pamd_sshd_end_boilerplate)
os.rename(self.temp_fname, "/etc/pam.d/sshd")
self.installed = True
def add_subject(self, sid):
# Add a subject to the temporary file
if self.installed:
raise Exception, "Cannot add subject once installed "
lines = commands.getoutput("/opt/likewise/bin/lw-find-by-sid %s" % sid).split("\n")
name_lines = filter(lambda x: x.startswith("Name:"), lines)
if len(name_lines) != 1:
# Just warn, don't raise exception - there may be others that work
log_err("Could not find user/group corresponding to SID %s (%s)" % (sid,str(lines)))
return
name = name_lines[0].split(":")[1].strip()
uid_lines = filter(lambda x: x.startswith("Uid:"), lines)
if len(uid_lines) == 0:
is_group = True
else:
is_group = False
if is_group:
os.write(self.temp_fd, "account sufficient pam_succeed_if.so user ingroup %s\n" % name)
else:
os.write(self.temp_fd, "account sufficient pam_succeed_if.so user = %s\n" % name)
def rewrite_etc_pamd_ssh(session, args):
# Rewrite the PAM SSH config using the latest info from Active Directory
# and the list of subjects from xapi
try:
config = PamSshConfig()
subjects = session.xenapi.subject.get_all()
admin_role = session.xenapi.role.get_by_name_label('pool-admin')[0]
# Add each subject which contains the admin role
for opaque_ref in subjects:
subject_rec = session.xenapi.subject.get_record(opaque_ref)
sid = subject_rec['subject_identifier']
if admin_role in subject_rec['roles']:
config.add_subject(sid)
config.install()
return str(True)
except:
return "ERROR_0: rewrite_etc_pamd_ssh failed"
def revert_etc_pamd_ssh(session, args):
# Revert the PAM SSH config to the default version that doesn't support
# Active Directory
try:
fd, fname = tempfile.mkstemp(prefix="sshd-", dir="/etc/pam.d")
os.write(fd, etc_pamd_sshd_ad_disabled)
os.rename(fname, "/etc/pam.d/sshd")
return str(True)
except:
return "ERROR_1: revert_etc_pamd_ssh failed"
def after_extauth_enable(session, args):
return rewrite_etc_pamd_ssh(session, args)
def after_xapi_initialize(session, args):
return rewrite_etc_pamd_ssh(session, args)
def after_subject_add(session, args):
return rewrite_etc_pamd_ssh(session, args)
def after_subject_remove(session, args):
return rewrite_etc_pamd_ssh(session, args)
def after_roles_update(session, args):
return rewrite_etc_pamd_ssh(session, args)
def before_extauth_disable(session, args):
return revert_etc_pamd_ssh(session, args)
# The dispatcher
if __name__ == "__main__":
dispatch_tbl = {
"after-extauth-enable": after_extauth_enable,
"after-xapi-initialize": after_xapi_initialize,
"after-subject-add": after_subject_add,
"after-subject-remove": after_subject_remove,
"after-roles-update": after_roles_update,
"before-extauth-disable":before_extauth_disable,
}
XenAPIPlugin.dispatch(dispatch_tbl)