URL: https://github.com/freeipa/freeipa/pull/117
Author: stlaz
 Title: #117: Make ipa-replica-install run in interactive mode
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/117/head:pr117
git checkout pr117
From 314bc73b81f7d6bc2f1b8f4a08af8a93e33d4228 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Mon, 26 Sep 2016 12:43:24 +0200
Subject: [PATCH] replicainstall: run in interactive mode

Tweaks to replica installation to support interactive mode:
 - modified man to better document what actually happens
 - added principal/password prompt for unattended mode
   of ipa-replica-install if no credentials are set
 - made ipa-client-install run in interactive mode during
   replica promotion if it is itself not run in unattended mode

https://fedorahosted.org/freeipa/ticket/6068
---
 install/tools/man/ipa-replica-install.1    |   4 +-
 ipaserver/install/server/replicainstall.py | 115 +++++++++++++++++++----------
 2 files changed, 78 insertions(+), 41 deletions(-)

diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index af37b07..f94098d 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -49,7 +49,7 @@ A replica should only be installed on the same or higher version of IPA on the r
 The user principal which will be used to promote the client to the replica and enroll the client itself, if necessary.
 .TP
 \fB\-w\fR, \fB\-\-admin\-password\fR
-The Kerberos password for the given principal.
+The Kerberos password for the given principal. If no principal is supplied with \-\-principal, "admin" is assumed.
 
 .SS "DOMAIN LEVEL 1 CLIENT ENROLLMENT OPTIONS"
 To install client and promote it to replica using a host keytab or One Time Password, the host needs to be a member of ipaservers group. This requires to create a host entry and add it to the host group prior replica installation.
@@ -58,7 +58,7 @@ To install client and promote it to replica using a host keytab or One Time Pass
 
 .TP
 \fB\-p\fR \fIPASSWORD\fR, \fB\-\-password\fR=\fIPASSWORD\fR
-One Time Password for joining a machine to the IPA realm.
+One Time Password for joining a machine to the IPA realm. If the \-\-principal option is used, this is assumed a password for that principal.
 .TP
 \fB\-k\fR, \fB\-\-keytab\fR
 Path to host keytab.
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 7effda7..3a10907 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -14,6 +14,7 @@
 import shutil
 import socket
 import tempfile
+import getpass
 
 import six
 
@@ -918,46 +919,50 @@ def install(installer):
 
 
 def ensure_enrolled(installer):
-    # Call client install script
-    service.print_msg("Configuring client side components")
+    # Prepare options for the installer script
+    args = [paths.IPA_CLIENT_INSTALL, "--no-ntp"]
+    nolog = ()
+
+    if installer.unattended:
+        args.append("--unattended")
+    if installer.domain_name:
+        args.extend(["--domain", installer.domain_name])
+    if installer.server:
+        args.extend(["--server", installer.server])
+    if installer.realm_name:
+        args.extend(["--realm", installer.realm_name])
+    if installer.host_name:
+        args.extend(["--hostname", installer.host_name])
+    if installer.password:
+        args.extend(["--password", installer.password])
+    else:
+        if installer.admin_password:
+            # Always set principal if password was set explicitly.
+            # This is the behaviour from domain level 0 so we're keeping it
+            args.extend(["--principal", installer.principal or "admin"])
+            nolog = (installer.admin_password, )
+            args.extend(["--password", installer.admin_password])
+        if installer.keytab:
+            args.extend(["--keytab", installer.keytab])
+
+    if installer.no_dns_sshfp:
+        args.append("--no-dns-sshfp")
+    if installer.ssh_trust_dns:
+        args.append("--ssh-trust-dns")
+    if installer.no_ssh:
+        args.append("--no-ssh")
+    if installer.no_sshd:
+        args.append("--no-sshd")
+    if installer.mkhomedir:
+        args.append("--mkhomedir")
+
     try:
+        service.print_msg("Configuring client side components")
+        # Set _enrollment_performed to True so that any mess left behind in
+        # case of an enrollment failure gets cleaned
         installer._enrollment_performed = True
-
-        args = [paths.IPA_CLIENT_INSTALL, "--unattended", "--no-ntp"]
-        stdin = None
-
-        if installer.domain_name:
-            args.extend(["--domain", installer.domain_name])
-        if installer.server:
-            args.extend(["--server", installer.server])
-        if installer.realm_name:
-            args.extend(["--realm", installer.realm_name])
-        if installer.host_name:
-            args.extend(["--hostname", installer.host_name])
-
-        if installer.password:
-            args.extend(["--password", installer.password])
-        else:
-            if installer.admin_password:
-                # Always set principal if password was set explicitly,
-                # the password itself gets passed directly via stdin
-                args.extend(["--principal", installer.principal or "admin"])
-                stdin = installer.admin_password
-            if installer.keytab:
-                args.extend(["--keytab", installer.keytab])
-
-        if installer.no_dns_sshfp:
-            args.append("--no-dns-sshfp")
-        if installer.ssh_trust_dns:
-            args.append("--ssh-trust-dns")
-        if installer.no_ssh:
-            args.append("--no-ssh")
-        if installer.no_sshd:
-            args.append("--no-sshd")
-        if installer.mkhomedir:
-            args.append("--mkhomedir")
-
-        ipautil.run(args, stdin=stdin, redirect_output=True)
+        # Call client install script
+        ipautil.run(args, nolog=nolog, redirect_output=True)
         print()
     except Exception:
         raise ScriptError("Configuration of client side components failed!")
@@ -1583,7 +1588,8 @@ class Replica(BaseServer):
 
     admin_password = Knob(
         BaseServer.admin_password,
-        description="Kerberos password for the specified admin principal",
+        description="Kerberos password for the specified admin principal. "
+                    "If no principal is specified it assumes \"admin\".",
         cli_short_name='w',
     )
 
@@ -1661,6 +1667,37 @@ def __init__(self, **kwargs):
         if self.replica_file is None:
             self.promote = True
 
+            # unless some credentials are given, we need to have at least
+            # an admin principal and its password so these are not asked for
+            # twice (first in client-install, then in conncheck)
+            if (not self.unattended and self.password is None and
+                    self.keytab is None and self.admin_password is None and
+                    self._ccache is None):
+                if not self.principal:
+                    try:
+                        # get the principal interactively, can't be empty
+                        self.principal = ipautil.user_input(
+                                "User authorized to enroll computers",
+                                allow_empty=False)
+                        root_logger.debug(
+                                "will use principal provided as option: %s",
+                                self.principal)
+                    except Exception as e:
+                        print()
+                        # higher-level error so script usage is not printed
+                        raise ScriptError(str(e))
+                # the principal is set now, we need its password
+                try:
+                    self.password = getpass.getpass("Password for %s: " %
+                                                    self.principal)
+                except EOFError:
+                    print()
+                    self.password = None
+                if not self.password:
+                    # higher-level error so script usage is not printed
+                    raise ScriptError("Password must be provided for %s." %
+                                      self.principal)
+
             if self.principal and not self.admin_password:
                 self.admin_password = self.password
                 self.password = None
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to