-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Uses a new subclass IPAOptionParser in scripts instead of OptionParser
from the standard python library. IPAOptionParser uses its own IPAOption
class to store options, which adds a new 'sensitive' attribute.

https://fedorahosted.org/freeipa/ticket/393
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAkzPFocACgkQHsardTLnvCXxagCg1tuQv+lSo+i2f02WSYncQrRi
zZoAoKHoB/6qO5atlxUdw8G9X4nUf/TL
=oZDX
-----END PGP SIGNATURE-----
From 1eabce20969622f02165d5a64da3444ac9c44278 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 29 Oct 2010 20:24:31 +0200
Subject: [PATCH] Log script options to logfile

Uses a new subclass IPAOptionParser in scripts instead of OptionParser
from the standard python library. IPAOptionParser uses its own IPAOption
class to store options, which adds a new 'sensitive' attribute.

https://fedorahosted.org/freeipa/ticket/393
---
 install/tools/ipa-dns-install             |   13 +++++---
 install/tools/ipa-ldap-updater            |   10 ++++---
 install/tools/ipa-replica-install         |   12 +++++---
 install/tools/ipa-server-install          |   23 +++++++++------
 ipa-client/ipa-install/ipa-client-install |   12 +++++---
 ipapython/config.py                       |   42 ++++++++++++++++++++++++++++-
 6 files changed, 83 insertions(+), 29 deletions(-)

diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index ece77ec..8502e3b 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -19,7 +19,6 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 #
 
-from optparse import OptionParser
 import traceback
 
 from ipaserver.plugins.ldap2 import ldap2
@@ -28,11 +27,12 @@ from ipaserver.install.installutils import *
 from ipapython import version
 from ipapython import ipautil, sysrestore
 from ipalib import api, errors, util
+from ipapython.config import IPAOptionParser
 
 def parse_options():
-    parser = OptionParser(version=version.VERSION)
+    parser = IPAOptionParser(version=version.VERSION)
     parser.add_option("-p", "--ds-password", dest="dm_password",
-                      help="admin password")
+                      sensitive=True, help="admin password")
     parser.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="print debugging information")
     parser.add_option("--ip-address", dest="ip_address", help="Master Server IP Address")
@@ -46,6 +46,7 @@ def parse_options():
                       default=False, help="unattended installation never prompts the user")
 
     options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
 
     if options.forwarders and options.no_forwarders:
         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
@@ -56,7 +57,7 @@ def parse_options():
         if not options.forwarders and not options.no_forwarders:
             parser.error("You must specify at least one --forwarder option or --no-forwarders option")
 
-    return options
+    return safe_options, options
 
 def resolve_host(host_name):
     ip = None
@@ -76,7 +77,7 @@ def resolve_host(host_name):
     return ip
 
 def main():
-    options = parse_options()
+    safe_options, options = parse_options()
 
     if os.getegid() != 0:
         print "Must be root to setup server"
@@ -85,6 +86,8 @@ def main():
     standard_logging_setup("/var/log/ipaserver-install.log", options.debug, filemode='a')
     print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
 
+    logging.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
+
     global fstore
     fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
 
diff --git a/install/tools/ipa-ldap-updater b/install/tools/ipa-ldap-updater
index f3b83ce..51db012 100755
--- a/install/tools/ipa-ldap-updater
+++ b/install/tools/ipa-ldap-updater
@@ -25,7 +25,7 @@
 
 import sys
 try:
-    from optparse import OptionParser
+    from ipapython.config import IPAOptionParser
     from ipapython import ipautil, config
     from ipaserver.install import installutils
     from ipaserver.install.ldapupdate import LDAPUpdate, BadSyntax, UPDATES_DIR
@@ -44,7 +44,7 @@ error was:
 def parse_options():
     usage = "%prog [options] input_file(s)\n"
     usage += "%prog [options]\n"
-    parser = OptionParser(usage=usage, formatter=config.IPAFormatter())
+    parser = IPAOptionParser(usage=usage, formatter=config.IPAFormatter())
 
     parser.add_option("-d", "--debug", action="store_true", dest="debug",
                       help="Display debugging information about the update(s)")
@@ -59,10 +59,11 @@ def parse_options():
 
     config.add_standard_options(parser)
     options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
 
     config.init_config(options)
 
