summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-02-19 13:29:14 -0500
committerRob Crittenden <rcritten@redhat.com>2010-03-19 17:17:14 -0400
commitc19911845d93e4cbbf296caf18568231549a3e60 (patch)
tree7215db333db05cefbe712e63f7c99d651afff908
parent664ae51eb6e76ceb3630687d2ee423f69fb0ba19 (diff)
downloadfreeipa-c19911845d93e4cbbf296caf18568231549a3e60.tar.gz
freeipa-c19911845d93e4cbbf296caf18568231549a3e60.tar.xz
freeipa-c19911845d93e4cbbf296caf18568231549a3e60.zip
Use GSSAPI auth for the ipa-replica-manage list and del commands.
This creates a new role, replicaadmin, so a non-DM user can do limited management of replication agreements. Note that with cn=config if an unauthorized user performs a search an error is not returned, no entries are returned. This makes it difficult to determine if there are simply no replication agreements or we aren't allowed to see them. Once the ipaldap.py module gets replaced by ldap2 we can use Get Effective Rights to easily tell the difference.
-rwxr-xr-xinstall/tools/ipa-replica-manage22
-rw-r--r--install/updates/40-delegation.update37
-rw-r--r--ipaserver/install/dsinstance.py2
-rw-r--r--ipaserver/install/replication.py20
4 files changed, 76 insertions, 5 deletions
diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 20d261c8..b85c491e 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 1be17893..77dca721 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 9a71b7f5..f535b7ba 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 24235297..a09fb305 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: