|
Lines 32-37
Link Here
|
| 32 |
# <http://www.gnu.org/licenses/>. |
32 |
# <http://www.gnu.org/licenses/>. |
| 33 |
|
33 |
|
| 34 |
import subprocess |
34 |
import subprocess |
|
|
35 |
import contextlib |
| 35 |
|
36 |
|
| 36 |
import univention.config_registry |
37 |
import univention.config_registry |
| 37 |
from univention.management.console.modules.diagnostic import Critical |
38 |
from univention.management.console.modules.diagnostic import Critical |
|
Lines 39-85
from univention.management.console.modules.diagnostic import Critical
Link Here
|
| 39 |
from univention.lib.i18n import Translation |
40 |
from univention.lib.i18n import Translation |
| 40 |
_ = Translation('univention-management-console-module-diagnostic').translate |
41 |
_ = Translation('univention-management-console-module-diagnostic').translate |
| 41 |
|
42 |
|
| 42 |
title = _('Check for Kerberos-authenticated DNS Updates') |
43 |
title = _('Check kerberos authenticated DNS updates') |
| 43 |
description = _('The check for updating DNS-Records with Kerberos Authentication was successful.') |
44 |
description = _('No errors occured.') |
|
|
45 |
|
| 46 |
|
| 47 |
class UpdateError(Exception): |
| 48 |
pass |
| 49 |
|
| 50 |
|
| 51 |
class KinitError(UpdateError): |
| 52 |
def __init__(self, principal, keytab, password_file): |
| 53 |
super(KinitError, self).__init__(principal, keytab, password_file) |
| 54 |
self.principal = principal |
| 55 |
self.keytab = keytab |
| 56 |
self.password_file = password_file |
| 57 |
|
| 58 |
def __str__(self): |
| 59 |
if self.keytab: |
| 60 |
msg = _('`kinit` for principal {princ} with keytab {tab} failed.') |
| 61 |
else: |
| 62 |
msg = _('`kinit` for principal {princ} with password file {file} failed.') |
| 63 |
return msg.format(princ=self.principal, tab=self.keytab, file=self.password_file) |
| 64 |
|
| 65 |
|
| 66 |
class NSUpdateError(UpdateError): |
| 67 |
def __init__(self, hostname, domainname): |
| 68 |
super(NSUpdateError, self).__init__(hostname, domainname) |
| 69 |
self.hostname = hostname |
| 70 |
self.domainname = domainname |
| 71 |
|
| 72 |
def __str__(self): |
| 73 |
msg = _('`nsupdate` existence check for domain {domain} failed.') |
| 74 |
return msg.format(domain=self.domainname) |
| 75 |
|
| 76 |
|
| 77 |
@contextlib.contextmanager |
| 78 |
def kinit(principal, keytab=None, password_file=None): |
| 79 |
auth = '--keytab={tab}' if keytab else '--password-file={file}' |
| 80 |
cmd = ('kinit', auth.format(tab=keytab, file=password_file), principal) |
| 81 |
try: |
| 82 |
subprocess.check_call(cmd) |
| 83 |
except subprocess.CalledProcessError: |
| 84 |
raise KinitError(principal, keytab, password_file) |
| 85 |
else: |
| 86 |
yield |
| 87 |
subprocess.call(('kdestroy',)) |
| 88 |
|
| 89 |
|
| 90 |
def nsupdate(hostname, domainname): |
| 91 |
process = subprocess.Popen(('nsupdate', '-g'), stdin=subprocess.PIPE, |
| 92 |
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 93 |
cmd = 'server {host}.{domain}\nprereq yxdomain {domain}\n' |
| 94 |
_ = process.communicate(cmd.format(host=hostname, domain=domainname)) |
| 95 |
if process.poll() != 0: |
| 96 |
raise NSUpdateError(hostname, domainname) |
| 97 |
|
| 98 |
|
| 99 |
def check_dns_machine_principal(hostname, domainname): |
| 100 |
with kinit('{}$'.format(hostname), password_file='/etc/machine.secret'): |
| 101 |
nsupdate(hostname, domainname) |
| 102 |
|
| 103 |
|
| 104 |
def check_dns_server_principal(hostname, domainname): |
| 105 |
with kinit('dns-{}'.format(hostname), keytab='/var/lib/samba/private/dns.keytab'): |
| 106 |
nsupdate(hostname, domainname) |
| 107 |
|
| 108 |
|
| 109 |
def check_nsupdate(hostname, domainname, is_dc=False): |
| 110 |
try: |
| 111 |
check_dns_machine_principal(hostname, domainname) |
| 112 |
except UpdateError as error: |
| 113 |
yield error |
| 114 |
|
| 115 |
if is_dc: |
| 116 |
try: |
| 117 |
check_dns_server_principal(hostname, domainname) |
| 118 |
except UpdateError as error: |
| 119 |
yield error |
| 44 |
|
120 |
|
| 45 |
|
121 |
|
| 46 |
def run(): |
122 |
def run(): |
| 47 |
config_registry = univention.config_registry.ConfigRegistry() |
123 |
config_registry = univention.config_registry.ConfigRegistry() |
| 48 |
config_registry.load() |
124 |
config_registry.load() |
| 49 |
|
125 |
|
| 50 |
pwdpath = config_registry.get("umc/module/diagnostic/umc_password") |
126 |
hostname = config_registry.get('hostname') |
| 51 |
hostname = config_registry.get("umc/module/diagnostic/umc_user") |
127 |
domainname = config_registry.get('domainname') |
| 52 |
domainname = config_registry.get("domainname") |
128 |
is_dc = config_registry.get('samba4/role') == 'DC' |
| 53 |
kerberos_realm = config_registry.get("kerberos/realm") |
129 |
|
| 54 |
process = subprocess.Popen(['testparm', '-sv'], stdout=subprocess.PIPE, |
130 |
problems = list(check_nsupdate(hostname, domainname, is_dc)) |
| 55 |
stderr=subprocess.STDOUT) |
131 |
if problems: |
| 56 |
stdout, stderr = process.communicate() |
132 |
ed = [_('Errors occured while running `kinit` or `nsupdate`.')] |
| 57 |
samba_server_role = utils.get_string_between_strings(stdout, "server role = ", "\n") |
133 |
ed.extend(str(error) for error in problems) |
| 58 |
|
134 |
raise Critical(description='\n'.join(ed)) |
| 59 |
if not samba_server_role == "active directory domain controller": |
135 |
|
| 60 |
return |
|
|
| 61 |
|
| 62 |
kinit = ['kinit', '--password-file=%s' % (pwdpath), '%s@%s' % (hostname, kerberos_realm)] |
| 63 |
process = subprocess.Popen(kinit, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 64 |
if process.returncode: |
| 65 |
description = _('Kinit with machine account failed') |
| 66 |
raise Critical('\n'.join([ |
| 67 |
description, |
| 68 |
"Returncode of process: %s" % (process.returncode) |
| 69 |
])) |
| 70 |
stdout, stderr = process.communicate() |
| 71 |
nsupdate_process = subprocess.Popen(['nsupdate', '-g'], |
| 72 |
stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 73 |
nsupdate_process.stdin.write('prereq yxdomain %s\nsend\nquit\n' % (domainname)) |
| 74 |
stdout, stderr = nsupdate_process.communicate() |
| 75 |
if nsupdate_process.returncode != 0: |
| 76 |
description = _('nsupdate -g failed') |
| 77 |
raise Critical('\n'.join([ |
| 78 |
description, |
| 79 |
"Returncode of process: %s" % (nsupdate_process.returncode), |
| 80 |
"stdout: %s" % (stdout), |
| 81 |
"stderr: %s" % (stderr) |
| 82 |
])) |
| 83 |
|
136 |
|
| 84 |
if __name__ == '__main__': |
137 |
if __name__ == '__main__': |
| 85 |
from univention.management.console.modules.diagnostic import main |
138 |
from univention.management.console.modules.diagnostic import main |
| 86 |
- |
|
|
| 87 |
`kerberos_ddns_update.py` (po) |
139 |
`kerberos_ddns_update.py` (po) |
| 88 |
-- |
|
|
| 89 |
.../umc/python/diagnostic/de.po | 36 ++++++++++++++++++++-- |
140 |
.../umc/python/diagnostic/de.po | 36 ++++++++++++++++++++-- |
| 90 |
1 file changed, 34 insertions(+), 2 deletions(-) |
141 |
1 file changed, 34 insertions(+), 2 deletions(-) |