__docformat__ = "restructuredText"
from base64 import b64encode
+import errno
import os
import re
import pwd
self.dns = None
self.winsdb = None
self.private_dir = None
+ self.binddns_dir = None
self.state_dir = None
"""
paths = ProvisionPaths()
paths.private_dir = lp.get("private dir")
+ paths.binddns_dir = lp.get("binddns dir")
paths.state_dir = lp.get("state directory")
# This is stored without path prefix for the "privateKeytab" attribute in
paths.idmapdb = os.path.join(paths.private_dir, "idmap.ldb")
paths.secrets = os.path.join(paths.private_dir, "secrets.ldb")
paths.privilege = os.path.join(paths.private_dir, "privilege.ldb")
- paths.dns = os.path.join(paths.private_dir, "dns", dnsdomain + ".zone")
paths.dns_update_list = os.path.join(paths.private_dir, "dns_update_list")
paths.spn_update_list = os.path.join(paths.private_dir, "spn_update_list")
- paths.namedconf = os.path.join(paths.private_dir, "named.conf")
- paths.namedconf_update = os.path.join(paths.private_dir, "named.conf.update")
- paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
paths.kdcconf = os.path.join(paths.private_dir, "kdc.conf")
paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
+
+ paths.dns = os.path.join(paths.binddns_dir, "dns", dnsdomain + ".zone")
+ paths.namedconf = os.path.join(paths.binddns_dir, "named.conf")
+ paths.namedconf_update = os.path.join(paths.binddns_dir, "named.conf.update")
+ paths.namedtxt = os.path.join(paths.binddns_dir, "named.txt")
+
paths.hklm = "hklm.ldb"
paths.hkcr = "hkcr.ldb"
paths.hkcu = "hkcu.ldb"
if os.path.exists(keytab_path):
os.unlink(keytab_path)
+ bind_dns_keytab_path = os.path.join(paths.binddns_dir, paths.dns_keytab)
+ if os.path.exists(bind_dns_keytab_path):
+ os.unlink(bind_dns_keytab_path)
+
dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
if os.path.exists(dns_keytab_path):
os.unlink(dns_keytab_path)
else:
samdb.transaction_commit()
+def directory_create_or_exists(path, mode=0o755):
+ if not os.path.exists(path):
+ try:
+ os.mkdir(path, mode)
+ except OSError as e:
+ if e.errno in [errno.EEXIST]:
+ pass
+ else:
+ raise ProvisioningError("Failed to create directory %s: %s" % (path, e.strerror))
def provision(logger, session_info, smbconf=None,
targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
if serverrole is None:
serverrole = lp.get("server role")
- if not os.path.exists(paths.private_dir):
- os.mkdir(paths.private_dir, 0o700)
- if not os.path.exists(os.path.join(paths.private_dir, "tls")):
- os.makedirs(os.path.join(paths.private_dir, "tls"), 0700)
- if not os.path.exists(paths.state_dir):
- os.mkdir(paths.state_dir)
+ directory_create_or_exists(paths.private_dir, 0o700)
+ directory_create_or_exists(paths.binddns_dir, 0o770)
+ directory_create_or_exists(os.path.join(paths.private_dir, "tls"))
+ directory_create_or_exists(paths.state_dir)
if paths.sysvol and not os.path.exists(paths.sysvol):
os.makedirs(paths.sysvol, 0775)
# Now commit the secrets.ldb to disk
secrets_ldb.transaction_commit()
- # the commit creates the dns.keytab, now chown it
- dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
- if os.path.isfile(dns_keytab_path) and paths.bind_gid is not None:
+ # the commit creates the dns.keytab in the private directory
+ private_dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
+ bind_dns_keytab_path = os.path.join(paths.binddns_dir, paths.dns_keytab)
+
+ if os.path.isfile(private_dns_keytab_path):
+ if os.path.isfile(bind_dns_keytab_path):
+ try:
+ os.unlink(bind_dns_keytab_path)
+ except OSError as e:
+ logger.error("Failed to remove %s: %s" %
+ (bind_dns_keytab_path, e.strerror))
+
+ # link the dns.keytab to the bind-dns directory
try:
- os.chmod(dns_keytab_path, 0640)
- os.chown(dns_keytab_path, -1, paths.bind_gid)
- except OSError:
- if not os.environ.has_key('SAMBA_SELFTEST'):
- logger.info("Failed to chown %s to bind gid %u",
- dns_keytab_path, paths.bind_gid)
+ os.link(private_dns_keytab_path, bind_dns_keytab_path)
+ except OSError as e:
+ logger.error("Failed to create link %s -> %s: %s" %
+ (private_dns_keytab_path, bind_dns_keytab_path, e.strerror))
+
+ # chown the dns.keytab in the bind-dns directory
+ if paths.bind_gid is not None:
+ try:
+ os.chmod(bind_dns_keytab_path, 0640)
+ os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
+ except OSError:
+ if not os.environ.has_key('SAMBA_SELFTEST'):
+ logger.info("Failed to chown %s to bind gid %u",
+ bind_dns_keytab_path, paths.bind_gid)
result = ProvisionResult()
result.server_role = serverrole
fqdn_hostname)
-def secretsdb_setup_dns(secretsdb, names, private_dir, realm,
+def secretsdb_setup_dns(secretsdb, names, private_dir, binddns_dir, realm,
dnsdomain, dns_keytab_path, dnspass, key_version_number):
"""Add DNS specific bits to a secrets database.
"""
try:
os.unlink(os.path.join(private_dir, dns_keytab_path))
+ os.unlink(os.path.join(binddns_dir, dns_keytab_path))
except OSError:
pass
if key_version_number is None:
key_version_number = 1
+ # This will create the dns.keytab file in the private_dir when it is
+ # commited!
setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), {
"REALM": realm,
"DNSDOMAIN": dnsdomain,
})
-def create_named_txt(path, realm, dnsdomain, dnsname, private_dir,
+def create_named_txt(path, realm, dnsdomain, dnsname, binddns_dir,
keytab_name):
"""Write out a file containing zone statements suitable for inclusion in a
named.conf file (including GSS-TSIG configuration).
:param path: Path of the new named.conf file.
:param realm: Realm name
:param dnsdomain: DNS Domain name
- :param private_dir: Path to private directory
+ :param binddns_dir: Path to bind dns directory
:param keytab_name: File name of DNS keytab file
"""
setup_file(setup_path("named.txt"), path, {
"DNSNAME" : dnsname,
"REALM": realm,
"DNS_KEYTAB": keytab_name,
- "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
- "PRIVATE_DIR": private_dir
+ "DNS_KEYTAB_ABS": os.path.join(binddns_dir, keytab_name),
+ "PRIVATE_DIR": binddns_dir
})
domainguid = get_domainguid(samdb, domaindn)
secretsdb_setup_dns(secretsdb, names,
- paths.private_dir, realm=names.realm,
+ paths.private_dir,
+ paths.binddns_dir,
+ realm=names.realm,
dnsdomain=names.dnsdomain,
dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
key_version_number=key_version_number)
create_named_txt(paths.namedtxt,
realm=names.realm, dnsdomain=names.dnsdomain,
dnsname = "%s.%s" % (names.hostname, names.dnsdomain),
- private_dir=paths.private_dir,
+ binddns_dir=paths.binddns_dir,
keytab_name=paths.dns_keytab)
logger.info("See %s for an example configuration include file for BIND",
paths.namedconf)
paths = ProvisionPaths()
paths.secrets = path
paths.private_dir = os.path.dirname(path)
+ paths.binddns_dir = os.path.dirname(path)
paths.keytab = "no.keytab"
paths.dns_keytab = "no.dns.keytab"
secrets_ldb = setup_secretsdb(paths, None, None, lp=lp)
secrets_tdb_path = os.path.join(self.tempdir, "secrets.tdb")
paths.secrets = path
paths.private_dir = os.path.dirname(path)
+ paths.binddns_dir = os.path.dirname(path)
paths.keytab = "no.keytab"
paths.dns_keytab = "no.dns.keytab"
ldb = setup_secretsdb(paths, None, None, lp=env_loadparm())
dns_key_version_number = None
secretsdb_setup_dns(ldbs.secrets, names,
- paths.private_dir, realm=names.realm,
+ paths.private_dir, paths.binddns_dir, realm=names.realm,
dnsdomain=names.dnsdomain,
dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
key_version_number=dns_key_version_number)
else:
logger.info("dns-%s account already exists" % hostname)
- dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
- if os.path.isfile(dns_keytab_path) and paths.bind_gid is not None:
+ private_dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab)
+ bind_dns_keytab_path = os.path.join(paths.binddns_dir, paths.dns_keytab)
+
+ if os.path.isfile(private_dns_keytab_path):
+ if os.path.isfile(bind_dns_keytab_path):
+ try:
+ os.unlink(bind_dns_keytab_path)
+ except OSError as e:
+ logger.error("Failed to remove %s: %s" %
+ (bind_dns_keytab_path, e.strerror))
+
+ # link the dns.keytab to the bind-dns directory
try:
- os.chmod(dns_keytab_path, 0640)
- os.chown(dns_keytab_path, -1, paths.bind_gid)
- except OSError:
- if not os.environ.has_key('SAMBA_SELFTEST'):
- logger.info("Failed to chown %s to bind gid %u",
- dns_keytab_path, paths.bind_gid)
+ os.link(private_dns_keytab_path, bind_dns_keytab_path)
+ except OSError as e:
+ logger.error("Failed to create link %s -> %s: %s" %
+ (private_dns_keytab_path, bind_dns_keytab_path, e.strerror))
+
+ # chown the dns.keytab in the bind-dns directory
+ if paths.bind_gid is not None:
+ try:
+ os.chmod(bind_dns_keytab_path, 0640)
+ os.chown(bind_dns_keytab_path, -1, paths.bind_gid)
+ except OSError:
+ if not os.environ.has_key('SAMBA_SELFTEST'):
+ logger.info("Failed to chown %s to bind gid %u",
+ bind_dns_keytab_path, paths.bind_gid)
+
# This forces a re-creation of dns directory and all the files within
# It's an overkill, but it's easier to re-create a samdb copy, rather
create_named_conf(paths, names.realm, dnsdomain, opts.dns_backend, logger)
create_named_txt(paths.namedtxt, names.realm, dnsdomain, dnsname,
- paths.private_dir, paths.dns_keytab)
+ paths.binddns_dir, paths.dns_keytab)
logger.info("See %s for an example configuration include file for BIND", paths.namedconf)
logger.info("and %s for further documentation required for secure DNS "
"updates", paths.namedtxt)
-def check_for_DNS(refprivate, private, dns_backend):
+def check_for_DNS(refprivate, private, refbinddns_dir, binddns_dir, dns_backend):
"""Check if the provision has already the requirement for dynamic dns
:param refprivate: The path to the private directory of the reference
namedfile = lp.get("dnsupdate:path")
if not namedfile:
- namedfile = "%s/named.conf.update" % private
+ namedfile = "%s/named.conf.update" % binddns_dir
if not os.path.exists(namedfile):
- destdir = "%s/new_dns" % private
- dnsdir = "%s/dns" % private
+ destdir = "%s/new_dns" % binddns_dir
+ dnsdir = "%s/dns" % binddns_dir
if not os.path.exists(destdir):
os.mkdir(destdir)
if not os.path.exists(dnsdir):
os.mkdir(dnsdir)
- shutil.copy("%s/named.conf" % refprivate, "%s/named.conf" % destdir)
- shutil.copy("%s/named.txt" % refprivate, "%s/named.txt" % destdir)
+ shutil.copy("%s/named.conf" % refbinddns_dir, "%s/named.conf" % destdir)
+ shutil.copy("%s/named.txt" % refbinddns_dir, "%s/named.txt" % destdir)
message(SIMPLE, "It seems that your provision did not integrate "
"new rules for dynamic dns update of domain related entries")
message(SIMPLE, "A copy of the new bind configuration files and "
# 20)
updateOEMInfo(ldbs.sam, str(names.rootdn))
# 21)
- check_for_DNS(newpaths.private_dir, paths.private_dir, names.dns_backend)
+ check_for_DNS(newpaths.private_dir, paths.private_dir,
+ newpaths.binddns_dir, paths.binddns_dir,
+ names.dns_backend)
# 22)
update_provision_usn(ldbs.sam, minUSN, maxUSN, names.invocation)
if opts.full and (names.policyid is None or names.policyid_dc is None):
server role = domain controller
private dir = @@PREFIX@@/private
+ binddns dir = @@PREFIX@@/bind-dns
lock dir = @@PREFIX@@/
posix:eadb = @@PREFIX@@/private/eadb.tdb
# - Modify BIND init scripts to pass the location of the generated keytab file.
# Fedora 8 & later provide a variable named KEYTAB_FILE in /etc/sysconfig/named
# for this purpose:
-KEYTAB_FILE="/home/mat/workspace/samba/alpha13/private/dns.keytab"
+KEYTAB_FILE="/home/mat/workspace/samba/alpha13/bind-dns/dns.keytab"
# Note that the Fedora scripts translate KEYTAB_FILE behind the scenes into a
# variable named KRB5_KTNAME, which is ultimately passed to the BIND daemon. If
# your distribution does not provide a variable like KEYTAB_FILE to pass a
# keytab file to the BIND daemon, a workaround is to place the following line in
# BIND's sysconfig file or in the init script for BIND:
-export KRB5_KTNAME="/home/mat/workspace/samba/alpha13/private/dns.keytab"
+export KRB5_KTNAME="/home/mat/workspace/samba/alpha13/bind-dns/dns.keytab"
# - Set appropriate ownership and permissions on the dns.keytab file. Note
# that most distributions have BIND configured to run under a non-root user
# by the user that BIND run as. If BIND is running as a non-root user, the
# "dns.keytab" file must have its permissions altered to allow the daemon to
# read it. Under Fedora 9, execute the following commands:
-chgrp named /home/mat/workspace/samba/alpha13/private/dns.keytab
-chmod g+r /home/mat/workspace/samba/alpha13/private/dns.keytab
+chgrp named /home/mat/workspace/samba/alpha13/bind-dns/dns.keytab
+chmod g+r /home/mat/workspace/samba/alpha13/bind-dns/dns.keytab
# - Ensure the BIND zone file(s) that will be dynamically updated are in a
# directory where the BIND daemon can write. When BIND performs dynamic
# file contexts. The dns.keytab file must be accessible by the BIND daemon
# and should have a SELinux type of named_conf_t. This can be set with the
# following command:
-chcon -t named_conf_t /home/mat/workspace/samba/alpha13/private/dns.keytab
+chcon -t named_conf_t /home/mat/workspace/samba/alpha13/bind-dns/dns.keytab
server role = domain controller
private dir = @@PREFIX@@/private
+ binddns dir = @@PREFIX@@/bind-dns
lock dir = @@PREFIX@@/
posix:eadb = @@PREFIX@@/private/eadb.tdb
server role = domain controller
private dir = @@PREFIX@@/private
+ binddns dir = @@PREFIX@@/bind-dns
lock dir = @@PREFIX@@/
posix:eadb = @@PREFIX@@/private/eadb.tdb
# 1. Insert following lines into the options {} section of your named.conf
# file:
-tkey-gssapi-keytab "/data/samba/git/samba4.1/st/promoted_dc/private/dns.keytab";
+tkey-gssapi-keytab "/data/samba/git/samba4.1/st/promoted_dc/bind-dns/dns.keytab";
#
# Common Steps for BIND 9.x.x --------------------------------------------
# is running as a non-root user, the "dns.keytab" file must have its
# permissions altered to allow the daemon to read it. Under Fedora 9,
# execute the following commands:
-chgrp named /data/samba/git/samba4.1/st/promoted_dc/private/dns.keytab
-chmod g+r /data/samba/git/samba4.1/st/promoted_dc/private/dns.keytab
+chgrp named /data/samba/git/samba4.1/st/promoted_dc/bind-dns/dns.keytab
+chmod g+r /data/samba/git/samba4.1/st/promoted_dc/bind-dns/dns.keytab
# 3. Ensure the BIND zone file(s) that will be dynamically updated are in
# a directory where the BIND daemon can write. When BIND performs
# SELinux file contexts. The dns.keytab file must be accessible by the
# BIND daemon and should have a SELinux type of named_conf_t. This can be
# set with the following command:
-chcon -t named_conf_t /data/samba/git/samba4.1/st/promoted_dc/private/dns.keytab
+chcon -t named_conf_t /data/samba/git/samba4.1/st/promoted_dc/bind-dns/dns.keytab
workgroup = SAMBADOMAIN
realm = SAMBA.EXAMPLE.COM
private dir = @@PREFIX@@/private
+ binddns dir = @@PREFIX@@/bind-dns
lock dir = @@PREFIX@@/
posix:eadb = @@PREFIX@@/private/eadb.tdb
elif self.getvar('NAMESERVER_BACKEND') != 'SAMBA_INTERNAL':
if self.named_supports_gssapi_keytab():
self.setvar("NAMED_TKEY_OPTION",
- 'tkey-gssapi-keytab "${PREFIX}/private/dns.keytab";')
+ 'tkey-gssapi-keytab "${PREFIX}/bind-dns/dns.keytab";')
else:
self.info("LCREALM=${LCREALM}")
self.setvar("NAMED_TKEY_OPTION",
'''tkey-gssapi-credential "DNS/${LCREALM}";
tkey-domain "${LCREALM}";
''')
- self.putenv('KEYTAB_FILE', '${PREFIX}/private/dns.keytab')
- self.putenv('KRB5_KTNAME', '${PREFIX}/private/dns.keytab')
+ self.putenv('KEYTAB_FILE', '${PREFIX}/bind-dns/dns.keytab')
+ self.putenv('KRB5_KTNAME', '${PREFIX}/bind-dns/dns.keytab')
else:
self.setvar("NAMED_TKEY_OPTION", "")