mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
There should not be mixed statestore as global variable and as local function parameter. This commit fixes usage of sysrestore and statestore as local variables only. In future we may need to change default statestore and fstore depending on where the functions are called and this change makes it easier and less error prone. https://fedorahosted.org/freeipa/ticket/6392 Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
284 lines
14 KiB
Python
Executable File
284 lines
14 KiB
Python
Executable File
#! /usr/bin/python2 -E
|
|
# Authors: Simo Sorce <ssorce@redhat.com>
|
|
# Karl MacMillan <kmacmillan@mentalrootkit.com>
|
|
#
|
|
# Copyright (C) 2007 Red Hat
|
|
# see file 'COPYING' for use and warranty information
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
from __future__ import print_function
|
|
|
|
import sys
|
|
import os
|
|
|
|
from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
|
|
|
|
from ipaclient.install import client
|
|
from ipapython.ipa_log_manager import standard_logging_setup, root_logger
|
|
from ipapython.ipautil import is_fips_enabled
|
|
from ipaplatform.tasks import tasks
|
|
from ipaplatform.paths import paths
|
|
from ipapython import version, sysrestore
|
|
from ipapython.config import IPAOptionParser
|
|
from ipalib import x509
|
|
from ipalib.util import normalize_hostname, validate_domain_name
|
|
|
|
|
|
def parse_options():
|
|
def validate_ca_cert_file_option(option, opt, value, parser):
|
|
if not os.path.exists(value):
|
|
raise OptionValueError("%s option '%s' does not exist" % (opt, value))
|
|
if not os.path.isfile(value):
|
|
raise OptionValueError("%s option '%s' is not a file" % (opt, value))
|
|
if not os.path.isabs(value):
|
|
raise OptionValueError("%s option '%s' is not an absolute file path" % (opt, value))
|
|
|
|
try:
|
|
x509.load_certificate_from_file(value)
|
|
except Exception:
|
|
raise OptionValueError("%s option '%s' is not a valid certificate file" % (opt, value))
|
|
|
|
parser.values.ca_cert_file = value
|
|
|
|
def kinit_attempts_callback(option, opt, value, parser):
|
|
if value < 1:
|
|
raise OptionValueError(
|
|
"Option %s expects an integer greater than 0."
|
|
% opt)
|
|
|
|
parser.values.kinit_attempts = value
|
|
|
|
parser = IPAOptionParser(version=version.VERSION)
|
|
|
|
basic_group = OptionGroup(parser, "basic options")
|
|
basic_group.add_option("--domain", dest="domain", help="domain name")
|
|
basic_group.add_option("--server", dest="server", help="FQDN of IPA server", action="append")
|
|
basic_group.add_option("--realm", dest="realm_name", help="realm name")
|
|
basic_group.add_option("--fixed-primary", dest="primary", action="store_true",
|
|
default=False, help="Configure sssd to use fixed server as primary IPA server")
|
|
basic_group.add_option("-p", "--principal", dest="principal",
|
|
help="principal to use to join the IPA realm")
|
|
basic_group.add_option("-w", "--password", dest="password", sensitive=True,
|
|
help="password to join the IPA realm (assumes bulk "
|
|
"password unless principal is also set)")
|
|
basic_group.add_option("-k", "--keytab", dest="keytab",
|
|
help="path to backed up keytab from previous enrollment")
|
|
basic_group.add_option("-W", dest="prompt_password", action="store_true",
|
|
default=False,
|
|
help="Prompt for a password to join the IPA realm")
|
|
basic_group.add_option("--mkhomedir", dest="mkhomedir",
|
|
action="store_true", default=False,
|
|
help="create home directories for users on their first login")
|
|
basic_group.add_option("", "--hostname", dest="hostname",
|
|
help="The hostname of this machine (FQDN). If specified, the hostname will be set and "
|
|
"the system configuration will be updated to persist over reboot. "
|
|
"By default the result of getfqdn() call from "
|
|
"Python's socket module is used.")
|
|
basic_group.add_option("", "--force-join", dest="force_join",
|
|
action="store_true", default=False,
|
|
help="Force client enrollment even if already enrolled")
|
|
basic_group.add_option("--ntp-server", dest="ntp_servers", action="append",
|
|
help="ntp server to use. This option can be used "
|
|
"multiple times")
|
|
basic_group.add_option("-N", "--no-ntp", action="store_false",
|
|
help="do not configure ntp", default=True, dest="conf_ntp")
|
|
basic_group.add_option("", "--force-ntpd", dest="force_ntpd",
|
|
action="store_true", default=False,
|
|
help="Stop and disable any time&date synchronization services besides ntpd")
|
|
basic_group.add_option("--nisdomain", dest="nisdomain",
|
|
help="NIS domain name")
|
|
basic_group.add_option("--no-nisdomain", action="store_true", default=False,
|
|
help="do not configure NIS domain name",
|
|
dest="no_nisdomain")
|
|
basic_group.add_option("--ssh-trust-dns", dest="trust_sshfp", default=False, action="store_true",
|
|
help="configure OpenSSH client to trust DNS SSHFP records")
|
|
basic_group.add_option("--no-ssh", dest="conf_ssh", default=True, action="store_false",
|
|
help="do not configure OpenSSH client")
|
|
basic_group.add_option("--no-sshd", dest="conf_sshd", default=True, action="store_false",
|
|
help="do not configure OpenSSH server")
|
|
basic_group.add_option("--no-sudo", dest="conf_sudo", default=True,
|
|
action="store_false",
|
|
help="do not configure SSSD as data source for sudo")
|
|
basic_group.add_option("--no-dns-sshfp", dest="create_sshfp", default=True, action="store_false",
|
|
help="do not automatically create DNS SSHFP records")
|
|
basic_group.add_option("--noac", dest="no_ac", default=False, action="store_true",
|
|
help="do not modify the nsswitch.conf and PAM configuration")
|
|
basic_group.add_option("-f", "--force", dest="force", action="store_true",
|
|
default=False, help="force setting of LDAP/Kerberos conf")
|
|
basic_group.add_option('--kinit-attempts', dest='kinit_attempts',
|
|
action='callback', type='int', default=5,
|
|
callback=kinit_attempts_callback,
|
|
help=("number of attempts to obtain host TGT"
|
|
" (defaults to %default)."))
|
|
basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
|
|
default=False, help="print debugging information")
|
|
basic_group.add_option("-U", "--unattended", dest="unattended",
|
|
action="store_true",
|
|
help="unattended (un)installation never prompts the user")
|
|
basic_group.add_option("--ca-cert-file", dest="ca_cert_file",
|
|
type="string", action="callback", callback=validate_ca_cert_file_option,
|
|
help="load the CA certificate from this file")
|
|
basic_group.add_option("--request-cert", dest="request_cert",
|
|
action="store_true", default=False,
|
|
help="request certificate for the machine")
|
|
# --on-master is used in ipa-server-install and ipa-replica-install
|
|
# only, it isn't meant to be used on clients.
|
|
basic_group.add_option("--on-master", dest="on_master", action="store_true",
|
|
help=SUPPRESS_HELP, default=False)
|
|
basic_group.add_option("--automount-location", dest="location",
|
|
help="Automount location")
|
|
basic_group.add_option("--configure-firefox", dest="configure_firefox",
|
|
action="store_true", default=False,
|
|
help="configure Firefox to use IPA domain credentials")
|
|
basic_group.add_option("--firefox-dir", dest="firefox_dir", default=None,
|
|
help="specify directory where Firefox is installed (for example: '/usr/lib/firefox')")
|
|
basic_group.add_option("--ip-address", dest="ip_addresses", default=[],
|
|
action="append", help="Specify IP address that should be added to DNS."
|
|
" This option can be used multiple times")
|
|
basic_group.add_option("--all-ip-addresses", dest="all_ip_addresses",
|
|
default=False, action="store_true", help="All routable IP"
|
|
" addresses configured on any inteface will be added to DNS")
|
|
parser.add_option_group(basic_group)
|
|
|
|
sssd_group = OptionGroup(parser, "SSSD options")
|
|
sssd_group.add_option("--permit", dest="permit",
|
|
action="store_true", default=False,
|
|
help="disable access rules by default, permit all access.")
|
|
sssd_group.add_option("", "--enable-dns-updates", dest="dns_updates",
|
|
action="store_true", default=False,
|
|
help="Configures the machine to attempt dns updates when the ip address changes.")
|
|
sssd_group.add_option("--no-krb5-offline-passwords", dest="krb5_offline_passwords",
|
|
action="store_false", default=True,
|
|
help="Configure SSSD not to store user password when the server is offline")
|
|
sssd_group.add_option("-S", "--no-sssd", dest="sssd",
|
|
action="store_false", default=True,
|
|
help="Do not configure the client to use SSSD for authentication")
|
|
sssd_group.add_option("--preserve-sssd", dest="preserve_sssd",
|
|
action="store_true", default=False,
|
|
help="Preserve old SSSD configuration if possible")
|
|
parser.add_option_group(sssd_group)
|
|
|
|
uninstall_group = OptionGroup(parser, "uninstall options")
|
|
uninstall_group.add_option("", "--uninstall", dest="uninstall", action="store_true",
|
|
default=False, help="uninstall an existing installation. The uninstall can " \
|
|
"be run with --unattended option")
|
|
parser.add_option_group(uninstall_group)
|
|
|
|
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")
|
|
|
|
if options.domain:
|
|
try:
|
|
validate_domain_name(options.domain)
|
|
except ValueError as ex:
|
|
parser.error("invalid domain name: %s" % ex)
|
|
options.domain = normalize_hostname(options.domain)
|
|
|
|
if options.force_ntpd and not options.conf_ntp:
|
|
parser.error("--force-ntpd cannot be used together with --no-ntp")
|
|
|
|
if options.firefox_dir and not options.configure_firefox:
|
|
parser.error("--firefox-dir cannot be used without --configure-firefox option")
|
|
|
|
if options.no_nisdomain and options.nisdomain:
|
|
parser.error("--no-nisdomain cannot be used together with --nisdomain")
|
|
|
|
if options.ip_addresses:
|
|
if options.dns_updates:
|
|
parser.error("--ip-address cannot be used together with"
|
|
" --enable-dns-updates")
|
|
|
|
if options.all_ip_addresses:
|
|
parser.error("--ip-address cannot be used together with"
|
|
" --all-ip-addresses")
|
|
|
|
return safe_opts, options
|
|
|
|
|
|
def logging_setup(options):
|
|
log_file = paths.IPACLIENT_INSTALL_LOG
|
|
|
|
if options.uninstall:
|
|
log_file = paths.IPACLIENT_UNINSTALL_LOG
|
|
|
|
standard_logging_setup(
|
|
filename=log_file, verbose=True, debug=options.debug,
|
|
console_format='%(message)s')
|
|
|
|
|
|
def main():
|
|
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
|
safe_options, options = parse_options()
|
|
|
|
if not os.getegid() == 0:
|
|
sys.exit("\nYou must be root to run ipa-client-install.\n")
|
|
if is_fips_enabled():
|
|
sys.exit("Installing IPA client in FIPS mode is not supported")
|
|
|
|
tasks.check_selinux_status()
|
|
logging_setup(options)
|
|
root_logger.debug(
|
|
'%s was invoked with options: %s', sys.argv[0], safe_options)
|
|
root_logger.debug("missing options might be asked for interactively later")
|
|
root_logger.debug('IPA version %s' % version.VENDOR_VERSION)
|
|
|
|
env={"PATH":"/bin:/sbin:/usr/kerberos/bin:/usr/kerberos/sbin:/usr/bin:/usr/sbin"}
|
|
|
|
if options.uninstall:
|
|
return client.uninstall(options, env)
|
|
|
|
if client.is_ipa_client_installed(fstore, on_master=options.on_master):
|
|
root_logger.error("IPA client is already configured on this system.")
|
|
root_logger.info(
|
|
"If you want to reinstall the IPA client, uninstall it first " +
|
|
"using 'ipa-client-install --uninstall'.")
|
|
return client.CLIENT_ALREADY_CONFIGURED
|
|
|
|
rval = client.install(options, env)
|
|
if rval == client.CLIENT_INSTALL_ERROR:
|
|
if options.force:
|
|
root_logger.warning(
|
|
"Installation failed. Force set so not rolling back changes.")
|
|
elif options.on_master:
|
|
root_logger.warning(
|
|
"Installation failed. As this is IPA server, changes will not "
|
|
"be rolled back."
|
|
)
|
|
else:
|
|
root_logger.error("Installation failed. Rolling back changes.")
|
|
options.unattended = True
|
|
client.uninstall(options, env)
|
|
|
|
return rval
|
|
|
|
try:
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|
|
except SystemExit as e:
|
|
sys.exit(e)
|
|
except KeyboardInterrupt:
|
|
sys.exit(1)
|
|
except RuntimeError as e:
|
|
sys.exit(e)
|
|
finally:
|
|
try:
|
|
os.remove(client.CCACHE_FILE)
|
|
except Exception:
|
|
pass
|