Ejemplo n.º 1
0
def verify_host_resolvable(fqdn, log):
    """
    See if the hostname has a DNS A/AAAA record.
    """
    if not isinstance(fqdn, DNSName):
        fqdn = DNSName(fqdn)

    fqdn = fqdn.make_absolute()
    for rdtype in ('A', 'AAAA'):
        try:
            answers = resolver.query(fqdn, rdtype)
            log.debug(
                'IPA: found %d %s records for %s: %s' % (len(answers),
                rdtype, fqdn, ' '.join(str(answer) for answer in answers))
            )
        except DNSException:
            log.debug(
                'IPA: DNS %s record lookup failed for %s' %
                (rdtype, fqdn)
            )
            continue
        else:
            return
    # dns lookup failed in both tries
    raise errors.DNSNotARecordError()
Ejemplo n.º 2
0
    def __setup_server_configuration(self):
        ensure_dnsserver_container_exists(api.Backend.ldap2, self.api)
        try:
            self.api.Command.dnsserver_add(
                self.fqdn,
                idnssoamname=DNSName(self.fqdn).make_absolute(),
            )
        except errors.DuplicateEntry:
            # probably reinstallation of DNS
            pass

        try:
            self.api.Command.dnsserver_mod(
                self.fqdn,
                idnsforwarders=[unicode(f) for f in self.forwarders],
                idnsforwardpolicy=unicode(self.forward_policy))
        except errors.EmptyModlist:
            pass

        sysupgrade.set_upgrade_state('dns', 'server_config_to_ldap', True)
Ejemplo n.º 3
0
def xml_unwrap(value, encoding='UTF-8'):
    """
    Unwrap all ``xmlrpc.Binary``, decode all ``str`` into ``unicode``.

    When decoding data from an XML-RPC packet, the following transformations
    occur:

        * The binary payloads of all ``xmlrpc.client.Binary`` instances are
          returned as ``str`` instances.

        * All ``str`` instances are treated as UTF-8 encoded Unicode strings.
          They are decoded and the resulting ``unicode`` instance is returned.

    Also see `xml_wrap()`.

    :param value: The value to unwrap.
    :param encoding: The Unicode encoding to use (defaults to ``'UTF-8'``).
    """
    if isinstance(value, (unicode, int, float, bool)):
        # most common first
        return value
    elif value is None:
        return value
    elif isinstance(value, bytes):
        return value.decode(encoding)
    elif isinstance(value, (list, tuple)):
        return tuple(xml_unwrap(v, encoding) for v in value)
    elif isinstance(value, dict):
        if '__dns_name__' in value:
            return DNSName(value['__dns_name__'])
        else:
            return dict(
                (k, xml_unwrap(v, encoding)) for (k, v) in value.items()
            )
    elif isinstance(value, Binary):
        assert type(value.data) is bytes
        return value.data
    elif isinstance(value, DateTime):
        # xmlprc DateTime is converted to string of %Y%m%dT%H:%M:%S format
        return datetime.datetime.strptime(str(value), "%Y%m%dT%H:%M:%S")
    raise TypeError(value)
    def _add_base_dns_records_for_server(
            self, zone_obj, hostname, roles=None, include_master_role=True,
            include_kerberos_realm=True,
    ):
        server = self.servers_data[hostname]
        if roles:
            eff_roles = server['roles'] & set(roles)
        else:
            eff_roles = server['roles']
        hostname_abs = DNSName(hostname).make_absolute()

        if include_kerberos_realm:
            self.__add_kerberos_txt_rec(zone_obj)

        # get master records
        if include_master_role:
            self.__add_srv_records(
                zone_obj,
                hostname_abs,
                IPA_DEFAULT_MASTER_SRV_REC,
                weight=server['weight']
            )

        if 'CA server' in eff_roles:
            self.__add_ca_records_from_hostname(zone_obj, hostname_abs)

        if 'AD trust controller' in eff_roles:
            self.__add_srv_records(
                zone_obj,
                hostname_abs,
                IPA_DEFAULT_ADTRUST_SRV_REC,
                weight=server['weight']
            )

        if 'NTP server' in eff_roles:
            self.__add_srv_records(
                zone_obj,
                hostname_abs,
                IPA_DEFAULT_NTP_SRV_REC,
                weight=server['weight']
            )
Ejemplo n.º 5
0
    def match_hostname(self, hostname):
        match_cert = {}

        match_cert['subject'] = match_subject = []
        for rdn in self._cert.subject.rdns:
            match_rdn = []
            for ava in rdn:
                if ava.oid == crypto_x509.oid.NameOID.COMMON_NAME:
                    match_rdn.append(('commonName', ava.value))
            match_subject.append(match_rdn)

        values = self.san_a_label_dns_names
        if values:
            match_cert['subjectAltName'] = match_san = []
            for value in values:
                match_san.append(('DNS', value))

        # deprecated in Python3.7 without replacement
        ssl.match_hostname(  # pylint: disable=deprecated-method
            match_cert, DNSName(hostname).ToASCII()
        )
Ejemplo n.º 6
0
def json_decode_binary(val):
    '''
    JSON cannot transport binary data. In order to transport binary data we
    convert binary data to a form like this:

   {'__base64__' : base64_encoding_of_binary_value}

   see json_encode_binary()

    After JSON had decoded the JSON stream back into a Python object we must
    recursively scan the object looking for any dicts which might represent
    binary values and replace the dict containing the base64 encoding of the
    binary value with the decoded binary value. Unlike the encoding problem
    where the input might consist of immutable object, all JSON decoded
    container are mutable so the conversion could be done in place. However we
    don't modify objects in place because of side effects which may be
    dangerous. Thus we elect to spend a few more cycles and avoid the
    possibility of unintended side effects in favor of robustness.
    '''

    if isinstance(val, dict):
        if '__base64__' in val:
            return base64.b64decode(val['__base64__'])
        elif '__datetime__' in val:
            return datetime.datetime.strptime(val['__datetime__'],
                                              LDAP_GENERALIZED_TIME_FORMAT)
        elif '__dns_name__' in val:
            return DNSName(val['__dns_name__'])
        else:
            return dict((k, json_decode_binary(v)) for k, v in val.items())
    elif isinstance(val, list):
        return tuple(json_decode_binary(v) for v in val)
    else:
        if isinstance(val, basestring):
            try:
                return val.decode('utf-8')
            except UnicodeDecodeError:
                raise ConversionError(name=val, error='incorrect type')
        else:
            return val
Ejemplo n.º 7
0
    def test_adtrust_system_records(self):
        """ Test ADTrust dns records with firstly installing a trust then
        removing the records and using the nsupdate generated by
        dns-update-system-records."""
        self.master.run_command(['ipa-adtrust-install', '-U',
                                 '--enable-compat', '--netbios-name', 'IPA',
                                 '-a', self.master.config.admin_password,
                                 '--add-sids'])
        # lets re-kinit after adtrust-install and restart named
        tasks.kinit_admin(self.master)
        tasks.restart_named(self.master)
        time.sleep(5)
        self.delete_update_system_records(rnames=(r[0] for r in
                                          IPA_DEFAULT_ADTRUST_SRV_REC))

        expected_servers = (
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.master.hostname)),
        )

        for ip in (self.master.ip, self.replicas[0].ip, self.replicas[1].ip):
            self._test_SRV_rec_against_server(
                    ip, self.domain, expected_servers,
                    rec_list=IPA_DEFAULT_ADTRUST_SRV_REC)
Ejemplo n.º 8
0
    def test_nsupdate_without_locations(self):
        """Test nsupdate file generated by dns-update-system-records
        Remove all records and the use nsupdate to restore state and test if
        all record are there as expected"""
        domain = DNSName(self.master.domain.name).make_absolute()
        filepath = '/tmp/ipa.nsupdate'
        self.master.run_command([
            'ipa', 'dns-update-system-records', '--dry-run', '--out', filepath
        ])

        # delete original records first
        for rname, _port in IPA_DEFAULT_MASTER_SRV_REC:
            self.master.run_command([
                'ipa', 'dnsrecord-del', str(domain), str(rname), '--del-all'
            ])

        # allow unauthenticates nsupdate (no need to testing authentication)
        self.master.run_command([
            'ipa', 'dnszone-mod', str(domain),
            '--update-policy=grant * wildcard *;'
        ])
        self.master.run_command(['nsupdate', '-g', filepath])
        time.sleep(5)  # give time to named to process everything from update
        self.test_without_locations()
    def __add_ca_records_from_hostname(self, zone_obj, hostname):
        assert isinstance(hostname, DNSName) and hostname.is_absolute()
        r_name = DNSName('ipa-ca') + self.domain_abs
        rrsets = []
        end_time = time() + 120  # timeout in seconds
        while time() < end_time:
            try:
                rrsets = resolve_rrsets(hostname, (rdatatype.A, rdatatype.AAAA))
            except DNSException:  # logging is done inside resolve_rrsets
                pass
            if rrsets:
                break
            sleep(5)

        if not rrsets:
            root_logger.error('unable to resolve host name %s to IP address, '
                              'ipa-ca DNS record will be incomplete', hostname)
            return

        for rrset in rrsets:
            for rd in rrset:
                rdataset = zone_obj.get_rdataset(
                    r_name, rd.rdtype, create=True)
                rdataset.add(rd, ttl=86400)  # FIXME: use TTL from config
Ejemplo n.º 10
0
 def get_ipa_idnssoamname(self, **kwargs):
     if self.ipa_params.name_server is not None:
         return DNSName(self.ipa_params.name_server)
Ejemplo n.º 11
0
import six
import dns.resolver
import dns.rrset
import dns.rdatatype
import dns.rdataclass

from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_plugins.integration import tasks
from ipapython.dnsutil import DNSName
from ipalib.constants import IPA_CA_RECORD

logger = logging.getLogger(__name__)

IPA_DEFAULT_MASTER_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp'), 389),
    (DNSName(u'_kerberos._tcp'), 88),
    (DNSName(u'_kerberos._udp'), 88),
    (DNSName(u'_kerberos-master._tcp'), 88),
    (DNSName(u'_kerberos-master._udp'), 88),
    (DNSName(u'_kpasswd._tcp'), 464),
    (DNSName(u'_kpasswd._udp'), 464),
)

IPA_DEFAULT_ADTRUST_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs'), 389),
    (DNSName(u'_ldap._tcp.dc._msdcs'), 389),
    (DNSName(u'_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs'), 88),
    (DNSName(u'_kerberos._udp.Default-First-Site-Name._sites.dc._msdcs'), 88),
    (DNSName(u'_kerberos._tcp.dc._msdcs'), 88),
Ejemplo n.º 12
0
 def get_ipa_idnssoamname(self, **_kwargs):  # pylint: disable=R1710
     if self.ipa_params.name_server is not None:
         return DNSName(self.ipa_params.name_server)
Ejemplo n.º 13
0
 def get_ipa_idnssoarname(self, **kwargs):
     if self.ipa_params.admin_email is not None:
         return DNSName(
             self._replace_at_symbol_in_rname(self.ipa_params.admin_email))
Ejemplo n.º 14
0
def validate_zonemgr_str(zonemgr):
    zonemgr = normalize_zonemgr(zonemgr)
    validate_idna_domain(zonemgr)
    zonemgr = DNSName(zonemgr)
    return validate_zonemgr(zonemgr)
Ejemplo n.º 15
0
    def interactive_prompt_callback(self, kw):
        try:
            has_cli_options(self, kw, self.no_option_msg)

            # Some DNS records were entered, do not use full interactive help
            # We should still ask user for required parts of DNS parts he is
            # trying to add in the same way we do for standard LDAP parameters
            #
            # Do not ask for required parts when any "extra" option is used,
            # it can be used to fill all required params by itself
            new_kw = {}
            for rrparam in iterate_rrparams_by_parts(self, kw,
                                                     skip_extra=True):
                rrtype = get_record_rrtype(rrparam.name)
                user_options = prompt_missing_parts(rrtype,
                                                    self,
                                                    kw,
                                                    prompt_optional=False)
                new_kw.update(user_options)
            kw.update(new_kw)
            return
        except errors.OptionError:
            pass

        try:
            idnsname = DNSName(kw['idnsname'])
        except Exception as e:
            raise errors.ValidationError(name='idnsname', error=unicode(e))

        try:
            zonename = DNSName(kw['dnszoneidnsname'])
        except Exception as e:
            raise errors.ValidationError(name='dnszoneidnsname',
                                         error=unicode(e))

        # check zone type
        if idnsname.is_empty():
            common_types = u', '.join(_zone_top_record_types)
        elif zonename.is_reverse():
            common_types = u', '.join(_rev_top_record_types)
        else:
            common_types = u', '.join(_top_record_types)

        self.Backend.textui.print_plain(
            _(u'Please choose a type of DNS resource record to be added'))
        self.Backend.textui.print_plain(_(u'The most common types for this type of zone are: %s\n') %\
                                          common_types)

        ok = False
        while not ok:
            rrtype = self.Backend.textui.prompt(_(u'DNS resource record type'))

            if rrtype is None:
                return

            rrtype = rrtype.upper()

            try:
                name = record_name_format % rrtype.lower()
                param = self.params[name]

                if 'no_option' in param.flags:
                    raise ValueError()
            except (KeyError, ValueError):
                all_types = u', '.join(
                    get_record_rrtype(p.name) for p in self.params() if
                    (get_record_rrtype(p.name) and 'no_option' not in p.flags))
                self.Backend.textui.print_plain(
                    _(u'Invalid or unsupported type. Allowed values are: %s') %
                    all_types)
                continue
            ok = True

        user_options = prompt_parts(rrtype, self)
        kw.update(user_options)
Ejemplo n.º 16
0
def run():
    try:
        check_client_configuration()
    except ScriptError as e:
        print(e.msg)
        return e.rval

    fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
    statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)

    options, _args = parse_options()

    logfile = paths.IPACLIENTSAMBA_INSTALL_LOG
    if options.uninstall:
        logfile = paths.IPACLIENTSAMBA_UNINSTALL_LOG

    standard_logging_setup(
        logfile,
        verbose=False,
        debug=options.debug,
        filemode="a",
        console_format="%(message)s",
    )

    cfg = dict(
        context="cli_installer",
        confdir=paths.ETC_IPA,
        in_server=False,
        debug=options.debug,
        verbose=0,
    )

    # Bootstrap API early so that env object is available
    api.bootstrap(**cfg)

    local_config = dict(
        host_princ=str("host/%s@%s" % (api.env.host, api.env.realm)),
        smb_princ=str("cifs/%s@%s" % (api.env.host, api.env.realm)),
    )

    # Until api.finalize() is called, we can add our own configuration
    api.env._merge(**local_config)

    if options.uninstall:
        if statestore.has_state("domain_member"):
            uninstall(fstore, statestore, options)
            try:
                keys = ("configured", "hardening", "groupmap", "tdb",
                        "service.principal", "smb.conf")
                for key in keys:
                    statestore.delete_state("domain_member", key)
            except Exception as e:
                print("Error: Failed to remove the domain_member statestores: "
                      "%s" % e)
                return 1
            else:
                print("Samba configuration is reverted. "
                      "However, Samba databases were fully cleaned and "
                      "old configuration file will not be usable anymore.")
        else:
            print("Samba domain member is not configured yet")
        return 0

    ca_cert_path = None
    if os.path.exists(paths.IPA_CA_CRT):
        ca_cert_path = paths.IPA_CA_CRT

    if statestore.has_state("domain_member") and not options.force:
        print("Samba domain member is already configured")
        return CLIENT_ALREADY_CONFIGURED

    if not os.path.exists(paths.SMBD):
        print("Samba suite is not installed")
        return CLIENT_NOT_CONFIGURED

    autodiscover = False
    ds = discovery.IPADiscovery()
    if not options.server:
        print("Searching for IPA server...")
        ret = ds.search(ca_cert_path=ca_cert_path)
        logger.debug("Executing DNS discovery")
        if ret == discovery.NO_LDAP_SERVER:
            logger.debug("Autodiscovery did not find LDAP server")
            s = urlsplit(api.env.xmlrpc_uri)
            server = [s.netloc]
            logger.debug("Setting server to %s", s.netloc)
        else:
            autodiscover = True
            if not ds.servers:
                print(
                    "Autodiscovery was successful but didn't return a server")
                return 1
            logger.debug(
                "Autodiscovery success, possible servers %s",
                ",".join(ds.servers),
            )
            server = ds.servers[0]
    else:
        server = options.server
        logger.debug("Verifying that %s is an IPA server", server)
        ldapret = ds.ipacheckldap(server, api.env.realm, ca_cert_path)
        if ldapret[0] == discovery.NO_ACCESS_TO_LDAP:
            print("Anonymous access to the LDAP server is disabled.")
            print("Proceeding without strict verification.")
            print("Note: This is not an error if anonymous access has been "
                  "explicitly restricted.")
        elif ldapret[0] == discovery.NO_TLS_LDAP:
            logger.warning("Unencrypted access to LDAP is not supported.")
        elif ldapret[0] != 0:
            print("Unable to confirm that %s is an IPA server" % server)
            return 1

    if not autodiscover:
        print("IPA server: %s" % server)
        logger.debug("Using fixed server %s", server)
    else:
        print("IPA server: DNS discovery")
        logger.info("Configured to use DNS discovery")

    if api.env.host == server:
        logger.error("Cannot run on IPA master. "
                     "Cannot configure Samba as a domain member on a domain "
                     "controller. Please use ipa-adtrust-install for that!")
        return 1

    if not options.netbiosname:
        options.netbiosname = DNSName.from_text(api.env.host)[0].decode()
    options.netbiosname = options.netbiosname.upper()

    with use_api_as_principal(api.env.host_princ, paths.KRB5_KEYTAB):
        try:
            # Try to access 'service_add_smb' command, if it throws
            # AttributeError exception, the IPA server doesn't support
            # setting up Samba as a domain member.
            service_add_smb = api.Command.service_add_smb

            # Now try to see if SMB principal already exists
            api.Command.service_show(api.env.smb_princ)

            # If no exception was raised, the object exists.
            # We cannot continue because we would break existing configuration
            print("WARNING: SMB service principal %s already exists. "
                  "Please remove it before proceeding." % (api.env.smb_princ))
            if not options.force:
                return 1
            # For --force, we should then delete cifs/.. service object
            api.Command.service_del(api.env.smb_princ)
        except AttributeError:
            logger.error(
                "Chosen IPA master %s does not have support to "
                "set up Samba domain members",
                server,
            )
            return 1
        except errors.VersionError as e:
            print("This client is incompatible: " + str(e))
            return 1
        except errors.NotFound:
            logger.debug("No SMB service principal exists, OK to proceed")
        except errors.PublicError as e:
            logger.error(
                "Cannot connect to the server due to "
                "a generic error: %s",
                e,
            )
            return 1

        # At this point we have proper setup:
        # - we connected to IPA API end-point as a host principal
        # - no cifs/... principal exists so we can create it
        print("Chosen IPA master: %s" % server)
        print("SMB principal to be created: %s" % api.env.smb_princ)
        print("NetBIOS name to be used: %s" % options.netbiosname)
        logger.info("Chosen IPA master: %s", server)
        logger.info("SMB principal to be created: %s", api.env.smb_princ)
        logger.info("NetBIOS name to be used: %s", options.netbiosname)

        # 1. Pull down ID range and other details of known domains
        domains = retrieve_domain_information(api)
        if len(domains) == 0:
            # logger.error() produces both log file and stderr output
            logger.error("No configured trust controller detected "
                         "on IPA masters. Use ipa-adtrust-install on an IPA "
                         "master to configure trust controller role.")
            return 1

        str_info = pretty_print_domain_information(domains)
        logger.info("Discovered domains to use:\n%s", str_info)
        print("Discovered domains to use:\n%s" % str_info)

        if not options.unattended and not ipautil.user_input(
                "Continue to configure the system with these values?", False):
            print("Installation aborted")
            return 1

        # 2. Create SMB service principal, if we are here, the command exists
        if (not statestore.get_state("domain_member", "service.principal")
                or options.force):
            service_add_smb(api.env.host, options.netbiosname)
            statestore.backup_state("domain_member", "service.principal",
                                    "configured")

        # 3. Generate machine account password for reuse
        password = generate_smb_machine_account(fstore, statestore, options,
                                                domains[0])

        # 4. Now that we have all domains retrieved, we can generate smb.conf
        if (not statestore.get_state("domain_member", "smb.conf")
                or options.force):
            configure_smb_conf(fstore, statestore, options, domains)
            statestore.backup_state("domain_member", "smb.conf", "configured")

        # 5. Create SMB service
        if statestore.get_state("domain_member",
                                "service.principal") == "configured":
            retrieve_service_principal(fstore, statestore, options, domains[0],
                                       api.env.smb_princ, password)
            statestore.backup_state("domain_member", "service.principal",
                                    "configured")

        # 6. Configure databases to contain proper details
        if not statestore.get_state("domain_member", "tdb") or options.force:
            populate_samba_databases(fstore, statestore, options, domains[0],
                                     password)
            statestore.backup_state("domain_member", "tdb", "configured")

        # 7. Configure default group mapping
        if (not statestore.get_state("domain_member", "groupmap")
                or options.force):
            configure_default_groupmap(fstore, statestore, options, domains[0])
            statestore.backup_state("domain_member", "groupmap", "configured")

        # 8. Enable SELinux policies
        if (not statestore.get_state("domain_member", "hardening")
                or options.force):
            harden_configuration(fstore, statestore, options, domains[0])
            statestore.backup_state("domain_member", "hardening", "configured")

        # 9. Finally, store the state of upgrade
        statestore.backup_state("domain_member", "configured", True)

        # Suggest service start only after validating smb.conf
        print("Samba domain member is configured. "
              "Please check configuration at %s and "
              "start smb and winbind services" % paths.SMB_CONF)
        logger.info(
            "Samba domain member is configured. "
            "Please check configuration at %s and "
            "start smb and winbind services",
            paths.SMB_CONF,
        )

    return 0
Ejemplo n.º 17
0
 def _get_filename(self, domain):
     basename = DNSName(domain).ToASCII() + '.pem'
     return os.path.join(self._dirname, basename)
Ejemplo n.º 18
0
import pytest
import dns.resolver
import dns.rrset
import dns.rdatatype
import dns.rdataclass

from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks
from ipapython.dnsutil import DNSName, DNSResolver
from ipalib.constants import IPA_CA_RECORD

logger = logging.getLogger(__name__)

IPA_DEFAULT_MASTER_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp'), 389),
    (DNSName(u'_kerberos._tcp'), 88),
    (DNSName(u'_kerberos._udp'), 88),
    (DNSName(u'_kerberos-master._tcp'), 88),
    (DNSName(u'_kerberos-master._udp'), 88),
    (DNSName(u'_kpasswd._tcp'), 464),
    (DNSName(u'_kpasswd._udp'), 464),
)

IPA_DEFAULT_MASTER_URI_REC = (
    (DNSName('_kerberos'), ("krb5srv:m:tcp:{hostname}",
                            "krb5srv:m:udp:{hostname}")),
    (DNSName('_kpasswd'), ("krb5srv:m:tcp:{hostname}",
                           "krb5srv:m:udp:{hostname}")),
)
Ejemplo n.º 19
0
import logging
import time
import dns.resolver
import dns.rrset
import dns.rdatatype
import dns.rdataclass

from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_plugins.integration import tasks
from ipapython.dnsutil import DNSName

logger = logging.getLogger(__name__)

IPA_DEFAULT_MASTER_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp'), 389),
    (DNSName(u'_kerberos._tcp'), 88),
    (DNSName(u'_kerberos._udp'), 88),
    (DNSName(u'_kerberos-master._tcp'), 88),
    (DNSName(u'_kerberos-master._udp'), 88),
    (DNSName(u'_kpasswd._tcp'), 464),
    (DNSName(u'_kpasswd._udp'), 464),
)


def resolve_records_from_server(rname, rtype, nameserver):
    res = dns.resolver.Resolver()
    res.nameservers = [nameserver]
    res.lifetime = 10
    logger.debug("Query: %s %s, nameserver %s", rname, rtype, nameserver)
    ans = res.query(rname, rtype)
Ejemplo n.º 20
0
 def __init__(self, api_instance, all_servers=False):
     self.api_instance = api_instance
     self.domain_abs = DNSName(self.api_instance.env.domain).make_absolute()
     self.servers_data = OrderedDict()
     self.__init_data(all_servers=all_servers)
Ejemplo n.º 21
0
 def __get_location_suffix(self, location):
     return location + DNSName('_locations') + self.domain_abs
Ejemplo n.º 22
0
from time import sleep, time

from ipalib import errors
from ipalib.dns import record_name_format
from ipapython.dnsutil import DNSName
from ipaserver.install import installutils

if six.PY3:
    unicode = str

logger = logging.getLogger(__name__)

IPA_DEFAULT_MASTER_SRV_REC = (
    # srv record name, port
    (DNSName('_ldap._tcp'), 389),
    # Kerberos records are provided for MIT KRB5 < 1.15 and AD
    (DNSName('_kerberos._tcp'), 88),
    (DNSName('_kerberos._udp'), 88),
    (DNSName('_kerberos-master._tcp'), 88),
    (DNSName('_kerberos-master._udp'), 88),
    (DNSName('_kpasswd._tcp'), 464),
    (DNSName('_kpasswd._udp'), 464),
)

IPA_DEFAULT_MASTER_URI_REC = (
    # URI record name, URI template

    # MIT KRB5 1.15+ prefers URI records for service discovery
    # scheme: always krb5srv
    # flags: empty or 'm' for primary server
Ejemplo n.º 23
0
    def interactive_prompt_callback(self, kw):
        try:
            has_cli_options(self, kw, self.no_option_msg)

            # Some DNS records were entered, do not use full interactive help
            # We should still ask user for required parts of DNS parts he is
            # trying to add in the same way we do for standard LDAP parameters
            #
            # Do not ask for required parts when any "extra" option is used,
            # it can be used to fill all required params by itself
            new_kw = {}
            for rrparam in iterate_rrparams_by_parts(self, kw,
                                                     skip_extra=True):
                rrtype = get_record_rrtype(rrparam.name)
                user_options = prompt_missing_parts(rrtype, self, kw,
                                                    prompt_optional=False)
                new_kw.update(user_options)
            kw.update(new_kw)
            return
        except errors.OptionError:
            pass

        try:
            idnsname = DNSName(kw['idnsname'])
        except Exception as e:
            raise errors.ValidationError(name='idnsname', error=unicode(e))

        try:
            zonename = DNSName(kw['dnszoneidnsname'])
        except Exception as e:
            raise errors.ValidationError(name='dnszoneidnsname', error=unicode(e))

        # check zone type
        if idnsname.is_empty():
            common_types = u', '.join(_zone_top_record_types)
        elif zonename.is_reverse():
            common_types = u', '.join(_rev_top_record_types)
        else:
            common_types = u', '.join(_top_record_types)

        self.Backend.textui.print_plain(_(u'Please choose a type of DNS resource record to be added'))
        self.Backend.textui.print_plain(_(u'The most common types for this type of zone are: %s\n') %\
                                          common_types)

        ok = False
        while not ok:
            rrtype = self.Backend.textui.prompt(_(u'DNS resource record type'))

            if rrtype is None:
                return

            rrtype = rrtype.upper()

            try:
                name = record_name_format % rrtype.lower()
                param = self.params[name]

                if 'no_option' in param.flags:
                    raise ValueError()
            except (KeyError, ValueError):
                all_types = u', '.join(get_record_rrtype(p.name)
                                       for p in self.params()
                                       if (get_record_rrtype(p.name) and
                                           'no_option' not in p.flags))
                self.Backend.textui.print_plain(_(u'Invalid or unsupported type. Allowed values are: %s') % all_types)
                continue
            ok = True

        user_options = prompt_parts(rrtype, self)
        kw.update(user_options)
Ejemplo n.º 24
0
class LocationTracker(Tracker):
    """Tracker for IPA Location tests"""
    retrieve_keys = {
        'idnsname', 'description', 'dn', 'servers_server', 'dns_server'
    }
    retrieve_all_keys = retrieve_keys | {'objectclass'}
    create_keys = {'idnsname', 'description', 'dn', 'objectclass'}
    find_keys = {
        'idnsname',
        'description',
        'dn',
    }
    find_all_keys = find_keys | {'objectclass'}
    update_keys = {'idnsname', 'description'}

    def __init__(self, name, description=u"Location description"):
        super(LocationTracker, self).__init__(default_version=None)
        # ugly hack to allow testing invalid inputs
        try:
            self.idnsname_obj = DNSName(name)
        except Exception:
            self.idnsname_obj = DNSName(u"placeholder-for-invalid-value")

        self.idnsname = name
        self.description = description
        self.dn = DN(('idnsname', self.idnsname_obj.ToASCII()), 'cn=locations',
                     'cn=etc', self.api.env.basedn)

        self.servers = {}

    def make_create_command(self):
        """Make function that creates this location using location-add"""
        return self.make_command(
            'location_add',
            self.idnsname,
            description=self.description,
        )

    def make_delete_command(self):
        """Make function that removes this location using location-del"""
        return self.make_command('location_del', self.idnsname)

    def make_retrieve_command(self, all=False, raw=False):
        """Make function that retrieves this location using location-show"""
        return self.make_command('location_show',
                                 self.idnsname,
                                 all=all,
                                 raw=raw)

    def make_find_command(self, *args, **kwargs):
        """Make function that finds locations using location-find"""
        return self.make_command('location_find', *args, **kwargs)

    def make_update_command(self, updates):
        """Make function that modifies the location using location-mod"""
        return self.make_command('location_mod', self.idnsname, **updates)

    def track_create(self):
        """Update expected state for location creation"""

        self.attrs = dict(
            dn=self.dn,
            idnsname=[self.idnsname_obj],
            description=[self.description],
            objectclass=[u'top', u'ipaLocationObject'],
        )
        self.exists = True

    def check_create(self, result):
        """Check `location-add` command result"""
        assert_deepequal(
            dict(value=self.idnsname_obj,
                 summary=u'Added IPA location "{loc}"'.format(
                     loc=self.idnsname),
                 result=self.filter_attrs(self.create_keys)), result)

    def check_delete(self, result):
        """Check `location-del` command result"""
        assert_deepequal(
            dict(
                value=[self.idnsname_obj],
                summary=u'Deleted IPA location "{loc}"'.format(
                    loc=self.idnsname),
                result=dict(failed=[]),
            ), result)

    def check_retrieve(self, result, all=False, raw=False):
        """Check `location-show` command result"""
        if all:
            expected = self.filter_attrs(self.retrieve_all_keys)
        else:
            expected = self.filter_attrs(self.retrieve_keys)
        assert_deepequal(
            dict(
                value=self.idnsname_obj,
                summary=None,
                result=expected,
                servers=self.servers,
            ), result)

    def check_find(self, result, all=False, raw=False):
        """Check `location-find` command result"""
        if all:
            expected = self.filter_attrs(self.find_all_keys)
        else:
            expected = self.filter_attrs(self.find_keys)
        assert_deepequal(
            dict(
                count=1,
                truncated=False,
                summary=u'1 IPA location matched',
                result=[expected],
            ), result)

    def check_update(self, result, extra_keys=()):
        """Check `location-update` command result"""
        assert_deepequal(
            dict(value=self.idnsname_obj,
                 summary=u'Modified IPA location "{loc}"'.format(
                     loc=self.idnsname),
                 result=self.filter_attrs(self.update_keys | set(extra_keys))),
            result)

    def add_server_to_location(self,
                               server_name,
                               weight=100,
                               relative_weight=u"100.0%"):
        self.attrs.setdefault('servers_server', []).append(server_name)
        self.attrs.setdefault('dns_server', []).append(server_name)
        self.servers[server_name] = {
            'cn': [server_name],
            'ipaserviceweight': [unicode(weight)],
            'service_relative_weight': [relative_weight],
            'enabled_role_servrole': lambda other: True
        }

    def remove_server_from_location(self, server_name):
        if 'servers_server' in self.attrs:
            try:
                self.attrs['servers_server'].remove(server_name)
                self.attrs['dns_server'].remove(server_name)
            except ValueError:
                pass
            else:
                if not self.attrs['servers_server']:
                    del self.attrs['servers_server']
                if not self.attrs['dns_server']:
                    del self.attrs['dns_server']
        try:
            del self.servers[server_name]
        except KeyError:
            pass
Ejemplo n.º 25
0
    def test_two_replicas_in_location(self):
        """Put second replica to location and test if records changed properly
        """

        # create location paris, replica1 --> location prague
        self.master.run_command(['ipa', 'location-add', self.LOC_PARIS])
        self.master.run_command([
            'ipa', 'server-mod', self.replicas[1].hostname, '--location',
            self.LOC_PARIS
        ])
        tasks.restart_named(self.replicas[1])

        servers_without_loc = (
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.master.hostname)),
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.replicas[0].hostname)),
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.replicas[1].hostname)),
        )
        domain_without_loc = DNSName(self.master.domain.name).make_absolute()

        servers_prague_loc = (
            (self.PRIO_LOW, self.WEIGHT, DNSName(self.master.hostname)),
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.replicas[0].hostname)),
            (self.PRIO_LOW, self.WEIGHT, DNSName(self.replicas[1].hostname)),
        )
        domain_prague_loc = (DNSName('{}._locations'.format(self.LOC_PRAGUE)) +
                             DNSName(self.master.domain.name).make_absolute())

        servers_paris_loc = (
            (self.PRIO_LOW, self.WEIGHT, DNSName(self.master.hostname)),
            (self.PRIO_LOW, self.WEIGHT, DNSName(self.replicas[0].hostname)),
            (self.PRIO_HIGH, self.WEIGHT, DNSName(self.replicas[1].hostname)),
        )
        domain_paris_loc = (DNSName('{}._locations'.format(self.LOC_PARIS)) +
                            DNSName(self.master.domain.name).make_absolute())

        self._test_against_server(self.replicas[0].ip, domain_prague_loc,
                                  servers_prague_loc)

        self._test_against_server(self.replicas[1].ip, domain_paris_loc,
                                  servers_paris_loc)

        self._test_against_server(self.master.ip, domain_without_loc,
                                  servers_without_loc)
Ejemplo n.º 26
0
 def get_ipa_idnssoarname(self, **_kwargs):  # pylint: disable=R1710
     if self.ipa_params.admin_email is not None:
         return DNSName(
             self._replace_at_symbol_in_rname(self.ipa_params.admin_email))
Ejemplo n.º 27
0
    def __setup_replica_keys(self):
        keylabel = replica_keylabel_template % DNSName(self.fqdn).\
            make_absolute().canonicalize().ToASCII()

        ldap = api.Backend.ldap2
        dn_base = DN(('cn', 'keys'), ('cn', 'sec'), ('cn', 'dns'),
                     api.env.basedn)

        with open(paths.DNSSEC_SOFTHSM_PIN, "r") as f:
            pin = f.read()

        os.environ["SOFTHSM2_CONF"] = paths.DNSSEC_SOFTHSM2_CONF
        p11 = _ipap11helper.P11_Helper(SOFTHSM_DNSSEC_TOKEN_LABEL, pin,
                                       paths.LIBSOFTHSM2_SO)

        try:
            # generate replica keypair
            logger.debug("Creating replica's key pair")
            key_id = None
            while True:
                # check if key with this ID exist in softHSM
                key_id = _ipap11helper.gen_key_id()
                replica_pubkey_dn = DN(('ipk11UniqueId', 'autogenerate'),
                                       dn_base)

                pub_keys = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY,
                                         label=keylabel,
                                         id=key_id)
                if pub_keys:
                    # key with id exists
                    continue

                priv_keys = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY,
                                          label=keylabel,
                                          id=key_id)
                if not priv_keys:
                    break  # we found unique id

            public_key_handle, _privkey_handle = p11.generate_replica_key_pair(
                keylabel,
                key_id,
                pub_cka_verify=False,
                pub_cka_verify_recover=False,
                pub_cka_wrap=True,
                priv_cka_unwrap=True,
                priv_cka_sensitive=True,
                priv_cka_extractable=False)

            # export public key
            public_key_blob = p11.export_public_key(public_key_handle)

            # save key to LDAP
            replica_pubkey_objectclass = [
                'ipk11Object', 'ipk11PublicKey', 'ipaPublicKeyObject', 'top'
            ]
            kw = {
                'objectclass': replica_pubkey_objectclass,
                'ipk11UniqueId': [u'autogenerate'],
                'ipk11Label': [keylabel],
                'ipaPublicKey': [public_key_blob],
                'ipk11Id': [key_id],
                'ipk11Wrap': [True],
                'ipk11Verify': [False],
                'ipk11VerifyRecover': [False],
            }

            logger.debug("Storing replica public key to LDAP, %s",
                         replica_pubkey_dn)

            entry = ldap.make_entry(replica_pubkey_dn, **kw)
            ldap.add_entry(entry)
            logger.debug("Replica public key stored")

            logger.debug("Setting CKA_WRAP=False for old replica keys")
            # first create new keys, we don't want disable keys before, we
            # have new keys in softhsm and LDAP

            # get replica pub keys with CKA_WRAP=True
            replica_pub_keys = p11.find_keys(
                _ipap11helper.KEY_CLASS_PUBLIC_KEY,
                label=keylabel,
                cka_wrap=True)
            # old keys in softHSM
            for handle in replica_pub_keys:
                # don't disable wrapping for new key
                # compare IDs not handle
                if key_id != p11.get_attribute(handle, _ipap11helper.CKA_ID):
                    p11.set_attribute(handle, _ipap11helper.CKA_WRAP, False)

            # get old keys from LDAP
            search_kw = {
                'objectclass': u"ipaPublicKeyObject",
                'ipk11Label': keylabel,
                'ipk11Wrap': True,
            }
            filter = ldap.make_filter(search_kw, rules=ldap.MATCH_ALL)
            entries, _truncated = ldap.find_entries(filter=filter,
                                                    base_dn=dn_base)
            for entry in entries:
                # don't disable wrapping for new key
                if entry.single_value['ipk11Id'] != key_id:
                    entry['ipk11Wrap'] = [False]
                    ldap.update_entry(entry)

        finally:
            p11.finalize()

        # change tokens mod/owner
        logger.debug("Changing ownership of token files")
        for (root, dirs, files) in os.walk(paths.DNSSEC_TOKENS_DIR):
            for directory in dirs:
                dir_path = os.path.join(root, directory)
                os.chmod(dir_path, 0o770 | stat.S_ISGID)
                # chown to ods:named
                os.chown(dir_path, self.ods_uid, self.named_gid)
            for filename in files:
                file_path = os.path.join(root, filename)
                os.chmod(file_path, 0o770 | stat.S_ISGID)
                # chown to ods:named
                os.chown(file_path, self.ods_uid, self.named_gid)
