Blame roles/ipaserver/module_utils/ansible_ipa_server.py

Packit Service 0a38ef
# -*- coding: utf-8 -*-
Packit Service 0a38ef
Packit Service 0a38ef
# Authors:
Packit Service 0a38ef
#   Thomas Woerner <twoerner@redhat.com>
Packit Service 0a38ef
#
Packit Service 0a38ef
# Based on ipa-client-install code
Packit Service 0a38ef
#
Packit Service 0a38ef
# Copyright (C) 2017  Red Hat
Packit Service 0a38ef
# see file 'COPYING' for use and warranty information
Packit Service 0a38ef
#
Packit Service 0a38ef
# This program is free software; you can redistribute it and/or modify
Packit Service 0a38ef
# it under the terms of the GNU General Public License as published by
Packit Service 0a38ef
# the Free Software Foundation, either version 3 of the License, or
Packit Service 0a38ef
# (at your option) any later version.
Packit Service 0a38ef
#
Packit Service 0a38ef
# This program is distributed in the hope that it will be useful,
Packit Service 0a38ef
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 0a38ef
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 0a38ef
# GNU General Public License for more details.
Packit Service 0a38ef
#
Packit Service 0a38ef
# You should have received a copy of the GNU General Public License
Packit Service 0a38ef
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 0a38ef
Packit Service 0a38ef
__all__ = ["IPAChangeConf", "certmonger", "sysrestore", "root_logger",
Packit Service 0a38ef
           "ipa_generate_password", "run", "ScriptError", "services",
Packit Service 0a38ef
           "tasks", "errors", "x509", "DOMAIN_LEVEL_0", "MIN_DOMAIN_LEVEL",
Packit Service 0a38ef
           "validate_domain_name",
Packit Service 0a38ef
           "no_matching_interface_for_ip_address_warning",
Packit Service 0a38ef
           "check_zone_overlap", "timeconf", "ntpinstance", "adtrust",
Packit Service 0a38ef
           "bindinstance", "ca", "dns", "httpinstance", "installutils",
Packit Service 0a38ef
           "kra", "krbinstance", "otpdinstance", "custodiainstance",
Packit Service 0a38ef
           "replication", "service", "sysupgrade", "IPA_MODULES",
Packit Service 0a38ef
           "BadHostError", "get_fqdn", "get_server_ip_address",
Packit Service 0a38ef
           "is_ipa_configured", "load_pkcs12", "read_password", "verify_fqdn",
Packit Service 0a38ef
           "update_hosts_file", "check_dirsrv", "validate_admin_password",
Packit Service 0a38ef
           "validate_dm_password", "read_cache", "write_cache",
Packit Service 0a38ef
           "adtrustinstance", "IPAAPI_USER", "sync_time", "PKIIniLoader",
Packit Service 0a38ef
           "default_subject_base", "default_ca_subject_dn",
Packit Service a166ed
           "check_ldap_conf", "encode_certificate", "decode_certificate",
Packit Service a166ed
           "check_available_memory"]
Packit Service 0a38ef
Packit Service 0a38ef
import sys
Packit Service 0a38ef
import logging
Packit Service 0a38ef
from contextlib import contextmanager as contextlib_contextmanager
Packit Service 0a38ef
import six
Packit Service 0a38ef
import base64
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
from ipapython.version import NUM_VERSION, VERSION
Packit Service 0a38ef
Packit Service 0a38ef
if NUM_VERSION < 30201:
Packit Service 0a38ef
    # See ipapython/version.py
Packit Service 0a38ef
    IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in VERSION.split(".", 2)]
Packit Service 0a38ef
    IPA_PYTHON_VERSION = IPA_MAJOR*10000 + IPA_MINOR*100 + IPA_RELEASE
Packit Service 0a38ef
else:
Packit Service 0a38ef
    IPA_PYTHON_VERSION = NUM_VERSION
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
if NUM_VERSION >= 40500:
Packit Service 0a38ef
    # IPA version >= 4.5
Packit Service 0a38ef
Packit Service 0a38ef
    from ipaclient.install.ipachangeconf import IPAChangeConf
Packit Service a166ed
    from ipalib.install import certmonger
Packit Service a166ed
    try:
Packit Service a166ed
        from ipalib import sysrestore
