Skip to content
Snippets Groups Projects
Select Git revision
  • 005b01bd9a79b0111d0506e69c0d16ce11c01cf5
  • master default protected
  • v2.28.0
  • v2.27.0
  • v2.25.1
  • v2.24.3
  • v2.26.0
  • v2.24.2
  • v2.25.0
  • v2.24.1
  • v2.22.2
  • v2.23.3
  • v2.24.0
  • v2.23.2
  • v2.23.1
  • v2.23.0
  • v2.22.1
  • v2.22.0
  • v2.21.0
  • v2.20.0
  • v2.19.1
  • v2.18.2
22 results

ansible.md

Blame
  • ansible-ipa-server-install 26.71 KiB
    #!/usr/bin/python
    # -*- 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-server-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")
        parser.add_argument("--uninstall", dest="uninstall",
                            action="store_true",
                            help="uninstall an existing installation. The "
                            "uninstall can be run with --unattended option")
        # basic
        parser.add_argument("-p", "--ds-password", dest="dm_password",
                            default=None,
                            help="Directory Manager password")
        parser.add_argument("-a", "--admin-password", dest="admin_password",
                            default=None,
                            help="admin user kerberos password")
        parser.add_argument("--ip-address", dest="ip_addresses",
                            metavar="IP_ADDRESS",
                            action='append', default=None,
                            help="Master 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("-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("--ca-cert-file", dest="ca_cert_file",
                            metavar="FILE", default=None,
                            help="File containing CA certificates for the "
                            "service certificate files")
        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")
        # server
        parser.add_argument("--setup-adtrust", dest="setup_adtrust",
                            action="store_true",
                            help="configure AD trust capability")
        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("--idstart", dest="idstart",
                            type=int, default=None,
                            help="The starting value for the IDs range (default "
                            "random)")
        parser.add_argument("--idmax", dest="idmax",
                            default=None, type=int,
                            help="The max value for the IDs range (default: "
                            "idstart+199999)")
        parser.add_argument("--no-hbac-allow", dest="no_hbac_allow",
                            action="store_true",
                            help="Don't install allow_all HBAC rule")
        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("--mkhomedir", dest="mkhomedir",
                            action="store_true",
                            help="create home directories for users on their "
                            "first login")
        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("--external-ca", dest="external_ca",
                            action="store_true",
                            help="Generate a CSR for the IPA CA certificate to "
                            "be signed by an external CA")
        parser.add_argument("--external-ca-type", dest="external_ca_type",
                            choices=("generic", "ms-cs"), default=None,
                            help="Type of the external CA")
        parser.add_argument("--external-ca-profile", dest="external_ca_profile",
                            default=None,
                            help="Specify the certificate profile/template to "
                            "use at the external CA")
        parser.add_argument("--external-cert-file", dest="external_cert_files",
                            metavar="FILE", default=None, action="append",
                            help="File containing the IPA CA certificate and the "
                            "external CA certificate chain")
        parser.add_argument("--subject-base", dest="subject_base",
                            default=None,
                            help="The certificate subject base (default "
                            "O=<realm-name>). RDNs are in LDAP order (most "
                            "specific RDN first).")
        parser.add_argument("--ca-subject", dest="ca_subject",
                            default=None,
                            help="The CA certificate subject DN (default "
                            "CN=Certificate Authority,O=<realm-name>). RDNs are "
                            "in LDAP order (most specific RDN first).")
        parser.add_argument("--ca-signing-algorithm", dest="ca_signing_algorithm",
                            choices=("SHA1withRSA", "SHA256withRSA",
                                     "SHA512withRSA"),
                            default=None,
                            help="Signing algorithm of the IPA CA certificate")
        # 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("--zonemgr", dest="zonemgr",
                            default=None,
                            help="DNS zone manager e-mail address. Defaults to "
                            "hostmaster@DOMAIN")
        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("--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")
        # uninstall
        parser.add_argument("--ignore-topology-disconnect",
                            dest="ignore_topology_disconnect",
                            action="store_true",
                            help="do not check whether server uninstall "
                            "disconnects the topology (domain level 1+)")
        parser.add_argument("--ignore-last-of-role", dest="ignore_last_of_role",
                            action="store_true",
                            help="do not check whether server uninstall removes "
                            "last CA/DNS server or DNSSec master (domain level "
                            "1+)")
        # 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("--ipaserver-install-packages",
                            dest="ipaserver_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("--ipaserver-setup-firewalld",
                            dest="ipaserver_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")
        parser.add_argument("--ipaserver-external-cert-files-from-controller",
                            dest="ipaserver_external_cert_files_from_controller",
                            default=None, action="append",
                            help="Files containing the IPA CA certificates and "
                            "the external CA certificate chains on the "
                            "controller that will be copied to the ipaserver "
                            "host to /root folder.")
        parser.add_argument("--ipaserver-copy-csr-to-controller",
                            dest="ipaserver_copy_csr_to_controller",
                            choices=("yes", "no"), default=None,
                            help="Copy the generated CSR from the ipaserver to "
                            "the controller as <hostname>-ipa.csr.")
        # playbook
        parser.add_argument("--playbook-dir",
                            dest="playbook_dir",
                            default=None,
                            help="If defined will be used as to create inventory "
                            "file and playbook in. The files will not be removed "
                            "after the playbook processing ended.")
        parser.add_argument("--become-method",
                            dest="become_method",
                            default="sudo",
                            help="privilege escalation method to use "
                            "(default=sudo), use `ansible-doc -t become -l` to "
                            "list valid choices.")
    
        options, args = parser.parse_known_args()
    
        if options.playbook_dir and not os.path.isdir(options.playbook_dir):
            parser.error("playbook dir does not exist")
    
        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: %s" % ",".join(args))
    
        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)
            while True:
                line = p.stdout.readline()
                if p.poll() is not None and line == "":
                    break
                sys.stdout.write(line)
        except KeyboardInterrupt:
            p.wait()
            raise
        else:
            p.wait()
            return p.returncode
    
    
    def main(options, args):
        if options.playbook_dir:
            playbook_dir = options.playbook_dir
        else:
            temp_dir = tempfile.mkdtemp(prefix='ansible-ipa-server')
            playbook_dir = temp_dir
    
        inventory = os.path.join(playbook_dir, "ipaserver-inventory")
        playbook = os.path.join(playbook_dir, "ipaserver-playbook.yml")
    
        with open(inventory, 'w') as f:
            f.write("[ipaserver]\n")
            f.write("%s\n" % args[0])
            f.write("\n")
            f.write("[ipaserver:vars]\n")
            # basic
            if options.dm_password:
                f.write("ipadm_password=%s\n" % options.dm_password)
            if options.admin_password:
                f.write("ipaadmin_password=%s\n" % options.admin_password)
            if options.ip_addresses:
                f.write("ipaserver_ip_addresses=%s\n" %
                        ",".join(options.ip_addresses))
            if options.domain:
                f.write("ipaserver_domain=%s\n" % options.domain)
            if options.realm:
                f.write("ipaserver_realm=%s\n" % options.realm)
            if options.hostname:
                f.write("ipaserver_hostname=%s\n" % options.hostname)
            if options.ca_cert_file:
                f.write("ipaserver_ca_cert_files=%s\n" % options.ca_cert_file)
            if options.pki_config_override:
                f.write("ipaserver_pki_config_override=yes\n")
            if options.no_host_dns:
                f.write("ipaserver_no_host_dns=yes\n")
            # server
            if options.setup_adtrust:
                f.write("ipaserver_setup_adtrust=yes\n")
            if options.setup_kra:
                f.write("ipaserver_setup_kra=yes\n")
            if options.setup_dns:
                f.write("ipaserver_setup_dns=yes\n")
            if options.idstart:
                f.write("ipaserver_idstart=%s\n" % options.idstart)
            if options.idmax:
                f.write("ipaserver_idmax=%s\n" % options.idmax)
            if options.no_hbac_allow:
                f.write("ipaserver_no_hbac_allow=yes\n")
            if options.no_pkinit:
                f.write("ipaserver_no_pkinit=yes\n")
            if options.no_ui_redirect:
                f.write("ipaserver_no_ui_redirect=yes\n")
            if options.dirsrv_config_file:
                f.write("ipaserver_dirsrv_config_file=%s\n" %
                        options.dirsrv_config_file)
            # ssl certificate
            if options.dirsrv_cert_files:
                f.write("ipaserver_dirsrv_cert_files=%s\n" %
                        ",".join(options.dirsrv_cert_files))
            if options.http_cert_files:
                f.write("ipaserver_http_cert_files=%s\n" %
                        ",".join(options.http_cert_files))
            if options.pkinit_cert_files:
                f.write("ipaserver_pkinit_cert_files=%s\n" %
                        ",".join(options.pkinit_cert_files))
            if options.dirsrv_pin:
                f.write("ipaserver_dirsrv_pin=%s\n" % options.dirsrv_pin)
            if options.http_pin:
                f.write("ipaserver_http_pin=%s\n" % options.http_pin)
            if options.pkinit_pin:
                f.write("ipaserver_pkinit_pin=%s\n" % options.pkinit_pin)
            if options.dirsrv_cert_name:
                f.write("ipaserver_dirsrv_cert_name=%s\n" %
                        options.dirsrv_cert_name)
            if options.http_cert_name:
                f.write("ipaserver_http_cert_name=%s\n" % options.http_cert_name)
            if options.pkinit_cert_name:
                f.write("ipaserver_pkinit_cert_name=%s\n" %
                        options.pkinit_cert_name)
            # client
            if options.mkhomedir:
                f.write("ipaclient_mkhomedir=yes\n")
            if options.ntp_servers:
                f.write("ipaclient_ntp_servers=%s\n" %
                        ",".join(options.ntp_servers))
            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.external_ca:
                f.write("ipaserver_external_ca=yes\n")
            if options.external_ca_type:
                f.write("ipaserver_external_ca_type=%s\n" %
                        options.external_ca_type)
            if options.external_ca_profile:
                f.write("ipaserver_external_ca_profile=%s\n" %
                        options.external_ca_profile)
            if options.external_cert_files:
                f.write("ipaserver_external_cert_files=%s\n" %
                        ",".join(options.external_cert_files))
            if options.subject_base:
                f.write("ipaserver_subject_base=%s\n" % options.subject_base)
            if options.ca_subject:
                f.write("ipaserver_ca_subject=%s\n" % options.ca_subject)
            if options.ca_signing_algorithm:
                f.write("ipaserver_ca_signing_algorithm=%s\n" %
                        options.ca_signing_algorithm)
            # dns
            if options.allow_zone_overlap:
                f.write("ipaserver_allow_zone_overlap=yes\n")
            if options.reverse_zones:
                f.write("ipaserver_reverse_zones=%s\n" %
                        ",".join(options.reverse_zones))
            if options.no_reverse:
                f.write("ipaserver_no_reverse=yes\n")
            if options.auto_reverse:
                f.write("ipaserver_auto_reverse=yes\n")
            if options.zonemgr:
                f.write("ipaserver_zonemgr=%s\n" % options.zonemgr)
            if options.forwarders:
                f.write("ipaserver_forwarders=%s\n" %
                        ",".join(options.forwarders))
            if options.no_forwarders:
                f.write("ipaserver_no_forwarders=yes\n")
            if options.auto_forwarders:
                f.write("ipaserver_auto_forwarders=yes\n")
            if options.forward_policy:
                f.write("ipaserver_forward_policy=%s\n" % options.forward_policy)
            if options.no_dnssec_validation:
                f.write("ipaserver_no_dnssec_validation=yes\n")
            # ad trust
            if options.enable_compat:
                f.write("ipaserver_enable_compat=yes\n")
            if options.netbios_name:
                f.write("ipaserver_netbios_name=%s\n" % options.netbios_name)
            if options.rid_base:
                f.write("ipaserver_rid_base=%s\n" % options.rid_base)
            if options.secondary_rid_base:
                f.write("ipaserver_secondary_rid_base=%s\n" %
                        options.secondary_rid_base)
            # uninstall
            if options.ignore_topology_disconnect:
                f.write("ipaserver_ignore_topology_disconnect=yes\n")
            if options.ignore_last_of_role:
                f.write("ipaserver_ignore_last_of_role=yes\n")
            # ansible
            if options.ipaserver_install_packages:
                f.write("ipaserver_install_packages=%s\n" %
                        options.ipaserver_install_packages)
            if options.ipaserver_setup_firewalld:
                f.write("ipaserver_setup_firewalld=%s\n" %
                        options.ipaserver_setup_firewalld)
            if options.ipaserver_external_cert_files_from_controller:
                f.write("ipaserver_external_cert_files_from_controller=%s\n" %
                        ",".join(
                            options.ipaserver_external_cert_files_from_controller))
            if options.ipaserver_copy_csr_to_controller:
                f.write("ipaserver_copy_csr_to_controller=%s\n" %
                        options.ipaserver_copy_csr_to_controller)
    
        if options.uninstall:
            state = "absent"
        else:
            state = "present"
    
        with open(playbook, 'w') as f:
            f.write("---\n")
            f.write("- name: Playbook to configure IPA server\n")
            f.write("  hosts: ipaserver\n")
            f.write("  become: true\n")
            if options.become_method:
                f.write("  become_method: %s\n" % options.become_method)
            f.write("\n")
            f.write("  roles:\n")
            f.write("  - role: ipaserver\n")
            f.write("    state: %s\n" % state)
    
        try:
            returncode = run_cmd(['ansible-playbook', '-i', inventory, playbook])
            if returncode != 0:
                raise RuntimeError()
        finally:
            if not options.playbook_dir:
                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)