diff options
-rw-r--r-- | install/share/default-aci.ldif | 2 | ||||
-rwxr-xr-x | install/tools/ipa-replica-install | 6 | ||||
-rwxr-xr-x | install/tools/ipa-server-install | 8 | ||||
-rw-r--r-- | ipaserver/install/bindinstance.py | 12 | ||||
-rw-r--r-- | ipaserver/install/cainstance.py | 4 | ||||
-rw-r--r-- | ipaserver/install/certs.py | 12 | ||||
-rw-r--r-- | ipaserver/install/dsinstance.py | 9 | ||||
-rw-r--r-- | ipaserver/install/httpinstance.py | 16 | ||||
-rw-r--r-- | ipaserver/install/krbinstance.py | 38 | ||||
-rw-r--r-- | ipaserver/install/ldapupdate.py | 3 | ||||
-rw-r--r-- | ipaserver/install/service.py | 60 |
11 files changed, 146 insertions, 24 deletions
diff --git a/install/share/default-aci.ldif b/install/share/default-aci.ldif index 7f08518b..784377e9 100644 --- a/install/share/default-aci.ldif +++ b/install/share/default-aci.ldif @@ -8,7 +8,7 @@ aci: (targetattr != "userPassword || krbPrincipalKey || sambaLMPassword || samba aci: (targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword")(version 3.0; acl "Self can write own password"; allow (write) userdn="ldap:///self";) aci: (targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Admins can write passwords"; allow (add,delete,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) aci: (targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Password change service can read/write passwords"; allow (read, write) userdn="ldap:///krbprincipalname=kadmin/changepw@$REALM,cn=$REALM,cn=kerberos,$SUFFIX";) -aci: (targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "KDC System Account can access passwords"; allow (all) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) +aci: (targetattr = "userPassword || krbPrincipalKey || krbPasswordExpiration || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "KDC System Account can access passwords"; allow (all) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) aci: (targetattr = "krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount")(version 3.0; acl "KDC System Account can update some fields"; allow (write) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) aci: (targetattr = "krbPrincipalName || krbUPEnabled || krbMKey || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData || krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount")(version 3.0; acl "Only the KDC System Account has access to kerberos material"; allow (read, search, compare) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) aci: (targetfilter = "(|(objectClass=person)(objectClass=krbPrincipalAux)(objectClass=posixAccount)(objectClass=groupOfNames)(objectClass=posixGroup))")(targetattr != "aci || userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "Account Admins can manage Users and Groups"; allow (add, delete, read, write) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 33d3726c..76695786 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -200,7 +200,7 @@ def install_http(config): config.dir + "/http_pin.txt") http = httpinstance.HTTPInstance() - http.create_instance(config.realm_name, config.host_name, config.domain_name, False, pkcs12_info, self_signed_ca=True) + http.create_instance(config.realm_name, config.host_name, config.domain_name, config.dirman_password, False, pkcs12_info, self_signed_ca=True) # Now copy the autoconfiguration files if ipautil.file_exists(config.dir + "/preferences.html"): @@ -347,6 +347,10 @@ def main(): CA.fix_ra_perms() service.restart("httpd") + # The DS instance is created before the keytab, add the SSL cert we + # generated + ds.add_cert_to_service() + # Create the management framework config file fd = open("/etc/ipa/default.conf", "w") fd.write("[global]\n") diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 0694d6ed..c92989a4 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -729,6 +729,10 @@ def main(): krb = krbinstance.KrbInstance(fstore) krb.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, master_password) + # The DS instance is created before the keytab, add the SSL cert we + # generated + ds.add_cert_to_service() + # Render webui assets: ipautil.run(["/sbin/restorecon", ASSETS_DIR]) render_assets() @@ -743,10 +747,10 @@ def main(): http = httpinstance.HTTPInstance(fstore) if options.http_pkcs12: pkcs12_info = (options.http_pkcs12, pw_name) - http.create_instance(realm_name, host_name, domain_name, autoconfig=False, pkcs12_info=pkcs12_info) + http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=False, pkcs12_info=pkcs12_info) os.remove(pw_name) else: - http.create_instance(realm_name, host_name, domain_name, autoconfig=True, self_signed_ca=not options.ca) + http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=True, self_signed_ca=not options.ca) ipautil.run(["/sbin/restorecon", "/var/cache/ipa/sessions"]) # Create the management framework config file diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index e2edcd39..9150c8ed 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 198b0c64..46a337cb 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 c4923a75..a1dffff2 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 c25b9753..33ff053c 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 94e155bf..ee62f81f 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 a33ab233..c4a20b54 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 c90f153d..ad2067c0 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 75868898..5e2eb63d 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 |