Packit Service a166ed
    except ImportError:
Packit Service a166ed
        from ipalib.install import sysrestore
Packit Service 0a38ef
    from ipapython import ipautil
Packit Service 0a38ef
    from ipapython.ipa_log_manager import standard_logging_setup
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipapython.ipa_log_manager import root_logger
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        root_logger = None
Packit Service 0a38ef
    from ipapython.ipautil import (
Packit Service 0a38ef
        ipa_generate_password, run)
Packit Service 0a38ef
    from ipapython.admintool import ScriptError
Packit Service 0a38ef
    from ipaplatform import services
Packit Service 0a38ef
    from ipaplatform.paths import paths
Packit Service 0a38ef
    from ipaplatform.tasks import tasks
Packit Service 0a38ef
    from ipalib import api, errors, x509
Packit Service 0a38ef
    from ipalib.constants import DOMAIN_LEVEL_0, MIN_DOMAIN_LEVEL, \
Packit Service 0a38ef
        MAX_DOMAIN_LEVEL
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipalib.constants import IPAAPI_USER
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        IPAAPI_USER = None
Packit Service 0a38ef
    from ipalib.util import (
Packit Service 0a38ef
        validate_domain_name,
Packit Service 0a38ef
        no_matching_interface_for_ip_address_warning,
Packit Service 0a38ef
    )
Packit Service 0a38ef
    from ipapython.dnsutil import check_zone_overlap
Packit Service 0a38ef
    from ipapython.dn import DN
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipaclient.install import timeconf
Packit Service 0a38ef
        from ipaclient.install.client import sync_time
Packit Service 0a38ef
        time_service = "chronyd"
Packit Service 0a38ef
        ntpinstance = None
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        try:
Packit Service 0a38ef
            from ipaclient.install import ntpconf as timeconf
Packit Service 0a38ef
        except ImportError:
Packit Service 0a38ef
            from ipaclient import ntpconf as timeconf
Packit Service 0a38ef
        from ipaserver.install import ntpinstance
Packit Service 0a38ef
        time_service = "ntpd"
Packit Service 0a38ef
        sync_time = None
Packit Service 0a38ef
    from ipaserver.install import (
Packit Service 0a38ef
        adtrust, bindinstance, ca, dns, dsinstance,
Packit Service 0a38ef
        httpinstance, installutils, kra, krbinstance,
Packit Service 0a38ef
        otpdinstance, custodiainstance, replication, service,
Packit Service 0a38ef
        sysupgrade)
Packit Service 0a38ef
    adtrust_imported = True
Packit Service 0a38ef
    kra_imported = True
Packit Service 0a38ef
    from ipaserver.install.installutils import (
Packit Service a166ed
        BadHostError, get_fqdn, get_server_ip_address,
Packit Service a166ed
        load_pkcs12, read_password, verify_fqdn,
Packit Service 0a38ef
        update_hosts_file)
Packit Service a166ed
    try:
Packit Service a166ed
        from ipalib.facts import is_ipa_configured
Packit Service a166ed
    except ImportError:
Packit Service a166ed
        from ipaserver.install.installutils import is_ipa_configured
Packit Service 0a38ef
    from ipaserver.install.server.install import (
Packit Service 0a38ef
        check_dirsrv, validate_admin_password, validate_dm_password,
Packit Service 0a38ef
        read_cache, write_cache)
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipaserver.install.dogtaginstance import PKIIniLoader
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        PKIIniLoader = None
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipaserver.install.installutils import default_subject_base
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        def default_subject_base(realm_name):
Packit Service 0a38ef
            return DN(('O', realm_name))
Packit Service 0a38ef
    try:
Packit Service a166ed
        from ipalib.facts import IPA_MODULES
Packit Service a166ed
    except ImportError:
Packit Service a166ed
        from ipaserver.install.installutils import IPA_MODULES
Packit Service a166ed
    try:
Packit Service 0a38ef
        from ipaserver.install.installutils import default_ca_subject_dn
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        def default_ca_subject_dn(subject_base):
Packit Service 0a38ef
            return DN(('CN', 'Certificate Authority'), subject_base)
Packit Service a166ed
    try:
Packit Service a166ed
        from ipaserver.install.installutils import check_available_memory
Packit Service a166ed
    except ImportError:
