bb0ded
From edb216849e4f47d6cae95981edf0c3fe2653fd7a Mon Sep 17 00:00:00 2001
bb0ded
From: Rob Crittenden <rcritten@redhat.com>
bb0ded
Date: Fri, 28 Jan 2022 16:46:35 -0500
bb0ded
Subject: [PATCH] Don't always override the port in import_included_profiles
bb0ded
bb0ded
I can only guess to the original purpose of this override. I
bb0ded
believe it was because this is called in the installer prior
bb0ded
to Apache being set up. The expectation was that this would
bb0ded
only be called locally. It predates the RestClient class.
bb0ded
bb0ded
RestClient will attempt to find an available service. In this
bb0ded
case, during a CA installation, the local server is not
bb0ded
considered available because it lacks an entry in
bb0ded
cn=masters. So it will never be returned as an option.
bb0ded
bb0ded
So by overriding the port to 8443 the remote connection will
bb0ded
likely fail because we don't require that the port be open.
bb0ded
bb0ded
So instead, instantiate a RestClient and see what happens.
bb0ded
bb0ded
There are several use-cases:
bb0ded
bb0ded
1. Installing an initial server. The RestClient connection
bb0ded
   should fail, so we will fall back to the override port and
bb0ded
   use the local server. If Apache happens to be running with
bb0ded
   a globally-issued certificate then the RestClient will
bb0ded
   succeed. In this case if the connected host and the local
bb0ded
   hostname are the same, override in that case as well.
bb0ded
bb0ded
2. Installing as a replica. In this case the local server should
bb0ded
   be ignored in all cases and a remote CA will be picked with
bb0ded
   no override done.
bb0ded
bb0ded
3. Switching from CA-less to CA-ful. The web server will be
bb0ded
   trusted but the RestClient login will fail with a 404. Fall
bb0ded
   back to the override port in this case.
bb0ded
bb0ded
The motivation for this is trying to install an EL 8.x replica
bb0ded
against an EL 7.9 server. 8.5+ includes the ACME service and
bb0ded
a new profile is needed which doesn't exist in 7. This was
bb0ded
failing because the RestClient determined that the local server
bb0ded
wasn't running a CA so tried the remote one (7.9) on the override
bb0ded
port 8443. Since this port isn't open: failure.
bb0ded
bb0ded
Chances are that adding the profile is still going to fail
bb0ded
because again, 7.9 lacks ACME capabilities, but it will fail in
bb0ded
a way that allows the installation to continue.
bb0ded
bb0ded
I suspect that all of the overrides can similarly handled, or
bb0ded
handled directly within the RestClient class, but for the sake
bb0ded
of "do no harm" I'm only changing this instance for now.
bb0ded
bb0ded
https://pagure.io/freeipa/issue/9100
bb0ded
bb0ded
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
bb0ded
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
bb0ded
---
bb0ded
 ipaserver/install/cainstance.py | 30 +++++++++++++++++++++++++++++-
bb0ded
 1 file changed, 29 insertions(+), 1 deletion(-)
bb0ded
bb0ded
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
bb0ded
index 8c8bf1b3a7bcf8a9c50183579b874a5710a32ac3..ad206aad411b42336e86e0b651a948fccd3a75ac 100644
bb0ded
--- a/ipaserver/install/cainstance.py
bb0ded
+++ b/ipaserver/install/cainstance.py
bb0ded
@@ -1953,7 +1953,35 @@ def import_included_profiles():
bb0ded
         cn=['certprofiles'],
bb0ded
     )
bb0ded
 
bb0ded
-    api.Backend.ra_certprofile.override_port = 8443
bb0ded
+    # At this point Apache may or may not be running with a valid
bb0ded
+    # certificate. The local server is not yet recognized as a full
bb0ded
+    # CA yet so it isn't discoverable. So try to do some detection
bb0ded
+    # on what port to use, 443 (remote) or 8443 (local) for importing
bb0ded
+    # the profiles.
bb0ded
+    #
bb0ded
+    # api.Backend.ra_certprofile invokes the RestClient class
bb0ded
+    # which will discover and login to the CA REST API. We can
bb0ded
+    # use this information to detect where to import the profiles.
bb0ded
+    #
bb0ded
+    # If the login is successful (e.g. doesn't raise an exception)
bb0ded
+    # and it returns our hostname (it prefers the local host) then
bb0ded
+    # we override and talk locally.
bb0ded
+    #
bb0ded
+    # Otherwise a NetworkError means we can't connect on 443 (perhaps
bb0ded
+    # a firewall) or we get an HTTP error (valid TLS certificate on
bb0ded
+    # Apache but no CA, login fails with 404) so we override to the
bb0ded
+    # local server.
bb0ded
+    #
bb0ded
+    # When override port was always set to 8443 the RestClient could
bb0ded
+    # pick a remote server and since 8443 isn't in our firewall profile
bb0ded
+    # setting up a new server would fail.
bb0ded
+    try:
bb0ded
+        with api.Backend.ra_certprofile as profile_api:
bb0ded
+            if profile_api.ca_host == api.env.host:
bb0ded
+                api.Backend.ra_certprofile.override_port = 8443
bb0ded
+    except (errors.NetworkError, errors.RemoteRetrieveError) as e:
bb0ded
+        logger.debug('Overriding CA port: %s', e)
bb0ded
+        api.Backend.ra_certprofile.override_port = 8443
bb0ded
 
bb0ded
     for (profile_id, desc, store_issued) in dogtag.INCLUDED_PROFILES:
bb0ded
         dn = DN(('cn', profile_id),
bb0ded
-- 
bb0ded
2.34.1
bb0ded