mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-05-15 05:52:24 +00:00
Utils scripts: ansible-ipa-[server,replica,client]-install
These are utils scripts to do a server,replica or client deployment and undeployment using the ansible roles. A client inventory and playbook is generated by the script which is then used with ansible-playbook. The command line options or the normal command line installers ipa-server-install, ipa-replica-install and ipa-client-install are all supported also by these scripts. Additonally to the commadn line of the normal installers it is needed to add the fqdn of the host to be installed. It is needed that the ansible-freeipa roles are available and also usable by ansible.
This commit is contained in:
493
utils/ansible-ipa-replica-install
Executable file
493
utils/ansible-ipa-replica-install
Executable file
@@ -0,0 +1,493 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2019 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/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import argparse
|
||||
import traceback
|
||||
import subprocess
|
||||
|
||||
|
||||
def parse_options():
|
||||
usage = "Usage: anisble-ipa-replica-install [options] <ansible host>"
|
||||
|
||||
parser = argparse.ArgumentParser(usage=usage)
|
||||
parser.add_argument("--version", dest="version",
|
||||
action="store_true",
|
||||
help="show program's version number and exit")
|
||||
parser.add_argument("-U", "--unattended", dest="unattended",
|
||||
action="store_true",
|
||||
help="unattended (un)installation never prompts the "
|
||||
"user")
|
||||
# basic
|
||||
parser.add_argument("-w", "--admin-password", dest="admin_password",
|
||||
default=None,
|
||||
help="Kerberos password for the specified admin "
|
||||
"principal")
|
||||
parser.add_argument("--ip-address", dest="ip_addresses",
|
||||
metavar="IP_ADDRESS",
|
||||
action='append', default=None,
|
||||
help="Replica server IP Address. This option can be "
|
||||
"used multiple times")
|
||||
parser.add_argument("-n", "--domain", dest="domain",
|
||||
metavar="DOMAIN_NAME", default=None,
|
||||
help="primary DNS domain of the IPA deployment (not "
|
||||
"necessarily related to the current hostname)")
|
||||
parser.add_argument("--server", dest="servers",
|
||||
metavar="SERVER",
|
||||
action='append', default=None,
|
||||
help="fully qualified name of IPA server to enroll to")
|
||||
parser.add_argument("-r", "--realm", dest="realm",
|
||||
metavar="REALM_NAME", default=None,
|
||||
help="Kerberos realm name of the IPA deployment "
|
||||
"(typically un upper-cased name of the primary DNS "
|
||||
"domain)")
|
||||
parser.add_argument("--hostname", dest="hostname",
|
||||
metavar="HOST_NAME", default=None,
|
||||
help="fully qualified name of this host")
|
||||
parser.add_argument("-P", "--principal", dest="principal",
|
||||
default=None,
|
||||
help="User Principal allowed to promote replicas and "
|
||||
"join IPA realm")
|
||||
parser.add_argument("--pki-config-override", dest="pki_config_override",
|
||||
default=None,
|
||||
help="Path to ini file with config overrides.")
|
||||
parser.add_argument("--no-host-dns", dest="no_host_dns",
|
||||
action="store_true",
|
||||
help="Do not use DNS for hostname lookup during "
|
||||
"installation")
|
||||
parser.add_argument("--skip-conncheck", dest="skip_conncheck",
|
||||
action="store_true",
|
||||
help="skip connection check to remote master")
|
||||
# server
|
||||
parser.add_argument("-p", "--password", dest="dm_password",
|
||||
default=None,
|
||||
help="Password to join the IPA realm. Assumes bulk "
|
||||
"password unless principal is also set. (domain "
|
||||
"level 1+) Directory Manager (existing master) "
|
||||
"password. (domain level 0)")
|
||||
parser.add_argument("--hidden-replica", dest="hidden_replica",
|
||||
action="store_true",
|
||||
help="Install a hidden replica")
|
||||
parser.add_argument("--setup-adtrust", dest="setup_adtrust",
|
||||
action="store_true",
|
||||
help="configure AD trust capability")
|
||||
parser.add_argument("--setup-ca", dest="setup_ca",
|
||||
action="store_true",
|
||||
help="configure a dogtag CA")
|
||||
parser.add_argument("--setup-kra", dest="setup_kra",
|
||||
action="store_true",
|
||||
help="configure a dogtag KRA")
|
||||
parser.add_argument("--setup-dns", dest="setup_dns",
|
||||
action="store_true",
|
||||
help="configure bind with our zone")
|
||||
parser.add_argument("--no-pkinit", dest="no_pkinit",
|
||||
action="store_true",
|
||||
help="disables pkinit setup steps")
|
||||
parser.add_argument("--no-ui-redirect", dest="no_ui_redirect",
|
||||
action="store_true",
|
||||
help="Do not automatically redirect to the Web UI")
|
||||
parser.add_argument("--dirsrv-config-file", dest="dirsrv_config_file",
|
||||
metavar="FILE", default=None,
|
||||
help="The path to LDIF file that will be used to "
|
||||
"modify configuration of dse.ldif during "
|
||||
"installation of the directory server instance")
|
||||
# ssl certificate
|
||||
parser.add_argument("--dirsrv-cert-file", dest="dirsrv_cert_files",
|
||||
metavar="FILE", default=None, action="append",
|
||||
help="File containing the Directory Server SSL "
|
||||
"certificate and private key")
|
||||
parser.add_argument("--http-cert-file", dest="http_cert_files",
|
||||
metavar="FILE", default=None, action="append",
|
||||
help="File containing the Apache Server SSL "
|
||||
"certificate and private key")
|
||||
parser.add_argument("--pkinit-cert-file", dest="pkinit_cert_files",
|
||||
metavar="FILE", default=None, action="append",
|
||||
help="File containing the Kerberos KDC SSL "
|
||||
"certificate and Private key")
|
||||
parser.add_argument("--dirsrv-pin", dest="dirsrv_pin",
|
||||
metavar="PIN", default=None,
|
||||
help="The password to unlock the Directory Server "
|
||||
"private key")
|
||||
parser.add_argument("--http-pin", dest="http_pin",
|
||||
metavar="PIN", default=None,
|
||||
help="The password to unlock the Apache Server "
|
||||
"private key")
|
||||
parser.add_argument("--pkinit-pin", dest="pkinit_pin",
|
||||
metavar="PIN", default=None,
|
||||
help="The password to unlock the Kerberos KDC "
|
||||
"private key")
|
||||
parser.add_argument("--dirsrv-cert-name", dest="dirsrv_cert_name",
|
||||
metavar="NAME", default=None,
|
||||
help="Name of the Directory Server SSL certificate "
|
||||
"to install")
|
||||
parser.add_argument("--http-cert-name", dest="http_cert_name",
|
||||
metavar="NAME", default=None,
|
||||
help="Name of the Apache Server SSL certificate to "
|
||||
"install")
|
||||
parser.add_argument("--pkinit-cert-name", dest="pkinit_cert_name",
|
||||
metavar="NAME", default=None,
|
||||
help="Name of the Kerberos KDC SSL certificate to "
|
||||
"install")
|
||||
# client
|
||||
parser.add_argument("-k", "--keytab", dest="keytab",
|
||||
default=None,
|
||||
help="path to backed up keytab from previous "
|
||||
"enrollment")
|
||||
parser.add_argument("--mkhomedir", dest="mkhomedir",
|
||||
action="store_true",
|
||||
help="create home directories for users on their "
|
||||
"first login")
|
||||
parser.add_argument("--force-join", dest="force_join",
|
||||
action="store_true",
|
||||
help="Force client enrollment even if already "
|
||||
"enrolled")
|
||||
parser.add_argument("--ntp-server", dest="ntp_servers",
|
||||
metavar="NTP_SERVER",
|
||||
action='append', default=None,
|
||||
help="ntp server to use. This option can be used "
|
||||
"multiple times")
|
||||
parser.add_argument("--ntp-pool", dest="ntp_pool",
|
||||
default=None,
|
||||
help="ntp server pool to use")
|
||||
parser.add_argument("-N", "--no-ntp", dest="no_ntp",
|
||||
action="store_true",
|
||||
help="do not configure ntp")
|
||||
parser.add_argument("--ssh-trust-dns", dest="ssh_trust_dns",
|
||||
action="store_true",
|
||||
help="configure OpenSSH client to trust DNS SSHFP "
|
||||
"records")
|
||||
parser.add_argument("--no-ssh", dest="no_ssh",
|
||||
action="store_true",
|
||||
help="do not configure OpenSSH client")
|
||||
parser.add_argument("--no-sshd", dest="no_sshd",
|
||||
action="store_true",
|
||||
help="do not configure OpenSSH server")
|
||||
parser.add_argument("--no-dns-sshfp", dest="no_dns_sshfp",
|
||||
action="store_true",
|
||||
help="do not automatically create DNS SSHFP records")
|
||||
# certificate system
|
||||
parser.add_argument("--skip-schema-check", dest="skip_schema_check",
|
||||
action="store_true",
|
||||
help="skip check for updated CA DS schema on the "
|
||||
"remote master")
|
||||
# dns
|
||||
parser.add_argument("--allow-zone-overlap", dest="allow_zone_overlap",
|
||||
action="store_true",
|
||||
help="Create DNS zone even if it already exists")
|
||||
parser.add_argument("--reverse-zone", dest="reverse_zones",
|
||||
metavar="REVERSE_ZONE", action="append", default=None,
|
||||
help="The reverse DNS zone to use. This option can "
|
||||
"be used multiple times")
|
||||
parser.add_argument("--no-reverse", dest="no_reverse",
|
||||
action="store_true",
|
||||
help="Do not create new reverse DNS zone")
|
||||
parser.add_argument("--auto-reverse", dest="auto_reverse",
|
||||
action="store_true",
|
||||
help="Create necessary reverse zones")
|
||||
parser.add_argument("--forwarder", dest="forwarders",
|
||||
action="append", default=None,
|
||||
help="Add a DNS forwarder. This option can be used "
|
||||
"multiple times")
|
||||
parser.add_argument("--no-forwarders", dest="no_forwarders",
|
||||
action="store_true",
|
||||
help="Do not add any DNS forwarders, use root "
|
||||
"servers instead")
|
||||
parser.add_argument("--auto-forwarders", dest="auto_forwarders",
|
||||
action="store_true",
|
||||
help="Use DNS forwarders configured in "
|
||||
"/etc/resolv.conf")
|
||||
parser.add_argument("-forward-policy-", dest="forward_policy",
|
||||
choices=("only", "first"), default=None,
|
||||
help="DNS forwarding policy for global forwarders")
|
||||
parser.add_argument("--no-dnssec-validation", dest="no_dnssec_validation",
|
||||
action="store_true",
|
||||
help="Disable DNSSEC validation")
|
||||
# ad trust
|
||||
parser.add_argument("--add-sids", dest="add_sids",
|
||||
action="store_true",
|
||||
help="Add SIDs for existing users and groups as the "
|
||||
"final step")
|
||||
parser.add_argument("--add-agents", dest="add_agents",
|
||||
action="store_true",
|
||||
help="Add IPA masters to a list of hosts allowed to "
|
||||
"serve information about users from trusted forests")
|
||||
parser.add_argument("--enable-compat", dest="enable_compat",
|
||||
action="store_true",
|
||||
help="Enable support for trusted domains for old "
|
||||
"clients")
|
||||
parser.add_argument("--netbios-name", dest="netbios_name",
|
||||
default=None,
|
||||
help="NetBIOS name of the IPA domain")
|
||||
parser.add_argument("--rid-base", dest="rid_base",
|
||||
default=None, type=int,
|
||||
help="Start value for mapping UIDs and GIDs to RIDs")
|
||||
parser.add_argument("--secondary-rid-base", dest="secondary_rid_base",
|
||||
default=None, type=int,
|
||||
help="Start value of the secondary range for mapping "
|
||||
"UIDs and GIDs to RIDs")
|
||||
# logging and output
|
||||
parser.add_argument("-v", "--verbose", dest="verbose",
|
||||
action="store_true",
|
||||
help="print debugging information")
|
||||
parser.add_argument("-d", "--debug", dest="verbose",
|
||||
action="store_true",
|
||||
help="alias for --verbose (deprecated)")
|
||||
parser.add_argument("-q", "--quiet", dest="quiet",
|
||||
action="store_true",
|
||||
help="output only errors")
|
||||
parser.add_argument("--log-file", dest="log_file",
|
||||
help="log to the given file")
|
||||
# ansible
|
||||
parser.add_argument("--ipareplica-install-packages",
|
||||
dest="ipareplica_install_packages",
|
||||
choices=("yes", "no"), default=None,
|
||||
help="The bool value defines if the needed packages "
|
||||
"are installed on the node. Default: yes")
|
||||
parser.add_argument("--ipareplica-setup-firewalld",
|
||||
dest="ipareplica_setup_firewalld",
|
||||
choices=("yes", "no"), default=None,
|
||||
help="The value defines if the needed services will "
|
||||
"automatically be openen in the firewall managed by "
|
||||
"firewalld. Default: yes")
|
||||
|
||||
options, args = parser.parse_known_args()
|
||||
|
||||
if options.log_file:
|
||||
parser.error("log_file is not supported")
|
||||
|
||||
if len(args) < 1:
|
||||
parser.error("ansible host not set")
|
||||
elif len(args) > 1:
|
||||
parser.error("too many arguments")
|
||||
|
||||
return options, args
|
||||
|
||||
|
||||
def run_cmd(args):
|
||||
"""
|
||||
Execute an external command.
|
||||
"""
|
||||
p_out = subprocess.PIPE
|
||||
p_err = subprocess.STDOUT
|
||||
try:
|
||||
p = subprocess.Popen(args, stdout=p_out, stderr=p_err,
|
||||
close_fds=True, bufsize=1,
|
||||
universal_newlines=True)
|
||||
with p.stdout:
|
||||
for line in p.stdout:
|
||||
sys.stdout.write(line)
|
||||
except KeyboardInterrupt:
|
||||
p.wait()
|
||||
raise
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def main(options, args):
|
||||
temp_dir = tempfile.mkdtemp(prefix='ansible-ipa')
|
||||
|
||||
inventory = os.path.join(temp_dir, "replica-inventory")
|
||||
playbook = os.path.join(temp_dir, "replica-playbook.yml")
|
||||
|
||||
with open(inventory, 'w') as f:
|
||||
if options.servers:
|
||||
f.write("[ipaservers]\n")
|
||||
for server in options.servers:
|
||||
f.write("%s\n" % server)
|
||||
f.write("\n")
|
||||
f.write("[ipareplica]\n")
|
||||
f.write("%s\n" % args[0])
|
||||
f.write("\n")
|
||||
f.write("[ipareplica:vars]\n")
|
||||
# basic
|
||||
if options.admin_password:
|
||||
f.write("ipaadmin_password=%s\n" % options.admin_password)
|
||||
if options.ip_addresses:
|
||||
f.write("ipareplica_ip_addresses=%s\n" %
|
||||
",".join(options.ip_addresses))
|
||||
if options.domain:
|
||||
f.write("ipareplica_domain=%s\n" % options.domain)
|
||||
# --servers are handled above
|
||||
if options.realm:
|
||||
f.write("ipareplica_realm=%s\n" % options.realm)
|
||||
if options.hostname:
|
||||
f.write("ipareplica_hostname=%s\n" % options.hostname)
|
||||
if options.principal:
|
||||
f.write("ipaadmin_principal=%s\n" % options.principal)
|
||||
if options.pki_config_override:
|
||||
f.write("ipareplica_pki_config_override=yes\n")
|
||||
if options.no_host_dns:
|
||||
f.write("ipareplica_no_host_dns=yes\n")
|
||||
if options.skip_conncheck:
|
||||
f.write("ipareplica_skip_conncheck=yes\n")
|
||||
# server
|
||||
if options.dm_password:
|
||||
f.write("ipadm_password=%s\n" % options.dm_password)
|
||||
if options.hidden_replica:
|
||||
f.write("ipareplica_hidden_replica=yes\n")
|
||||
if options.setup_adtrust:
|
||||
f.write("ipareplica_setup_adtrust=yes\n")
|
||||
if options.setup_ca:
|
||||
f.write("ipareplica_setup_ca=yes\n")
|
||||
if options.setup_kra:
|
||||
f.write("ipareplica_setup_kra=yes\n")
|
||||
if options.setup_dns:
|
||||
f.write("ipareplica_setup_dns=yes\n")
|
||||
if options.no_pkinit:
|
||||
f.write("ipareplica_no_pkinit=yes\n")
|
||||
if options.no_ui_redirect:
|
||||
f.write("ipareplica_no_ui_redirect=yes\n")
|
||||
# ssl certificate
|
||||
if options.dirsrv_cert_files:
|
||||
f.write("ipareplica_dirsrv_cert_files=%s\n" %
|
||||
",".join(options.dirsrv_cert_files))
|
||||
if options.http_cert_files:
|
||||
f.write("ipareplica_http_cert_files=%s\n" %
|
||||
",".join(options.http_cert_files))
|
||||
if options.pkinit_cert_files:
|
||||
f.write("ipareplica_pkinit_cert_files=%s\n" %
|
||||
",".join(options.pkinit_cert_files))
|
||||
if options.dirsrv_pin:
|
||||
f.write("ipareplica_dirsrv_pin=%s\n" % options.dirsrv_pin)
|
||||
if options.http_pin:
|
||||
f.write("ipareplica_http_pin=%s\n" % options.http_pin)
|
||||
if options.pkinit_pin:
|
||||
f.write("ipareplica_pkinit_pin=%s\n" % options.pkinit_pin)
|
||||
if options.dirsrv_cert_name:
|
||||
f.write("ipareplica_dirsrv_cert_name=%s\n" %
|
||||
options.dirsrv_cert_name)
|
||||
if options.http_cert_name:
|
||||
f.write("ipareplica_http_cert_name=%s\n" % options.http_cert_name)
|
||||
if options.pkinit_cert_name:
|
||||
f.write("ipareplica_pkinit_cert_name=%s\n" %
|
||||
options.pkinit_cert_name)
|
||||
# client
|
||||
if options.keytab:
|
||||
f.write("ipaclient_keytab=%s\n" % options.keytab)
|
||||
if options.mkhomedir:
|
||||
f.write("ipaclient_mkhomedir=yes\n")
|
||||
if options.force_join:
|
||||
f.write("ipaclient_force_join=yes\n")
|
||||
if options.ntp_servers:
|
||||
f.write("ipaclient_ntp_server=%s\n" %
|
||||
",".join(options.ntp_replicas))
|
||||
if options.ntp_pool:
|
||||
f.write("ipaclient_ntp_pool=%s\n" % options.ntp_pool)
|
||||
if options.no_ntp:
|
||||
f.write("ipaclient_no_ntp=yes\n")
|
||||
if options.ssh_trust_dns:
|
||||
f.write("ipaclient_ssh_trust_dns=yes\n")
|
||||
if options.no_ssh:
|
||||
f.write("ipaclient_no_ssh=yes\n")
|
||||
if options.no_sshd:
|
||||
f.write("ipaclient_no_sshd=yes\n")
|
||||
if options.no_dns_sshfp:
|
||||
f.write("ipaclient_no_dns_sshfp=yes\n")
|
||||
# certificate system
|
||||
if options.skip_schema_check:
|
||||
f.write("ipareplica_skip_schema_check=yes\n")
|
||||
# dns
|
||||
if options.allow_zone_overlap:
|
||||
f.write("ipareplica_allow_zone_overlap=yes\n")
|
||||
if options.reverse_zones:
|
||||
f.write("ipareplica_reverse_zones=%s\n" %
|
||||
",".join(options.reverse_zones))
|
||||
if options.no_reverse:
|
||||
f.write("ipareplica_no_reverse=yes\n")
|
||||
if options.auto_reverse:
|
||||
f.write("ipareplica_auto_reverse=yes\n")
|
||||
if options.forwarders:
|
||||
f.write("ipareplica_forwarders=%s\n" %
|
||||
",".join(options.forwarders))
|
||||
if options.no_forwarders:
|
||||
f.write("ipareplica_no_forwarders=yes\n")
|
||||
if options.auto_forwarders:
|
||||
f.write("ipareplica_auto_forwarders=yes\n")
|
||||
if options.forward_policy:
|
||||
f.write("ipareplica_forward_policy=%s\n" % options.forward_policy)
|
||||
if options.no_dnssec_validation:
|
||||
f.write("ipareplica_no_dnssec_validation=yes\n")
|
||||
# ad trust
|
||||
if options.add_sids:
|
||||
f.write("ipareplica_add_sids=yes\n")
|
||||
if options.add_agents:
|
||||
f.write("ipareplica_add_agents=yes\n")
|
||||
if options.enable_compat:
|
||||
f.write("ipareplica_enable_compat=yes\n")
|
||||
if options.netbios_name:
|
||||
f.write("ipareplica_netbios_name=%s\n" % options.netbios_name)
|
||||
if options.rid_base:
|
||||
f.write("ipareplica_rid_base=%s\n" % options.rid_base)
|
||||
if options.secondary_rid_base:
|
||||
f.write("ipareplica_secondary_rid_base=%s\n" %
|
||||
options.secondary_rid_base)
|
||||
# ansible
|
||||
if options.ipareplica_install_packages:
|
||||
f.write("ipareplica_install-packages=%s\n" %
|
||||
options.ipareplica_install_packages)
|
||||
if options.ipareplica_setup_firewalld:
|
||||
f.write("ipareplica_setup_firewalld=%s\n" %
|
||||
options.ipareplica_setup_firewalld)
|
||||
|
||||
# uninstall done with ipaserver role
|
||||
state = "present"
|
||||
|
||||
with open(playbook, 'w') as f:
|
||||
f.write("""---
|
||||
- name: Playbook to configure IPA replica
|
||||
hosts: ipareplica
|
||||
become: true
|
||||
|
||||
roles:
|
||||
- role: ipareplica
|
||||
state: %s
|
||||
""" % state)
|
||||
|
||||
try:
|
||||
returncode = run_cmd(['ansible-playbook', '-i', inventory, playbook])
|
||||
if returncode != 0:
|
||||
raise RuntimeError()
|
||||
finally:
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
|
||||
|
||||
options, args = parse_options()
|
||||
try:
|
||||
main(options, args)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
except SystemExit as e:
|
||||
sys.exit(e)
|
||||
except RuntimeError as e:
|
||||
sys.exit(e)
|
||||
except Exception as e:
|
||||
if options.verbose:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
else:
|
||||
print("Re-run %s with --verbose option to get more information" %
|
||||
sys.argv[0])
|
||||
|
||||
print("Unexpected error: %s" % str(e))
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user