Packit Service a166ed
        check_available_memory = None
Packit Service 0a38ef
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipaserver.install import adtrustinstance
Packit Service 0a38ef
        _server_trust_ad_installed = True
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        _server_trust_ad_installed = False
Packit Service 0a38ef
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipaclient.install.client import check_ldap_conf
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        check_ldap_conf = None
Packit Service 0a38ef
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipalib.x509 import Encoding
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        from cryptography.hazmat.primitives.serialization import Encoding
Packit Service 0a38ef
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        from ipalib.x509 import load_pem_x509_certificate
Packit Service 0a38ef
    except ImportError:
Packit Service 0a38ef
        from ipalib.x509 import load_certificate
Packit Service 0a38ef
        load_pem_x509_certificate = None
Packit Service 0a38ef
Packit Service 0a38ef
else:
Packit Service 0a38ef
    # IPA version < 4.5
Packit Service 0a38ef
Packit Service 0a38ef
    raise Exception("freeipa version '%s' is too old" % VERSION)
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
logger = logging.getLogger("ipa-server-install")
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def setup_logging():
Packit Service 0a38ef
    # logger.setLevel(logging.DEBUG)
Packit Service 0a38ef
    standard_logging_setup(
Packit Service 0a38ef
        paths.IPASERVER_INSTALL_LOG, verbose=False, debug=False,
Packit Service 0a38ef
        filemode='a', console_format='%(message)s')
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
@contextlib_contextmanager
Packit Service 0a38ef
def redirect_stdout(f):
Packit Service 0a38ef
    sys.stdout = f
Packit Service 0a38ef
    try:
Packit Service 0a38ef
        yield f
Packit Service 0a38ef
    finally:
Packit Service 0a38ef
        sys.stdout = sys.__stdout__
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
class AnsibleModuleLog():
Packit Service 0a38ef
    def __init__(self, module):
Packit Service 0a38ef
        self.module = module
Packit Service 0a38ef
        _ansible_module_log = self
Packit Service 0a38ef
Packit Service 0a38ef
        class AnsibleLoggingHandler(logging.Handler):
Packit Service 0a38ef
            def emit(self, record):
Packit Service 0a38ef
                _ansible_module_log.write(self.format(record))
Packit Service 0a38ef
Packit Service 0a38ef
        self.logging_handler = AnsibleLoggingHandler()
Packit Service 0a38ef
        logger.setLevel(logging.DEBUG)
Packit Service 0a38ef
        logger.root.addHandler(self.logging_handler)
Packit Service 0a38ef
Packit Service 0a38ef
    def close(self):
Packit Service 0a38ef
        self.flush()
Packit Service 0a38ef
Packit Service 0a38ef
    def flush(self):
Packit Service 0a38ef
        pass
Packit Service 0a38ef
Packit Service 0a38ef
    def log(self, msg):
Packit Service 0a38ef
        # self.write(msg+"\n")
Packit Service 0a38ef
        self.write(msg)
Packit Service 0a38ef
Packit Service 0a38ef
    def debug(self, msg):
Packit Service 0a38ef
        self.module.debug(msg)
Packit Service 0a38ef
Packit Service 0a38ef
    def info(self, msg):
Packit Service 0a38ef
        self.module.debug(msg)
Packit Service 0a38ef
Packit Service 0a38ef
    def write(self, msg):
Packit Service 0a38ef
        self.module.debug(msg)
Packit Service 0a38ef
        # self.module.warn(msg)
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
class options_obj(object):
Packit Service 0a38ef
    def __init__(self):
Packit Service 0a38ef
        self._replica_install = False
Packit Service 0a38ef
        self.dnssec_master = False  # future unknown
Packit Service 0a38ef
        self.disable_dnssec_master = False  # future unknown
Packit Service 0a38ef
        self.domainlevel = MAX_DOMAIN_LEVEL  # deprecated
Packit Service 0a38ef
        self.domain_level = self.domainlevel  # deprecated
Packit Service 0a38ef
        self.interactive = False
Packit Service 0a38ef
        self.unattended = not self.interactive
Packit Service 0a38ef
Packit Service 0a38ef
    # def __getattribute__(self, attr):
Packit Service 0a38ef
    #    logger.info(" <-- Accessing options.%s" % attr)
