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