summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/replication.py
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-06-11 15:45:38 -0400
committerSimo Sorce <simo@redhat.com>2015-10-01 16:20:48 -0400
commit70bd0ec94c87069b0f4d8777332ac62bbd541ab6 (patch)
treee2ff5901c1cef8b583aec008d0d83ff64ad4f582 /ipaserver/install/replication.py
parent4622d20742d60bf57d5fda6effa534c2ed2a48d8 (diff)
downloadfreeipa-70bd0ec94c87069b0f4d8777332ac62bbd541ab6.tar.gz
freeipa-70bd0ec94c87069b0f4d8777332ac62bbd541ab6.tar.xz
freeipa-70bd0ec94c87069b0f4d8777332ac62bbd541ab6.zip
Implement replica promotion functionality
This patch implements a new flag --promote for the ipa-replica-install command that allows an administrative user to 'promote' an already joined client to become a full ipa server. The only credentials used are that of an administrator. This code relies on ipa-custodia being available on the peer master as well as a number of other patches to allow a computer account to request certificates for its services. Therefore this feature is marked to work only with domain level 1 and above servers. Ticket: https://fedorahosted.org/freeipa/ticket/2888 Signed-off-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'ipaserver/install/replication.py')
-rw-r--r--ipaserver/install/replication.py90
1 files changed, 90 insertions, 0 deletions
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index b50dc0584..858e3f36b 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -1605,6 +1605,96 @@ class ReplicationManager(object):
except errors.EmptyModlist:
pass
+ def join_replication_managers(self, conn):
+ """
+ Create a pseudo user to use for replication.
+ """
+ dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'),
+ ('cn', 'etc'), self.suffix)
+ mydn = DN(('krbprincipalname', 'ldap/%s@%s' % (self.hostname,
+ self.realm)),
+ ('cn', 'services'), ('cn', 'accounts'), self.suffix)
+
+ entry = conn.get_entry(dn)
+ if mydn not in entry['member']:
+ entry['member'].append(mydn)
+
+ try:
+ conn.update_entry(entry)
+ except errors.EmptyModlist:
+ pass
+
+ def add_temp_sasl_mapping(self, conn, r_hostname):
+ """
+ Create a special user to let SASL Mapping find a valid user
+ on first replication.
+ """
+ name = 'ldap/%s@%s' % (r_hostname, self.realm)
+ replica_binddn = DN(('cn', name), ('cn', 'config'))
+ entry = conn.make_entry(
+ replica_binddn,
+ objectclass=["top", "person"],
+ cn=[name],
+ sn=["replication manager pseudo user"]
+ )
+ conn.add_entry(entry)
+
+ entry = conn.get_entry(self.replica_dn())
+ entry['nsDS5ReplicaBindDN'].append(replica_binddn)
+ conn.update_entry(entry)
+
+ entry = conn.make_entry(
+ DN(('cn', 'Peer Master'), ('cn', 'mapping'), ('cn', 'sasl'),
+ ('cn', 'config')),
+ objectclass=["top", "nsSaslMapping"],
+ cn=["Peer Master"],
+ nsSaslMapRegexString=['^[^:@]+$'],
+ nsSaslMapBaseDNTemplate=[DN(('cn', 'config'))],
+ nsSaslMapFilterTemplate=['(cn=&@%s)' % self.realm],
+ nsSaslMapPriority=['1'],
+ )
+ conn.add_entry(entry)
+
+ def remove_temp_replication_user(self, conn, r_hostname):
+ """
+ Remove the special SASL Mapping user created in a previous step.
+ """
+ name = 'ldap/%s@%s' % (r_hostname, self.realm)
+ replica_binddn = DN(('cn', name), ('cn', 'config'))
+ conn.delete_entry(replica_binddn)
+
+ entry = conn.get_entry(self.replica_dn())
+ while replica_binddn in entry['nsDS5ReplicaBindDN']:
+ entry['nsDS5ReplicaBindDN'].remove(replica_binddn)
+ conn.update_entry(entry)
+
+ def setup_promote_replication(self, r_hostname):
+ # note - there appears to be a bug in python-ldap - it does not
+ # allow connections using two different CA certs
+ r_conn = ipaldap.IPAdmin(r_hostname, port=389, protocol='ldap')
+ r_conn.do_sasl_gssapi_bind()
+
+ # Setup the first half
+ l_id = self._get_replica_id(self.conn, r_conn)
+ self.basic_replication_setup(self.conn, l_id, self.repl_man_dn, None)
+ self.add_temp_sasl_mapping(self.conn, r_hostname)
+
+ # Now setup the other half
+ r_id = self._get_replica_id(r_conn, r_conn)
+ self.basic_replication_setup(r_conn, r_id, self.repl_man_dn, None)
+ self.join_replication_managers(r_conn)
+
+ self.setup_agreement(r_conn, self.conn.host, isgssapi=True)
+ self.setup_agreement(self.conn, r_hostname, isgssapi=True)
+
+ # Finally start replication
+ ret = self.start_replication(r_conn, master=False)
+ if ret != 0:
+ raise RuntimeError("Failed to start replication")
+
+ self.remove_temp_replication_user(self.conn, r_hostname)
+
+
class CSReplicationManager(ReplicationManager):
"""ReplicationManager specific to CA agreements