Packit Service 0a38ef
    #    return super(options_obj, self).__getattribute__(attr)
Packit Service 0a38ef
Packit Service 0a38ef
    # def __getattr__(self, attr):
Packit Service 0a38ef
    #    logger.info(" --> Adding missing options.%s" % attr)
Packit Service 0a38ef
    #    setattr(self, attr, None)
Packit Service 0a38ef
    #    return getattr(self, attr)
Packit Service 0a38ef
Packit Service 0a38ef
    def knobs(self):
Packit Service 0a38ef
        for name in self.__dict__:
Packit Service 0a38ef
            yield self, name
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
options = options_obj()
Packit Service 0a38ef
installer = options
Packit Service 0a38ef
Packit Service 0a38ef
# ServerMasterInstall
Packit Service 0a38ef
options.add_sids = True
Packit Service 0a38ef
options.add_agents = False
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
# Installable
Packit Service 0a38ef
options.uninstalling = False
Packit Service 0a38ef
Packit Service 0a38ef
# ServerInstallInterface
Packit Service 0a38ef
options.description = "Server"
Packit Service 0a38ef
Packit Service 0a38ef
options.kinit_attempts = 1
Packit Service 0a38ef
options.fixed_primary = True
Packit Service 0a38ef
options.permit = False
Packit Service 0a38ef
options.enable_dns_updates = False
Packit Service 0a38ef
options.no_krb5_offline_passwords = False
Packit Service 0a38ef
options.preserve_sssd = False
Packit Service 0a38ef
options.no_sssd = False
Packit Service 0a38ef
Packit Service 0a38ef
# ServerMasterInstall
Packit Service 0a38ef
options.force_join = False
Packit Service 0a38ef
options.servers = None
Packit Service 0a38ef
options.no_wait_for_dns = True
Packit Service 0a38ef
options.host_password = None
Packit Service 0a38ef
options.keytab = None
Packit Service 0a38ef
options.setup_ca = True
Packit Service 0a38ef
# always run sidgen task and do not allow adding agents on first master
Packit Service 0a38ef
options.add_sids = True
Packit Service 0a38ef
options.add_agents = False
Packit Service 0a38ef
Packit Service 0a38ef
# ADTrustInstallInterface
Packit Service 0a38ef
# no_msdcs is deprecated
Packit Service 0a38ef
options.no_msdcs = False
Packit Service 0a38ef
Packit Service 0a38ef
# For pylint
Packit Service 0a38ef
options.external_cert_files = None
Packit Service 0a38ef
options.dirsrv_cert_files = None
Packit Service 0a38ef
Packit Service 0a38ef
# Uninstall
Packit Service 0a38ef
options.ignore_topology_disconnect = False
Packit Service 0a38ef
options.ignore_last_of_role = False
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def api_Backend_ldap2(host_name, setup_ca, connect=False):
Packit Service 0a38ef
    # we are sure we have the configuration file ready.
Packit Service 0a38ef
    cfg = dict(context='installer', confdir=paths.ETC_IPA, in_server=True,
Packit Service 0a38ef
               host=host_name)
Packit Service 0a38ef
    if setup_ca:
Packit Service 0a38ef
        # we have an IPA-integrated CA
Packit Service 0a38ef
        cfg['ca_host'] = host_name
Packit Service 0a38ef
Packit Service 0a38ef
    api.bootstrap(**cfg)
Packit Service 0a38ef
    api.finalize()
Packit Service 0a38ef
    if connect:
Packit Service 0a38ef
        api.Backend.ldap2.connect()
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def ds_init_info(ansible_log, fstore, domainlevel, dirsrv_config_file,
Packit Service 0a38ef
                 realm_name, host_name, domain_name, dm_password,
Packit Service 0a38ef
                 idstart, idmax, subject_base, ca_subject,
Packit Service 0a38ef
                 no_hbac_allow, dirsrv_pkcs12_info, no_pkinit):
Packit Service 0a38ef
Packit Service 0a38ef
    if not options.external_cert_files:
Packit Service 0a38ef
        ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel,
Packit Service 0a38ef
                                   config_ldif=dirsrv_config_file)
Packit Service 0a38ef
        ds.set_output(ansible_log)
Packit Service 0a38ef
Packit Service 0a38ef
        if options.dirsrv_cert_files:
