From ec58278fa7fc6d0b5ae8340c4054005a7864086f Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 26 Mar 2019 13:10:23 +0100 Subject: [PATCH] Don't allow to hide last server for a role DNSSec key master and CA renewal master can't be hidden. There must be at least one enabled server available for each role, too. Fixes: https://pagure.io/freeipa/issue/7892 Signed-off-by: Christian Heimes Reviewed-By: Thomas Woerner Reviewed-By: Francois Cami --- ipaserver/plugins/server.py | 30 ++++++++++++++++++ .../test_replica_promotion.py | 31 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/ipaserver/plugins/server.py b/ipaserver/plugins/server.py index 0d144d13bca66b65de64328139fd7126eea24c89..bfd1406ff826aea97195aa08ca35018e35cac18c 100644 --- a/ipaserver/plugins/server.py +++ b/ipaserver/plugins/server.py @@ -970,6 +970,35 @@ class server_state(crud.PKQuery): has_output = output.standard_boolean + def _check_hide_server(self, fqdn): + result = self.api.Command.config_show()['result'] + err = [] + # single value entries + if result.get("ca_renewal_master_server") == fqdn: + err.append(_("Cannot hide CA renewal master.")) + if result.get("dnssec_key_master_server") == fqdn: + err.append(_("Cannot hide DNSSec key master.")) + # multi value entries, only fail if we are the last one + checks = [ + ("ca_server_server", "CA"), + ("dns_server_server", "DNS"), + ("ipa_master_server", "IPA"), + ("kra_server_server", "KRA"), + ] + for key, name in checks: + values = result.get(key, []) + if values == [fqdn]: # fqdn is the only entry + err.append( + _("Cannot hide last enabled %(name)s server.") % { + 'name': name + } + ) + if err: + raise errors.ValidationError( + name=fqdn, + error=' '.join(str(e) for e in err) + ) + def execute(self, *keys, **options): fqdn = keys[0] if options['state'] == u'enabled': @@ -992,6 +1021,7 @@ class server_state(crud.PKQuery): if to_status == ENABLED: enable_services(fqdn) else: + self._check_hide_server(fqdn) hide_services(fqdn) # update system roles diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py index 9ce0074ea0df276b4800b306530d04c8274ece69..bf028bf7dc58abb6455ba1659f2d19bede69daa2 100644 --- a/ipatests/test_integration/test_replica_promotion.py +++ b/ipatests/test_integration/test_replica_promotion.py @@ -812,7 +812,15 @@ class TestHiddenReplicaPromotion(IntegrationTest): @classmethod def install(cls, mh): + # master with DNSSEC master tasks.install_master(cls.master, setup_dns=True, setup_kra=True) + cls.master.run_command([ + "ipa-dns-install", + "--dnssec-master", + "--forwarder", cls.master.config.dns_forwarder, + "-U", + ]) + # hidden replica with CA and DNS tasks.install_replica( cls.master, cls.replicas[0], setup_dns=True, setup_kra=True, @@ -879,6 +887,29 @@ class TestHiddenReplicaPromotion(IntegrationTest): self._check_dnsrecords([self.master], [self.replicas[0]]) self._check_config([self.master], [self.replicas[0]]) + def test_hide_master_fails(self): + # verify state + self._check_config([self.master], [self.replicas[0]]) + # nothing to do + result = self.master.run_command([ + 'ipa', 'server-state', + self.master.hostname, '--state=enabled' + ], raiseonerr=False) + assert result.returncode == 1 + assert "no modifications to be performed" in result.stderr_text + # hiding the last master fails + result = self.master.run_command([ + 'ipa', 'server-state', + self.master.hostname, '--state=hidden' + ], raiseonerr=False) + assert result.returncode == 1 + keys = [ + "CA renewal master", "DNSSec key master", "CA server", + "KRA server", "DNS server", "IPA server" + ] + for key in keys: + assert key in result.stderr_text + def test_hidden_replica_promote(self): self.replicas[0].run_command([ 'ipa', 'server-state', -- 2.20.1