Ejemplo n.º 28
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
                     **options):
        assert isinstance(dn, DN)
        hostname = keys[0]
        if len(keys) == 2:
            netbiosname = keys[1]
        else:
            # By default take leftmost label from the host name
            netbiosname = DNSName.from_text(hostname)[0].decode().upper()

        # SMB service requires existence of the host object
        # because DCE RPC calls authenticated with GSSAPI are using
        # host/.. principal by default for validation
        try:
            hostresult = self.api.Command['host_show'](hostname)['result']
        except errors.NotFound:
            raise errors.NotFound(
                reason=_("The host '%s' does not exist to add a service to.") %
                hostname)

        # We cannot afford the host not being resolvable even for
        # clustered environments with CTDB because the target name
        # has to exist even in that case
        util.verify_host_resolvable(hostname)

        smbaccount = '{name}$'.format(name=netbiosname)
        smbprincipal = 'cifs/{hostname}'.format(hostname=hostname)

        entry_attrs['krbprincipalname'] = [
            str(kerberos.Principal(smbprincipal, realm=self.api.env.realm)),
            str(kerberos.Principal(smbaccount, realm=self.api.env.realm))
        ]

        entry_attrs['krbcanonicalname'] = entry_attrs['krbprincipalname'][0]

        # Rewrite DN using proper rdn and new canonical name because when
        # LDAPCreate.execute() was called, it set DN to krbcanonicalname=$value
        dn = DN(('krbprincipalname', entry_attrs['krbcanonicalname']),
                DN(self.obj.container_dn, api.env.basedn))

        # Enforce ipaKrbPrincipalAlias to aid case-insensitive searches as
        # krbPrincipalName/krbCanonicalName are case-sensitive in Kerberos
        # schema
        entry_attrs['ipakrbprincipalalias'] = entry_attrs['krbcanonicalname']

        for o in ('ipakrbprincipal', 'ipaidobject', 'krbprincipalaux',
                  'posixaccount'):
            if o not in entry_attrs['objectclass']:
                entry_attrs['objectclass'].append(o)

        entry_attrs['uid'] = [
            '/'.join(kerberos.Principal(smbprincipal).components)
        ]
        entry_attrs['uid'].append(smbaccount)
        entry_attrs['cn'] = netbiosname
        entry_attrs['homeDirectory'] = '/dev/null'
        entry_attrs['uidNumber'] = DNA_MAGIC
        entry_attrs['gidNumber'] = DNA_MAGIC

        self.obj.validate_ipakrbauthzdata(entry_attrs)

        if 'managedby' not in entry_attrs:
            entry_attrs['managedby'] = hostresult['dn']

        update_krbticketflags(ldap, entry_attrs, attrs_list, options, False)

        return dn
Ejemplo n.º 29
0
                                              fuzzy_hex, raises_exact)
from ipatests.test_xmlrpc.test_user_plugin import get_group_dn
from ipatests.test_xmlrpc import objectclasses
from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker
from ipatests.test_xmlrpc.testcert import get_testcert, subject_base
from ipatests.util import assert_deepequal
from ipaplatform.paths import paths

# Constants DNS integration tests
# TODO: Use tracker fixtures for zones/records/users/groups
dnszone = u'test-zone.test'
dnszone_absolute = dnszone + '.'
dnszone_dn = DN(('idnsname', dnszone_absolute), api.env.container_dns,
                api.env.basedn)
dnszone_rname = u'root.%s' % dnszone_absolute
dnszone_rname_dnsname = DNSName(dnszone_rname)

revzone = u'29.16.172.in-addr.arpa.'
revzone_dn = DN(('idnsname', revzone), api.env.container_dns, api.env.basedn)

revipv6zone = u'0.0.0.0.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.'
revipv6zone_dn = DN(('idnsname', revipv6zone), api.env.container_dns,
                    api.env.basedn)

arec = u'172.16.29.22'
aaaarec = u'2001:db8:1::beef'

arec2 = u'172.16.29.33'
aaaarec2 = u'2001:db8:1::dead'

ipv4_fromip = u'testipv4fromip'
from dns.exception import DNSException

from time import sleep, time

from ipalib import errors
from ipalib.dns import record_name_format
from ipapython.dnsutil import DNSName, resolve_rrsets
from ipapython.ipa_log_manager import root_logger

if six.PY3:
    unicode=str


IPA_DEFAULT_MASTER_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp'), 389),
    (DNSName(u'_kerberos._tcp'), 88),
    (DNSName(u'_kerberos._udp'), 88),
    (DNSName(u'_kerberos-master._tcp'), 88),
    (DNSName(u'_kerberos-master._udp'), 88),
    (DNSName(u'_kpasswd._tcp'), 464),
    (DNSName(u'_kpasswd._udp'), 464),
)

IPA_DEFAULT_ADTRUST_SRV_REC = (
    # srv record name, port
    (DNSName(u'_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs'), 389),
    (DNSName(u'_ldap._tcp.dc._msdcs'), 389),
    (DNSName(u'_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs'), 88),
    (DNSName(u'_kerberos._udp.Default-First-Site-Name._sites.dc._msdcs'), 88),
    (DNSName(u'_kerberos._tcp.dc._msdcs'), 88),
Ejemplo n.º 31
0
def zone_is_reverse(zone_name):
    return DNSName(zone_name).is_reverse()
 def __init__(self, api_instance):
     self.api_instance = api_instance
     self.domain_abs = DNSName(self.api_instance.env.domain).make_absolute()
     self.servers_data = {}
     self.__init_data()