diff options
-rwxr-xr-x | install/tools/ipa-replica-manage | 22 | ||||
-rw-r--r-- | install/updates/40-delegation.update | 37 | ||||
-rw-r--r-- | ipaserver/install/dsinstance.py | 2 | ||||
-rw-r--r-- | ipaserver/install/replication.py | 20 |
4 files changed, 76 insertions, 5 deletions
diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage index 20d261c8f..b85c491e5 100755 --- a/install/tools/ipa-replica-manage +++ b/install/tools/ipa-replica-manage @@ -27,6 +27,7 @@ from ipaserver.install import replication, dsinstance, installutils from ipaserver import ipaldap from ipapython import version from ipalib import util +from ipalib import errors def parse_options(): from optparse import OptionParser @@ -102,12 +103,15 @@ def del_master(replman, hostname, force=False): try: t = replman.get_agreement_type(hostname) except ldap.NO_SUCH_OBJECT: - print "No replication agreement found for %s" % hostname + print "No replication agreement found for '%s'" % hostname + return + except errors.NotFound: + print "No replication agreement found for '%s'" % hostname + return if t == replication.IPA_REPLICA: - dirman_passwd = getpass.getpass("Directory Manager password (%s): " % hostname) try: - other_replman = replication.ReplicationManager(hostname, dirman_passwd) + other_replman = replication.ReplicationManager(hostname, dirman_passwd=None) other_replman.suffix = get_suffix() other_replman.delete_agreement(replman.conn.host) except Exception, e: @@ -179,10 +183,13 @@ def synch_master(replman, hostname): def main(): options, args = parse_options() + dirman_passwd = None + if options.dirman_passwd: dirman_passwd = options.dirman_passwd else: - dirman_passwd = getpass.getpass("Directory Manager password: ") + if args[0] in ["add", "init"]: + dirman_passwd = getpass.getpass("Directory Manager password: ") if options.host: host = options.host @@ -227,5 +234,12 @@ except SystemExit, e: except ldap.INVALID_CREDENTIALS: print "Invalid password" sys.exit(1) +except ldap.INSUFFICIENT_ACCESS: + print "Insufficient access" + sys.exit(1) +except ldap.LOCAL_ERROR, e: + print e.args[0]['info'] + sys.exit(1) except Exception, e: print "unexpected error: %s" % str(e) + sys.exit(1) diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update index 1be178933..77dca721d 100644 --- a/install/updates/40-delegation.update +++ b/install/updates/40-delegation.update @@ -72,6 +72,13 @@ add:objectClass: nestedgroup add:cn: certadmin add:description: Certificate Administrators +dn: cn=replicaadmin,cn=rolegroups,cn=accounts,$SUFFIX +add:objectClass: top +add:objectClass: nestedgroup +add:cn: replicaadmin +add:description: Replication Administrators +add:member:'uid=admin,cn=users,cn=accounts,$SUFFIX' + # Add the taskgroups referenced by the ACIs for user administration dn: cn=taskgroups,cn=accounts,$SUFFIX @@ -648,3 +655,33 @@ add: aci: '(targetattr = "objectClass")(target = $SUFFIX" )(version 3.0 ; acl "Certificate Remove Hold" ; allow (write) groupdn = "ldap:///cn=certificate_remove_hold, cn=taskgroups,cn=accounts,$SUFFIX";)' + +# Taskgroup for managing replicas +dn: cn=managereplica,cn=taskgroups,cn=accounts,$SUFFIX +add:objectClass: top +add:objectClass: nestedgroup +add:cn: managereplica +add:description: Manage Replication Agreements +add:member:'cn=replicaadmin,cn=rolegroups,cn=accounts,$SUFFIX' + +# Taskgroup for deleting replicas +dn: cn=deletereplica,cn=taskgroups,cn=accounts,$SUFFIX +add:objectClass: top +add:objectClass: nestedgroup +add:cn: deletereplica +add:description: Delete Replication Agreements +add:member:'cn=replicaadmin,cn=rolegroups,cn=accounts,$SUFFIX' + +# Add acis allowing admins to read/write/delete replicas +dn: cn="$SUFFIX",cn=mapping tree,cn=config +add: aci: '(targetattr=*)(targetfilter="(|(objectclass=nsds5Replica) + (objectclass=nsds5replicationagreement)(objectclass= + nsDSWindowsReplicationAgreement))")(version 3.0; acl "Manage + replication agreements"; allow (read, write, search) groupdn = + "ldap:///cn=managereplica,cn=taskgroups,cn=accounts,$SUFFIX";)' + +dn: cn="$SUFFIX",cn=mapping tree,cn=config +add: aci: '(targetattr=*)(targetfilter="(|(objectclass= + nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement + ))")(version 3.0;acl "Delete replication agreements";allow (delete) + groupdn = "ldap:///cn=deletereplica,cn=taskgroups,cn=accounts,$SUFFIX";)' diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 9a71b7f56..f535b7ba8 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -148,6 +148,8 @@ class DsInstance(service.Service): self.pkcs12_info = None self.ds_user = None self.dercert = None + self.uidstart = 1100 + self.gidstart = 1100 if realm_name: self.suffix = util.realm_to_suffix(self.realm_name) self.__setup_sub_dict() diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index 242352975..a09fb3058 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -38,6 +38,8 @@ TIMEOUT = 120 IPA_REPLICA = 1 WINSYNC = 2 +SASL_AUTH = ldap.sasl.sasl({}, 'GSSAPI') + class ReplicationManager: """Manage replication agreements between DS servers, and sync agreements with Windows servers""" @@ -45,8 +47,13 @@ class ReplicationManager: self.hostname = hostname self.dirman_passwd = dirman_passwd + # If we are passed a password we'll use it as the DM password + # otherwise we'll do a GSSAPI bind. self.conn = ipaldap.IPAdmin(hostname, port=PORT, cacert=CACERT) - self.conn.do_simple_bind(bindpw=dirman_passwd) + if dirman_passwd: + self.conn.do_simple_bind(bindpw=dirman_passwd) + else: + self.conn.sasl_interactive_bind_s('', SASL_AUTH) self.repl_man_passwd = dirman_passwd @@ -98,6 +105,16 @@ class ReplicationManager: return retval def find_replication_dns(self, conn): + """ + The replication agreements are stored in + cn="$SUFFIX",cn=mapping tree,cn=config + + FIXME: Rather than failing with a read error if a user tries + to read this it simply returns zero entries. We need to use + GER to determine if we are allowed to read this to return a proper + response. For now just return "No entries" even if the user may + not be allowed to see them. + """ filt = "(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement))" try: ents = conn.search_s("cn=mapping tree,cn=config", ldap.SCOPE_SUBTREE, filt) @@ -465,6 +482,7 @@ class ReplicationManager: # allow connections using two different CA certs other_conn = ipaldap.IPAdmin(other_hostname, port=oth_port, cacert=oth_cacert) try: + # For now we always require a password to set up new replica other_conn.do_simple_bind(binddn=oth_binddn, bindpw=oth_bindpw) except Exception, e: if iswinsync: |