-    return options, args
+    return safe_options, options, args
 
 def get_dirman_password():
     """Prompt the user for the Directory Manager password and verify its
@@ -75,7 +76,7 @@ def get_dirman_password():
 def main():
     loglevel = logging.INFO
 
-    options, args = parse_options()
+    safe_options, options, args = parse_options()
     if options.debug:
         loglevel = logging.DEBUG
 
@@ -95,6 +96,7 @@ def main():
         logging.basicConfig(level=loglevel,
                             format='%(levelname)s %(message)s',
                             filename='/var/log/ipaupgrade.log')
+        logging.debug('%s was invoked with arguments %s and options: %s' % (sys.argv[0], args, safe_options))
         realm = krbV.default_context().default_realm
         upgrade = IPAUpgrade(realm, files, live_run=not options.test)
         upgrade.create_instance()
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index e541012..e4aae4a 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -31,6 +31,7 @@ from ipaserver.install import bindinstance, httpinstance, ntpinstance, certs
 from ipaserver.plugins.ldap2 import ldap2
 from ipapython import version
 from ipalib import api, errors, util
+from ipapython.config import IPAOptionParser
 
 CACERT="/usr/share/ipa/html/ca.crt"
 
@@ -50,14 +51,13 @@ class ReplicaConfig:
         self.subject_base = "O=IPA"
 
 def parse_options():
-    from optparse import OptionParser
     usage = "%prog [options] REPLICA_FILE"
-    parser = OptionParser(usage=usage, version=version.VERSION)
+    parser = IPAOptionParser(usage=usage, version=version.VERSION)
     parser.add_option("-N", "--no-ntp", dest="conf_ntp", action="store_false",
                       help="do not configure ntp", default=True)
     parser.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="gather extra debugging information")
-    parser.add_option("-p", "--password", dest="password", 
+    parser.add_option("-p", "--password", dest="password", sensitive=True,
                       help="Directory Manager (existing master) password")
     parser.add_option("--setup-dns", dest="setup_dns", action="store_true",
                       default=False, help="configure bind with our zone")
@@ -70,6 +70,7 @@ def parse_options():
                       help="Do not use DNS for hostname lookup during installation")
 
     options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
 
     if len(args) != 1:
         parser.error("you must provide a file generated by ipa-replica-prepare")
@@ -84,7 +85,7 @@ def parse_options():
     elif not options.forwarders and not options.no_forwarders:
         parser.error("You must specify at least one --forwarder option or --no-forwarders option")
 
-    return options, args[0]
+    return safe_options, options, args[0]
 
 def get_dirman_password():
     return installutils.read_password("Directory Manager (existing master)", confirm=False, validate=False)
@@ -261,8 +262,9 @@ def check_bind():
         sys.exit(1)
 
 def main():
-    options, filename = parse_options()
+    safe_options, options, filename = parse_options()
     installutils.standard_logging_setup("/var/log/ipareplica-install.log", options.debug)
+    logging.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
 
     if not ipautil.file_exists(filename):
         sys.exit("Replica file %s does not exist" % filename)
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index ebf7166..c5b3333 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -35,7 +35,6 @@ import signal
 import shutil
 import glob
 import traceback
-from optparse import OptionParser
 from ConfigParser import RawConfigParser
 import random
 
@@ -55,6 +54,7 @@ from ipaserver.plugins.ldap2 import ldap2
 from ipapython import sysrestore
 from ipapython.ipautil import *
 from ipalib import api, errors, util
+from ipapython.config import IPAOptionParser
 
 
 pw_name = None
@@ -65,7 +65,7 @@ MAXINT_32BIT = 2147483648
 
 def parse_options():
     namespace = random.randint(1000000, (MAXINT_32BIT - 1000000))
-    parser = OptionParser(version=version.VERSION)
+    parser = IPAOptionParser(version=version.VERSION)
     parser.add_option("-u", "--user", dest="ds_user",
                       help="ds user")
     parser.add_option("-r", "--realm", dest="realm_name",
@@ -73,10 +73,12 @@ def parse_options():
     parser.add_option("-n", "--domain", dest="domain_name",
                       help="domain name")
     parser.add_option("-p", "--ds-password", dest="dm_password",
-                      help="admin password")
-    parser.add_option("-P", "--master-password", dest="master_password",
+                      sensitive=True, help="admin password")
+    parser.add_option("-P", "--master-password",
+                      dest="master_password", sensitive=True,
                       help="kerberos master password (normally autogenerated)")
-    parser.add_option("-a", "--admin-password", dest="admin_password",
+    parser.add_option("-a", "--admin-password",
+                      sensitive=True, dest="admin_password",
                       help="admin user kerberos password")
     parser.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="print debugging information")
@@ -108,9 +110,9 @@ def parse_options():
                       help="PKCS#12 file containing the Directory Server SSL certificate")
     parser.add_option("--http_pkcs12", dest="http_pkcs12",
                       help="PKCS#12 file containing the Apache Server SSL certificate")
-    parser.add_option("--dirsrv_pin", dest="dirsrv_pin",
+    parser.add_option("--dirsrv_pin", dest="dirsrv_pin", sensitive=True,
                       help="The password of the Directory Server PKCS#12 file")
-    parser.add_option("--http_pin", dest="http_pin",
+    parser.add_option("--http_pin", dest="http_pin", sensitive=True,
                       help="The password of the Apache Server PKCS#12 file")
     parser.add_option("--no-host-dns", dest="no_host_dns", action="store_true",
                       default=False,
@@ -126,6 +128,7 @@ def parse_options():
                       action="store_true",
                       help="Don't install allow_all HBAC rule")
     options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
 
     if not options.setup_dns:
         if options.forwarders:
@@ -167,7 +170,7 @@ def parse_options():
     if (options.external_cert_file and not os.path.isabs(options.external_cert_file)):
         parser.error("--external-cert-file must use an absolute path")
 
-    return options
+    return safe_options, options
 
 def signal_handler(signum, frame):
     global ds
@@ -432,7 +435,7 @@ def main():
     global uninstalling
     ds = None
 
-    options = parse_options()
+    safe_options, options = parse_options()
 
     if os.getegid() != 0:
         print "Must be root to set up server"
@@ -450,6 +453,8 @@ def main():
         if dsinstance.DsInstance().is_configured() or cainstance.CADSInstance().is_configured():
             sys.exit("IPA server is already configured on this system.")
 
+    logging.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
+
     global fstore
     fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
 
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index b1e001c..8f4b9d2 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -28,7 +28,6 @@ try:
     import logging
     import tempfile
     import getpass
-    from optparse import OptionParser
     import ipaclient.ipadiscovery
     import ipaclient.ipachangeconf
     import ipaclient.ntpconf
@@ -36,6 +35,7 @@ try:
     from ipapython import sysrestore
     from ipapython import version
     from ipapython import certmonger
+    from ipapython.config import IPAOptionParser
     import SSSDConfig
     from ConfigParser import RawConfigParser
 except ImportError:
@@ -50,7 +50,7 @@ error was:
 client_nss_nickname = 'IPA Machine Certificate - %s' % socket.getfqdn()
 
 def parse_options():
-    parser = OptionParser(version=version.VERSION)
+    parser = IPAOptionParser(version=version.VERSION)
     parser.add_option("--domain", dest="domain", help="domain name")
     parser.add_option("--server", dest="server", help="IPA server")
     parser.add_option("--realm", dest="realm_name", help="realm name")
@@ -66,7 +66,7 @@ def parse_options():
                       help="do not configure sssd", default=True, dest="sssd")
     parser.add_option("-N", "--no-ntp", action="store_false",
                       help="do not configure ntp", default=True, dest="conf_ntp")
-    parser.add_option("-w", "--password", dest="password",
+    parser.add_option("-w", "--password", dest="password", sensitive=True,
                       help="password to join the IPA realm (assumes bulk password unless principal is also set)"),
     parser.add_option("-W", dest="prompt_password", action="store_true",
                       default=False,
@@ -83,11 +83,12 @@ def parse_options():
                       default=False, help="uninstall an existing installation")
 
     options, args = parser.parse_args()
+    safe_opts = parser.get_safe_opts(options)
 
     if (options.server and not options.domain):
         parser.error("--server cannot be used without providing --domain")
 
-    return options
+    return safe_opts, options
 
 def logging_setup(options):
     # Always log everything (i.e., DEBUG) to the log
@@ -500,8 +501,9 @@ def configure_sssd_conf(fstore, cli_domain, cli_server, options):
     return 0
 
 def main():
-    options = parse_options()
+    safe_options, options = parse_options()
     logging_setup(options)
+    logging.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
     dnsok = False
     env={"PATH":"/bin:/sbin:/usr/kerberos/bin:/usr/kerberos/sbin:/usr/bin:/usr/sbin"}
 
diff --git a/ipapython/config.py b/ipapython/config.py
index 12d916c..4df47de 100644
--- a/ipapython/config.py
+++ b/ipapython/config.py
@@ -18,7 +18,7 @@
 #
 
 import ConfigParser
-from optparse import OptionParser, IndentedHelpFormatter
+from optparse import Option, Values, OptionParser, IndentedHelpFormatter
 
 import socket
 import ipapython.dnsclient
@@ -46,6 +46,46 @@ class IPAFormatter(IndentedHelpFormatter):
             ret += "%s %s\n" % (spacing, line)
         return ret
 
+class IPAOption(Option):
+    """
+    optparse.Option subclass with support of options labeled as
+    security-sensitive such as passwords.
+    """
+    ATTRS = Option.ATTRS + ["sensitive"]
+
+class IPAOptionParser(OptionParser):
+    """
+    optparse.OptionParser subclass that uses IPAOption by default
+    for storing options.
+    """
+    def __init__(self,
+                 usage=None,
+                 option_list=None,
+                 option_class=IPAOption,
+                 version=None,
+                 conflict_handler="error",
+                 description=None,
+                 formatter=None,
+                 add_help_option=True,
+                 prog=None):
+        OptionParser.__init__(self, usage, option_list, option_class,
+                              version, conflict_handler, description,
+                              formatter, add_help_option, prog)
+
+    def get_safe_opts(self, opts):
+        """
+        Returns all options except those with sensitive=True in the same
+        fashion as parse_args would
+        """
+        all_opts_dict = dict([ (o.dest, o) for o in self._get_all_options() if hasattr(o, 'sensitive') ])
+        safe_opts_dict = {}
+
+        for option, value in opts.__dict__.iteritems():
+            if all_opts_dict[option].sensitive != True:
+                safe_opts_dict[option] = value
+
+        return Values(safe_opts_dict)
+
 def verify_args(parser, args, needed_args = None):
     """Verify that we have all positional arguments we need, if not, exit."""
     if needed_args:
-- 
1.7.2.3

Attachment: jhrozek-freeipa-0004-Log-script-options-to-logfile.patch.sig
Description: PGP signature

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to