mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Allow ipa-dns-install to install with just admin credentials
Do this by creating a common way to attach to the ldap server for each instance. Fixes: https://fedorahosted.org/freeipa/ticket/686
This commit is contained in:
parent
56f000e9a9
commit
21bf175e0c
@ -28,6 +28,8 @@ from ipapython import version
|
||||
from ipapython import ipautil, sysrestore
|
||||
from ipalib import api, errors, util
|
||||
from ipapython.config import IPAOptionParser
|
||||
import krbV
|
||||
import ldap
|
||||
|
||||
def parse_options():
|
||||
parser = IPAOptionParser(version=version.VERSION)
|
||||
@ -52,8 +54,6 @@ def parse_options():
|
||||
parser.error("You cannot specify a --forwarder option together with --no-forwarders")
|
||||
|
||||
if options.unattended:
|
||||
if not options.dm_password:
|
||||
parser.error("In unattended mode you need to provide at least the -p option")
|
||||
if not options.forwarders and not options.no_forwarders:
|
||||
parser.error("You must specify at least one --forwarder option or --no-forwarders option")
|
||||
|
||||
@ -138,22 +138,6 @@ def main():
|
||||
dns_forwarders = read_dns_forwarders()
|
||||
logging.debug("will use dns_forwarders: %s\n", str(dns_forwarders))
|
||||
|
||||
if not options.dm_password:
|
||||
dm_password = read_password("Directory Manager", confirm=False, validate=False)
|
||||
else:
|
||||
dm_password = options.dm_password
|
||||
|
||||
# Try out the password
|
||||
ldapuri = 'ldap://%s' % api.env.host
|
||||
try:
|
||||
conn = ldap2(shared_instance=False, ldap_uri=ldapuri)
|
||||
conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
|
||||
conn.disconnect()
|
||||
except errors.ACIError:
|
||||
sys.exit("\nThe password provided is incorrect for LDAP server %s" % api.env.host)
|
||||
except errors.LDAPError:
|
||||
sys.exit("\nUnable to connect to LDAP server %s" % api.env.host)
|
||||
|
||||
conf_ntp = ntpinstance.NTPInstance(fstore).is_enabled()
|
||||
|
||||
if not options.unattended:
|
||||
@ -163,12 +147,39 @@ def main():
|
||||
print ""
|
||||
|
||||
# Create a BIND instance
|
||||
bind = bindinstance.BindInstance(fstore, dm_password)
|
||||
bind = bindinstance.BindInstance(fstore, options.dm_password)
|
||||
|
||||
valid_password = False
|
||||
while not valid_password:
|
||||
# try the connection
|
||||
try:
|
||||
bind.ldap_connect()
|
||||
bind.ldap_disconnect()
|
||||
valid_password = True
|
||||
except ldap.LOCAL_ERROR, e:
|
||||
if not bind.dm_password:
|
||||
if options.unattended:
|
||||
sys.exit("\nIn unattended mode you need to provide at least the -p option")
|
||||
else:
|
||||
bind.dm_password = read_password("Directory Manager", confirm=False, validate=False)
|
||||
except ldap.INVALID_CREDENTIALS, e:
|
||||
if options.unattended:
|
||||
sys.exit("\nPassword is not valid!")
|
||||
bind.dm_password = read_password("Directory Manager", confirm=False, validate=False)
|
||||
|
||||
create_reverse = bindinstance.create_reverse(options.unattended)
|
||||
bind.setup(api.env.host, ip_address, api.env.realm, api.env.domain, dns_forwarders, conf_ntp, create_reverse, zonemgr=options.zonemgr)
|
||||
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password)
|
||||
|
||||
if bind.dm_password:
|
||||
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=bind.dm_password)
|
||||
else:
|
||||
# See if our LDAP server is up and we can talk to it over GSSAPI
|
||||
ccache = krbV.default_context().default_ccache().name
|
||||
api.Backend.ldap2.connect(ccache)
|
||||
|
||||
bind.create_instance()
|
||||
|
||||
|
||||
print "=============================================================================="
|
||||
print "Setup complete"
|
||||
print ""
|
||||
|
@ -797,7 +797,6 @@ def main():
|
||||
# generated
|
||||
ds.add_cert_to_service()
|
||||
|
||||
|
||||
# Create a HTTP instance
|
||||
|
||||
if options.http_pin:
|
||||
|
@ -217,7 +217,6 @@ class BindInstance(service.Service):
|
||||
service.Service.__init__(self, "named", dm_password=dm_password)
|
||||
self.dns_backup = DnsBackup(self)
|
||||
self.named_user = None
|
||||
self.fqdn = None
|
||||
self.domain = None
|
||||
self.host = None
|
||||
self.ip_address = None
|
||||
@ -270,6 +269,9 @@ class BindInstance(service.Service):
|
||||
except:
|
||||
pass
|
||||
|
||||
# get a connection to the DS
|
||||
self.ldap_connect()
|
||||
|
||||
if not dns_container_exists(self.fqdn, self.suffix):
|
||||
self.step("adding DNS container", self.__setup_dns_container)
|
||||
if not dns_zone_exists(self.domain):
|
||||
@ -384,30 +386,19 @@ class BindInstance(service.Service):
|
||||
# it can host the memberof attribute, then also add it to the
|
||||
# dnsserver role group, this way the DNS is allowed to perform
|
||||
# DNS Updates
|
||||
conn = None
|
||||
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", self.dm_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
|
||||
raise e
|
||||
|
||||
dns_group = "cn=dnsserver,cn=privileges,cn=pbac,%s" % self.suffix
|
||||
if isinstance(dns_principal, unicode):
|
||||
dns_principal = dns_principal.encode('utf-8')
|
||||
mod = [(ldap.MOD_ADD, 'member', dns_principal)]
|
||||
|
||||
try:
|
||||
conn.modify_s(dns_group, mod)
|
||||
self.admin_conn.modify_s(dns_group, mod)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS:
|
||||
pass
|
||||
except Exception, e:
|
||||
logging.critical("Could not modify principal's %s entry" % dns_principal)
|
||||
raise e
|
||||
|
||||
conn.unbind()
|
||||
|
||||
def __setup_named_conf(self):
|
||||
self.fstore.backup_file('/etc/named.conf')
|
||||
named_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.named.conf.template", self.sub_dict)
|
||||
|
@ -68,6 +68,10 @@ class HTTPInstance(service.Service):
|
||||
self.subject_base = subject_base
|
||||
self.sub_dict = { "REALM" : realm, "FQDN": fqdn, "DOMAIN" : self.domain }
|
||||
|
||||
# get a connection to the DS
|
||||
self.ldap_connect()
|
||||
|
||||
|
||||
self.step("disabling mod_ssl in httpd", self.__disable_mod_ssl)
|
||||
self.step("Setting mod_nss port to 443", self.__set_mod_nss_port)
|
||||
self.step("Setting mod_nss password file", self.__set_mod_nss_passwordfile)
|
||||
|
@ -99,17 +99,10 @@ class KrbInstance(service.Service):
|
||||
Used to move a host/ service principal created by kadmin.local from
|
||||
cn=kerberos to reside under the host entry.
|
||||
"""
|
||||
conn = None
|
||||
|
||||
service_dn = "krbprincipalname=%s,cn=%s,cn=kerberos,%s" % (principal, self.realm, self.suffix)
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", self.admin_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
|
||||
raise e
|
||||
service_entry = conn.getEntry(service_dn, ldap.SCOPE_BASE)
|
||||
conn.deleteEntry(service_dn)
|
||||
service_entry = self.admin_conn.getEntry(service_dn, ldap.SCOPE_BASE)
|
||||
self.admin_conn.deleteEntry(service_dn)
|
||||
|
||||
# Create a host entry for this master
|
||||
host_dn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
|
||||
@ -127,8 +120,7 @@ class KrbInstance(service.Service):
|
||||
host_entry.setValue('fqdn', self.fqdn)
|
||||
host_entry.setValue('ipauniqueid', 'autogenerate')
|
||||
host_entry.setValue('managedby', host_dn)
|
||||
conn.addEntry(host_entry)
|
||||
conn.unbind()
|
||||
self.admin_conn.addEntry(host_entry)
|
||||
|
||||
def __common_setup(self, ds_user, realm_name, host_name, domain_name, admin_password):
|
||||
self.ds_user = ds_user
|
||||
@ -145,12 +137,7 @@ class KrbInstance(service.Service):
|
||||
self.__setup_sub_dict()
|
||||
|
||||
# get a connection to the DS
|
||||
try:
|
||||
self.conn = ipaldap.IPAdmin(self.fqdn)
|
||||
self.conn.do_simple_bind(bindpw=self.admin_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
|
||||
raise e
|
||||
self.ldap_connect()
|
||||
|
||||
self.backup_state("running", self.is_running())
|
||||
try:
|
||||
@ -271,12 +258,12 @@ class KrbInstance(service.Service):
|
||||
# they may conflict.
|
||||
|
||||
try:
|
||||
res = self.conn.search_s("cn=mapping,cn=sasl,cn=config",
|
||||
res = self.admin_conn.search_s("cn=mapping,cn=sasl,cn=config",
|
||||
ldap.SCOPE_ONELEVEL,
|
||||
"(objectclass=nsSaslMapping)")
|
||||
for r in res:
|
||||
try:
|
||||
self.conn.delete_s(r.dn)
|
||||
self.admin_conn.delete_s(r.dn)
|
||||
except LDAPError, e:
|
||||
logging.critical("Error during SASL mapping removal: %s" % str(e))
|
||||
raise e
|
||||
@ -292,7 +279,7 @@ class KrbInstance(service.Service):
|
||||
entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=\\1@\\2)')
|
||||
|
||||
try:
|
||||
self.conn.add_s(entry)
|
||||
self.admin_conn.add_s(entry)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
logging.critical("failed to add Full Principal Sasl mapping")
|
||||
raise e
|
||||
@ -305,7 +292,7 @@ class KrbInstance(service.Service):
|
||||
entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=&@%s)' % self.realm)
|
||||
|
||||
try:
|
||||
self.conn.add_s(entry)
|
||||
self.admin_conn.add_s(entry)
|
||||
except ldap.ALREADY_EXISTS:
|
||||
logging.critical("failed to add Name Only Sasl mapping")
|
||||
raise e
|
||||
@ -383,7 +370,7 @@ class KrbInstance(service.Service):
|
||||
|
||||
def __write_stash_from_ds(self):
|
||||
try:
|
||||
entry = self.conn.getEntry("cn=%s, cn=kerberos, %s" % (self.realm, self.suffix), ldap.SCOPE_SUBTREE)
|
||||
entry = self.admin_conn.getEntry("cn=%s, cn=kerberos, %s" % (self.realm, self.suffix), ldap.SCOPE_SUBTREE)
|
||||
except errors.NotFound, e:
|
||||
logging.critical("Could not find master key in DS")
|
||||
raise e
|
||||
@ -485,7 +472,7 @@ class KrbInstance(service.Service):
|
||||
mod = [(ldap.MOD_ADD, 'aci', ipautil.template_str(KRBMKEY_DENY_ACI, self.sub_dict)),
|
||||
(ldap.MOD_ADD, 'krbMKey', str(asn1key))]
|
||||
try:
|
||||
self.conn.modify_s(dn, mod)
|
||||
self.admin_conn.modify_s(dn, mod)
|
||||
except ldap.TYPE_OR_VALUE_EXISTS, e:
|
||||
logging.critical("failed to add master key to kerberos database\n")
|
||||
raise e
|
||||
@ -553,16 +540,8 @@ class KrbInstance(service.Service):
|
||||
|
||||
# Create the special anonymous principal
|
||||
installutils.kadmin_addprinc(princ_realm)
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", self.admin_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
|
||||
raise e
|
||||
|
||||
dn = "krbprincipalname=%s,cn=%s,cn=kerberos,%s" % (princ_realm, self.realm, self.suffix)
|
||||
conn.inactivateEntry(dn, False)
|
||||
conn.unbind()
|
||||
self.admin_conn.inactivateEntry(dn, False)
|
||||
|
||||
def uninstall(self):
|
||||
if self.is_configured():
|
||||
|
@ -18,7 +18,7 @@
|
||||
#
|
||||
|
||||
import logging, sys
|
||||
import os
|
||||
import os, socket
|
||||
import tempfile
|
||||
from ipapython import sysrestore
|
||||
from ipapython import ipautil
|
||||
@ -30,6 +30,9 @@ import time
|
||||
import datetime
|
||||
from ipaserver.install import installutils
|
||||
|
||||
CACERT = "/etc/ipa/ca.crt"
|
||||
SASL_AUTH = ldap.sasl.sasl({}, 'GSSAPI')
|
||||
|
||||
SERVICE_LIST = {
|
||||
'KDC':('krb5kdc', 10),
|
||||
'KPASSWD':('ipa_kpasswd', 20),
|
||||
@ -100,11 +103,21 @@ class Service:
|
||||
self.output_fd = sys.stdout
|
||||
self.dm_password = dm_password
|
||||
|
||||
self.fqdn = socket.gethostname()
|
||||
self.admin_conn = None
|
||||
|
||||
if sstore:
|
||||
self.sstore = sstore
|
||||
else:
|
||||
self.sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore')
|
||||
|
||||
def ldap_connect(self):
|
||||
self.admin_conn = self.__get_conn(self.fqdn, self.dm_password)
|
||||
|
||||
def ldap_disconnect(self):
|
||||
self.admin_conn.unbind()
|
||||
self.admin_conn = None
|
||||
|
||||
def _ldap_mod(self, ldif, sub_dict = None):
|
||||
|
||||
pw_name = None
|
||||
@ -145,31 +158,24 @@ class Service:
|
||||
Used to move a principal entry created by kadmin.local from
|
||||
cn=kerberos to cn=services
|
||||
"""
|
||||
|
||||
dn = "krbprincipalname=%s,cn=%s,cn=kerberos,%s" % (principal, self.realm, self.suffix)
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", self.dm_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e)))
|
||||
raise e
|
||||
try:
|
||||
entry = conn.getEntry(dn, ldap.SCOPE_BASE)
|
||||
entry = self.admin_conn.getEntry(dn, ldap.SCOPE_BASE)
|
||||
except errors.NotFound:
|
||||
# There is no service in the wrong location, nothing to do.
|
||||
# This can happen when installing a replica
|
||||
conn.unbind()
|
||||
return
|
||||
newdn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (principal, self.suffix)
|
||||
hostdn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
|
||||
conn.deleteEntry(dn)
|
||||
self.admin_conn.deleteEntry(dn)
|
||||
entry.dn = newdn
|
||||
classes = entry.getValues("objectclass")
|
||||
classes = classes + ["ipaobject", "ipaservice", "pkiuser"]
|
||||
entry.setValues("objectclass", list(set(classes)))
|
||||
entry.setValue("ipauniqueid", 'autogenerate')
|
||||
entry.setValue("managedby", hostdn)
|
||||
conn.addEntry(entry)
|
||||
conn.unbind()
|
||||
self.admin_conn.addEntry(entry)
|
||||
return newdn
|
||||
|
||||
def add_cert_to_service(self):
|
||||
@ -180,6 +186,10 @@ class Service:
|
||||
a base64-encoded cert if needed (like when we add certs that come
|
||||
from PKCS#12 files.)
|
||||
"""
|
||||
|
||||
if not self.admin_conn:
|
||||
self.ldap_connect()
|
||||
|
||||
try:
|
||||
s = self.dercert.find('-----BEGIN CERTIFICATE-----')
|
||||
if s > -1:
|
||||
@ -190,18 +200,11 @@ class Service:
|
||||
except Exception:
|
||||
pass
|
||||
dn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (self.principal, self.suffix)
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", self.dm_password)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e)))
|
||||
raise e
|
||||
mod = [(ldap.MOD_ADD, 'userCertificate', self.dercert)]
|
||||
try:
|
||||
conn.modify_s(dn, mod)
|
||||
self.admin_conn.modify_s(dn, mod)
|
||||
except Exception, e:
|
||||
logging.critical("Could not add certificate to service %s entry: %s" % (self.principal, str(e)))
|
||||
conn.unbind()
|
||||
|
||||
def is_configured(self):
|
||||
return self.sstore.has_state(self.service_name)
|
||||
@ -278,11 +281,16 @@ class Service:
|
||||
self.steps = []
|
||||
|
||||
def __get_conn(self, fqdn, dm_password):
|
||||
# If we are passed a password we'll use it as the DM password
|
||||
# otherwise we'll do a GSSAPI bind.
|
||||
try:
|
||||
conn = ipaldap.IPAdmin("127.0.0.1")
|
||||
conn.simple_bind_s("cn=directory manager", dm_password)
|
||||
conn = ipaldap.IPAdmin(fqdn, port=636, cacert=CACERT)
|
||||
if dm_password:
|
||||
conn.do_simple_bind(bindpw=dm_password)
|
||||
else:
|
||||
conn.sasl_interactive_bind_s('', SASL_AUTH)
|
||||
except Exception, e:
|
||||
logging.critical("Could not connect to the Directory Server on %s: %s" % (fqdn, str(e)))
|
||||
logging.debug("Could not connect to the Directory Server on %s: %s" % (fqdn, str(e)))
|
||||
raise e
|
||||
|
||||
return conn
|
||||
|
Loading…
Reference in New Issue
Block a user