summaryrefslogtreecommitdiffstats
path: root/ipaserver/install
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-12-07 23:17:00 -0500
committerJason Gerard DeRose <jderose@redhat.com>2009-12-11 23:06:08 -0700
commit766b534da0c3a1ed09fe187323eaae0440eb7784 (patch)
tree8eebfdf577f4d64da9fbaa2fea3d5c955514bca7 /ipaserver/install
parent7105a0c0d62583384c6a2d20bc508e35bd227347 (diff)
downloadfreeipa-766b534da0c3a1ed09fe187323eaae0440eb7784.tar.gz
freeipa-766b534da0c3a1ed09fe187323eaae0440eb7784.tar.xz
freeipa-766b534da0c3a1ed09fe187323eaae0440eb7784.zip
Make the IPA server host and its services "real" IPA entries
We use kadmin.local to bootstrap the creation of the kerberos principals for the IPA server machine: host, HTTP and ldap. This works fine and has the side-effect of protecting the services from modification by an admin (which would likely break the server). Unfortunately this also means that the services can't be managed by useful utilities such as certmonger. So we have to create them as "real" services instead.
Diffstat (limited to 'ipaserver/install')
-rw-r--r--ipaserver/install/bindinstance.py12
-rw-r--r--ipaserver/install/cainstance.py4
-rw-r--r--ipaserver/install/certs.py12
-rw-r--r--ipaserver/install/dsinstance.py9
-rw-r--r--ipaserver/install/httpinstance.py16
-rw-r--r--ipaserver/install/krbinstance.py38
-rw-r--r--ipaserver/install/ldapupdate.py3
-rw-r--r--ipaserver/install/service.py60
8 files changed, 134 insertions, 20 deletions
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index e2edcd392..9150c8edf 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -201,6 +201,7 @@ class BindInstance(service.Service):
# Store the keytab on disk
self.fstore.backup_file("/etc/named.keytab")
installutils.create_keytab("/etc/named.keytab", dns_principal)
+ dns_principal = self.move_service(dns_principal)
# Make sure access is strictly reserved to the named user
pent = pwd.getpwnam(self.named_user)
@@ -220,17 +221,8 @@ class BindInstance(service.Service):
logging.critical("Could not connect to the Directory Server on %s" % self.fqdn)
raise e
- dns_princ_dn = "krbprincipalname=%s,cn=%s,cn=kerberos,%s" % (dns_principal, self.realm, self.suffix)
- mod = [(ldap.MOD_ADD, 'objectClass', 'ipaService')]
-
- try:
- conn.modify_s(dns_princ_dn, mod)
- except Exception, e:
- logging.critical("Could not modify principal's %s entry" % dns_principal)
- raise e
-
dns_group = "cn=dnsserver,cn=rolegroups,cn=accounts,%s" % self.suffix
- mod = [(ldap.MOD_ADD, 'member', dns_princ_dn)]
+ mod = [(ldap.MOD_ADD, 'member', dns_principal)]
try:
conn.modify_s(dns_group, mod)
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 198b0c644..46a337cb0 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -810,7 +810,7 @@ class CAInstance(service.Service):
os.close(f)
os.chmod(self.ra_agent_pwd, stat.S_IRUSR)
- stdout, stderr = self.__run_certutil(["-N"])
+ (stdout, stderr, returncode) = self.__run_certutil(["-N"])
def __get_ca_chain(self):
try:
@@ -886,7 +886,7 @@ class CAInstance(service.Service):
# Generate our CSR. The result gets put into stdout
try:
- (stdout, stderr) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", "CN=RA Subsystem Certificate,OU=pki-ipa,O=%s" % self.domain_name, "-z", noise_name, "-a"])
+ (stdout, stderr, returncode) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", "CN=RA Subsystem Certificate,OU=pki-ipa,O=%s" % self.domain_name, "-z", noise_name, "-a"])
finally:
os.remove(noise_name)
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index c4923a751..a1dffff24 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -26,6 +26,7 @@ import urllib
import xml.dom.minidom
import pwd
import fcntl
+import base64
from ipapython import nsslib
from ipapython import sysrestore
@@ -459,9 +460,20 @@ class CertDB(object):
(out, err) = self.request_cert(subject)
cdb.issue_server_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
+ fd = open(self.certder_fname, "r")
+ dercert = fd.read()
+ fd.close()
+
os.unlink(self.certreq_fname)
os.unlink(self.certder_fname)
+ # On the off-chance the certificate is base64-encoded
+ try:
+ dercert = base64.b64decode(dercert)
+ except:
+ pass
+ return dercert
+
def create_signing_cert(self, nickname, hostname, other_certdb=None, subject=None):
cdb = other_certdb
if not cdb:
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index c25b97538..33ff053c3 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -146,6 +146,7 @@ class DsInstance(service.Service):
self.host_name = None
self.pkcs12_info = None
self.ds_user = None
+ self.dercert = None
if realm_name:
self.suffix = util.realm_to_suffix(self.realm_name)
self.__setup_sub_dict()
@@ -164,6 +165,7 @@ class DsInstance(service.Service):
self.self_signed_ca = self_signed_ca
self.uidstart = uidstart
self.gidstart = gidstart
+ self.principal = "ldap/%s@%s" % (self.host_name, self.realm_name)
self.__setup_sub_dict()
self.step("creating directory server user", self.__create_ds_user)
@@ -203,7 +205,7 @@ class DsInstance(service.Service):
REALM=self.realm_name, USER=self.ds_user,
SERVER_ROOT=server_root, DOMAIN=self.domain,
TIME=int(time.time()), UIDSTART=self.uidstart,
- GIDSTART=self.gidstart)
+ GIDSTART=self.gidstart, HOST=self.host_name)
def __create_ds_user(self):
user_exists = True
@@ -335,19 +337,20 @@ class DsInstance(service.Service):
# We only handle one server cert
nickname = server_certs[0][0]
+ self.dercert = dsdb.get_cert_from_db(nickname)
else:
nickname = "Server-Cert"
cadb = certs.CertDB(httpinstance.NSS_DIR, host_name=self.host_name)
if self.self_signed_ca:
cadb.create_self_signed()
dsdb.create_from_cacert(cadb.cacert_fname, passwd=None)
- dsdb.create_server_cert("Server-Cert", self.host_name, cadb)
+ self.dercert = dsdb.create_server_cert("Server-Cert", self.host_name, cadb)
dsdb.create_pin_file()
else:
# FIXME, need to set this nickname in the RA plugin
cadb.export_ca_cert('ipaCert', False)
dsdb.create_from_cacert(cadb.cacert_fname, passwd=None)
- dsdb.create_server_cert("Server-Cert", self.host_name, cadb)
+ self.dercert = dsdb.create_server_cert("Server-Cert", self.host_name, cadb)
dsdb.create_pin_file()
conn = ipaldap.IPAdmin("127.0.0.1")
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 94e155bf0..ee62f81f2 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -30,6 +30,7 @@ import dsinstance
import installutils
from ipapython import sysrestore
from ipapython import ipautil
+from ipalib import util
HTTPD_DIR = "/etc/httpd"
SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf"
@@ -55,12 +56,16 @@ class HTTPInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
- def create_instance(self, realm, fqdn, domain_name, autoconfig=True, pkcs12_info=None, self_signed_ca=False):
+ def create_instance(self, realm, fqdn, domain_name, dm_password=None, autoconfig=True, pkcs12_info=None, self_signed_ca=False):
self.fqdn = fqdn
self.realm = realm
self.domain = domain_name
+ self.dm_password = dm_password
+ self.suffix = util.realm_to_suffix(self.realm)
self.pkcs12_info = pkcs12_info
self.self_signed_ca = self_signed_ca
+ self.principal = "HTTP/%s@%s" % (self.fqdn, self.realm)
+ self.dercert = None
self.sub_dict = { "REALM" : realm, "FQDN": fqdn, "DOMAIN" : self.domain }
self.step("disabling mod_ssl in httpd", self.__disable_mod_ssl)
@@ -68,11 +73,11 @@ class HTTPInstance(service.Service):
self.step("Setting mod_nss password file", self.__set_mod_nss_passwordfile)
self.step("Adding URL rewriting rules", self.__add_include)
self.step("configuring httpd", self.__configure_http)
- self.step("creating a keytab for httpd", self.__create_http_keytab)
self.step("Setting up ssl", self.__setup_ssl)
if autoconfig:
self.step("Setting up browser autoconfig", self.__setup_autoconfig)
self.step("publish CA cert", self.__publish_ca_cert)
+ self.step("creating a keytab for httpd", self.__create_http_keytab)
self.step("configuring SELinux for httpd", self.__selinux_config)
self.step("restarting httpd", self.__start)
self.step("configuring httpd to start on boot", self.__enable)
@@ -117,6 +122,8 @@ class HTTPInstance(service.Service):
http_principal = "HTTP/" + self.fqdn + "@" + self.realm
installutils.kadmin_addprinc(http_principal)
installutils.create_keytab("/etc/httpd/conf/ipa.keytab", http_principal)
+ self.move_service(http_principal)
+ self.add_cert_to_service()
pent = pwd.getpwnam("apache")
os.chown("/etc/httpd/conf/ipa.keytab", pent.pw_uid, pent.pw_gid)
@@ -170,16 +177,17 @@ class HTTPInstance(service.Service):
db.create_password_conf()
# We only handle one server cert
nickname = server_certs[0][0]
+ self.dercert = db.get_cert_from_db(nickname)
self.__set_mod_nss_nickname(nickname)
else:
if self.self_signed_ca:
db.create_from_cacert(ca_db.cacert_fname)
db.create_password_conf()
- db.create_server_cert("Server-Cert", self.fqdn, ca_db)
+ self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
else:
- db.create_server_cert("Server-Cert", self.fqdn, ca_db)
+ self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
db.create_password_conf()
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index a33ab233c..c4a20b545 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -32,6 +32,7 @@ from ipapython import sysrestore
from ipapython import ipautil
from ipalib import util
from ipalib import errors
+from ipalib import uuid
from ipaserver import ipaldap
@@ -91,6 +92,40 @@ class KrbInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+ def move_service_to_host(self, principal):
+ """
+ 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)
+
+ # Create a host entry for this master
+ host_dn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
+ host_entry = ipaldap.Entry(host_dn)
+ host_entry.setValues('objectclass', ['top', 'ipaobject', 'nshost', 'ipahost', 'pkiuser', 'krbprincipalaux', 'krbprincipal', 'krbticketpolicyaux'])
+ host_entry.setValue('krbextradata', service_entry.getValue('krbextradata'))
+ host_entry.setValue('krblastpwdchange', service_entry.getValue('krblastpwdchange'))
+ host_entry.setValue('krbpasswordexpiration', service_entry.getValue('krbpasswordexpiration'))
+ host_entry.setValue('krbprincipalname', service_entry.getValue('krbprincipalname'))
+ host_entry.setValue('krbticketflags', service_entry.getValue('krbticketflags'))
+ host_entry.setValue('krbprincipalkey', service_entry.getValue('krbprincipalkey'))
+ host_entry.setValue('serverhostname', self.fqdn.split('.',1)[0])
+ host_entry.setValue('cn', self.fqdn)
+ host_entry.setValue('fqdn', self.fqdn)
+ host_entry.setValue('ipauniqueid', str(uuid.uuid1()))
+ conn.addEntry(host_entry)
+ conn.unbind()
+
def __common_setup(self, ds_user, realm_name, host_name, domain_name, admin_password):
self.ds_user = ds_user
self.fqdn = host_name
@@ -404,6 +439,7 @@ class KrbInstance(service.Service):
def __create_ds_keytab(self):
ldap_principal = "ldap/" + self.fqdn + "@" + self.realm
installutils.kadmin_addprinc(ldap_principal)
+ self.move_service(ldap_principal)
self.fstore.backup_file("/etc/dirsrv/ds.keytab")
installutils.create_keytab("/etc/dirsrv/ds.keytab", ldap_principal)
@@ -424,6 +460,8 @@ class KrbInstance(service.Service):
os.chown("/etc/krb5.keytab", 0, 0)
os.chmod("/etc/krb5.keytab", 0600)
+ self.move_service_to_host(host_principal)
+
def __export_kadmin_changepw_keytab(self):
installutils.kadmin_modprinc("kadmin/changepw", "+requires_preauth")
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index c90f153db..ad2067c09 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -28,7 +28,7 @@ import sys
from ipaserver.install import installutils
from ipaserver import ipaldap
from ipapython import entity, ipautil
-from ipalib import util
+from ipalib import util, uuid
from ipalib import errors
import ldap
import logging
@@ -124,6 +124,7 @@ class LDAPUpdate:
def _template_str(self, s):
try:
+ self.sub_dict["UUID"] = str(uuid.uuid1())
return ipautil.template_str(s, self.sub_dict)
except KeyError, e:
raise BadSyntax("Unknown template keyword %s" % e)
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 758688982..5e2eb63dc 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -22,6 +22,10 @@ import os
import tempfile
from ipapython import sysrestore
from ipapython import ipautil
+from ipalib import uuid, errors
+import ldap
+from ipaserver import ipaldap
+import base64
def stop(service_name, instance_name=""):
@@ -98,6 +102,7 @@ class Service:
path = ipautil.SHARE_DIR + ldif
if sub_dict is not None:
+ sub_dict['UUID'] = str(uuid.uuid1())
txt = ipautil.template_file(path, sub_dict)
fd = ipautil.write_tmp_file(txt)
path = fd.name
@@ -120,6 +125,61 @@ class Service:
if fd is not None:
fd.close()
+ def move_service(self, principal):
+ """
+ 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)
+ 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)
+ conn.deleteEntry(dn)
+ entry.dn = newdn
+ classes = entry.getValues("objectclass")
+ classes = classes + ["ipaobject", "ipaservice", "pkiuser"]
+ entry.setValues("objectclass", list(set(classes)))
+ entry.setValue("ipauniqueid", str(uuid.uuid1()))
+ conn.addEntry(entry)
+ conn.unbind()
+ return newdn
+
+ def add_cert_to_service(self):
+ """
+ Add a certificate to a service
+
+ This should be passed in DER format but we'll be nice and convert
+ a base64-encoded cert if needed.
+ """
+ try:
+ self.dercert = base64.b64decode(self.dercert)
+ 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)
+ except Exception, e:
+ logging.critical("Could not add certificate to service %s entry: %s" % (self.principal, str(e)))
+ conn.unbind()
+
def set_output(self, fd):
self.output_fd = fd