Packit Service 0a38ef
            _dirsrv_pkcs12_info = dirsrv_pkcs12_info
Packit Service 0a38ef
        else:
Packit Service 0a38ef
            _dirsrv_pkcs12_info = None
Packit Service 0a38ef
Packit Service 0a38ef
        with redirect_stdout(ansible_log):
Packit Service 0a38ef
            ds.init_info(realm_name, host_name, domain_name, dm_password,
Packit Service 0a38ef
                         subject_base, ca_subject, idstart, idmax,
Packit Service 0a38ef
                         # hbac_allow=not no_hbac_allow,
Packit Service 0a38ef
                         _dirsrv_pkcs12_info, setup_pkinit=not no_pkinit)
Packit Service 0a38ef
    else:
Packit Service 0a38ef
        ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel)
Packit Service 0a38ef
        ds.set_output(ansible_log)
Packit Service 0a38ef
Packit Service 0a38ef
        with redirect_stdout(ansible_log):
Packit Service 0a38ef
            ds.init_info(realm_name, host_name, domain_name, dm_password,
Packit Service 0a38ef
                         subject_base, ca_subject, 1101, 1100, None,
Packit Service 0a38ef
                         setup_pkinit=not no_pkinit)
Packit Service 0a38ef
Packit Service 0a38ef
    return ds
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def ansible_module_get_parsed_ip_addresses(ansible_module,
Packit Service 0a38ef
                                           param='ip_addresses'):
Packit Service 0a38ef
    ip_addrs = []
Packit Service 0a38ef
    for ip in ansible_module.params.get(param):
Packit Service 0a38ef
        try:
Packit Service 0a38ef
            ip_parsed = ipautil.CheckedIPAddress(ip)
Packit Service 0a38ef
        except Exception as e:
Packit Service 0a38ef
            ansible_module.fail_json(msg="Invalid IP Address %s: %s" % (ip, e))
Packit Service 0a38ef
        ip_addrs.append(ip_parsed)
Packit Service 0a38ef
    return ip_addrs
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def encode_certificate(cert):
Packit Service 0a38ef
    """
Packit Service 0a38ef
    Encode a certificate using base64.
Packit Service 0a38ef
Packit Service 0a38ef
    It also takes FreeIPA and Python versions into account.
Packit Service 0a38ef
    """
Packit Service 0a38ef
    if isinstance(cert, (str, bytes)):
Packit Service 0a38ef
        encoded = base64.b64encode(cert)
Packit Service 0a38ef
    else:
Packit Service 0a38ef
        encoded = base64.b64encode(cert.public_bytes(Encoding.DER))
Packit Service 0a38ef
    if not six.PY2:
Packit Service 0a38ef
        encoded = encoded.decode('ascii')
Packit Service 0a38ef
    return encoded
Packit Service 0a38ef
Packit Service 0a38ef
Packit Service 0a38ef
def decode_certificate(cert):
Packit Service 0a38ef
    """
Packit Service 0a38ef
    Decode a certificate using base64.
Packit Service 0a38ef
Packit Service 0a38ef
    It also takes FreeIPA versions into account and returns a IPACertificate
Packit Service 0a38ef
    for newer IPA versions.
Packit Service 0a38ef
    """
Packit Service 0a38ef
    if hasattr(x509, "IPACertificate"):
Packit Service 0a38ef
        cert = cert.strip()
Packit Service 0a38ef
        if not cert.startswith("-----BEGIN CERTIFICATE-----"):
Packit Service 0a38ef
            cert = "-----BEGIN CERTIFICATE-----\n" + cert
Packit Service 0a38ef
        if not cert.endswith("-----END CERTIFICATE-----"):
Packit Service 0a38ef
            cert += "\n-----END CERTIFICATE-----"
Packit Service 0a38ef
Packit Service 0a38ef
        if load_pem_x509_certificate is not None:
Packit Service 0a38ef
            cert = load_pem_x509_certificate(cert.encode('utf-8'))
Packit Service 0a38ef
        else:
Packit Service 0a38ef
            cert = load_certificate(cert.encode('utf-8'))
Packit Service 0a38ef
    else:
Packit Service 0a38ef
        cert = base64.b64decode(cert)
Packit Service 0a38ef
    return cert