Ejemplo n.º 1
0
def run(api):
    error = None
    try:
        (_options, argv) = api.bootstrap_with_global_options(context='cli')

        try:
            check_client_configuration()
        except ScriptError as e:
            sys.exit(e)

        for klass in cli_plugins:
            api.add_plugin(klass)
        api.finalize()
        if not 'config_loaded' in api.env and not 'help' in argv:
            raise NotConfiguredError()
        sys.exit(api.Backend.cli.run(argv))
    except KeyboardInterrupt:
        print('')
        logger.info('operation aborted')
    except PublicError as e:
        error = e
    except Exception as e:
        logger.exception('%s: %s', e.__class__.__name__, str(e))
        error = InternalError()
    if error is not None:
        assert isinstance(error, PublicError)
        logger.error(error.strerror)
        sys.exit(error.rval)
Ejemplo n.º 2
0
def run(api):
    error = None
    try:
        (_options, argv) = api.bootstrap_with_global_options(context='cli')

        try:
            check_client_configuration()
        except ScriptError as e:
            sys.exit(e)

        for klass in cli_plugins:
            api.add_plugin(klass)
        api.finalize()
        if not 'config_loaded' in api.env and not 'help' in argv:
            raise NotConfiguredError()
        sys.exit(api.Backend.cli.run(argv))
    except KeyboardInterrupt:
        print('')
        logger.info('operation aborted')
    except PublicError as e:
        error = e
    except Exception as e:
        logger.exception('%s: %s', e.__class__.__name__, str(e))
        error = InternalError()
    if error is not None:
        assert isinstance(error, PublicError)
        logger.error(error.strerror)
        sys.exit(error.rval)
Ejemplo n.º 3
0
    def run(self):
        check_client_configuration()

        old_krb5ccname = os.environ.get('KRB5CCNAME')
        os.environ['KRB5_CLIENT_KTNAME'] = '/etc/krb5.keytab'
        os.environ['KRB5CCNAME'] = "MEMORY:"

        try:
            api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA)
            api.finalize()

            api.Backend.rpcclient.connect()
            run_with_args(api)
            api.Backend.rpcclient.disconnect()
        except errors.CCacheError:
            logger.error(
                "Unable to obtain credentials for %s from /etc/krb5.keytab",
                FQDN
            )
            raise
        finally:
            if old_krb5ccname is None:
                del os.environ['KRB5CCNAME']
            else:
                os.environ['KRB5CCNAME'] = old_krb5ccname
Ejemplo n.º 4
0
    def run(self):
        check_client_configuration()

        api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA)
        api.finalize()

        server = urlsplit(api.env.jsonrpc_uri).hostname
        ldap_uri = ipaldap.get_ldap_uri(server)
        ldap = ipaldap.LDAPClient(ldap_uri)

        tmpdir = tempfile.mkdtemp(prefix="tmp-")
        ccache_name = os.path.join(tmpdir, 'ccache')
        try:
            principal = str('host/%s@%s' % (api.env.host, api.env.realm))
            kinit_keytab(principal, paths.KRB5_KEYTAB, ccache_name)
            os.environ['KRB5CCNAME'] = ccache_name

            api.Backend.rpcclient.connect()
            try:
                result = api.Backend.rpcclient.forward(
                    'ca_is_enabled',
                    version=u'2.107',
                )
                ca_enabled = result['result']
            except (errors.CommandError, errors.NetworkError):
                result = api.Backend.rpcclient.forward(
                    'env',
                    server=True,
                    version=u'2.0',
                )
                ca_enabled = result['result']['enable_ra']

            ldap.gssapi_bind()

            certs = certstore.get_ca_certs(ldap, api.env.basedn, api.env.realm,
                                           ca_enabled)

            if ca_enabled:
                lwcas = api.Command.ca_find()['result']
            else:
                lwcas = []

            api.Backend.rpcclient.disconnect()
        finally:
            shutil.rmtree(tmpdir)

        server_fstore = sysrestore.FileStore(paths.SYSRESTORE)
        if server_fstore.has_files():
            self.update_server(certs)
            try:
                # pylint: disable=import-error,ipa-forbidden-import
                from ipaserver.install import cainstance
                # pylint: enable=import-error,ipa-forbidden-import
                cainstance.add_lightweight_ca_tracking_requests(lwcas)
            except Exception:
                logger.exception(
                    "Failed to add lightweight CA tracking requests")

        self.update_client(certs)
Ejemplo n.º 5
0
    def run(self):
        check_client_configuration()

        api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA)
        api.finalize()

        api.Backend.rpcclient.connect()
        run_with_args(api)
        api.Backend.rpcclient.disconnect()
Ejemplo n.º 6
0
    def run(self):
        check_client_configuration()

        api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA)
        api.finalize()

        api.Backend.rpcclient.connect()
        run_with_args(api)
        api.Backend.rpcclient.disconnect()
Ejemplo n.º 7
0
    def run(self):
        check_client_configuration()

        old_krb5ccname = os.environ.get('KRB5CCNAME')
        os.environ['KRB5_CLIENT_KTNAME'] = '/etc/krb5.keytab'
        os.environ['KRB5CCNAME'] = "MEMORY:"

        try:
            api.bootstrap(context='cli_installer', confdir=paths.ETC_IPA)
            api.finalize()

            api.Backend.rpcclient.connect()
            run_with_args(api)
            api.Backend.rpcclient.disconnect()
        finally:
            if old_krb5ccname is None:
                del os.environ['KRB5CCNAME']
            else:
                os.environ['KRB5CCNAME'] = old_krb5ccname
Ejemplo n.º 8
0
def configure_automount():
    try:
        check_client_configuration()
    except ScriptError as e:
        print(e.msg)
        sys.exit(e.rval)

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

    options, _args = parse_options()

    standard_logging_setup(
        paths.IPACLIENT_INSTALL_LOG,
        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)

    if options.uninstall:
        return uninstall(fstore, statestore)

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

    if statestore.has_state('autofs'):
        print('An automount location is already configured')
        sys.exit(CLIENT_ALREADY_CONFIGURED)

    autodiscover = False
    ds = ipadiscovery.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 == ipadiscovery.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:
                sys.exit(
                    'Autodiscovery was successful but didn\'t return a server'
                )
            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] == ipadiscovery.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] == ipadiscovery.NO_TLS_LDAP:
            logger.warning("Unencrypted access to LDAP is not supported.")
        elif ldapret[0] != 0:
            sys.exit('Unable to confirm that %s is an IPA server' % server)

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

    print("Location: %s" % options.location)
    logger.debug('Using automount location %s', options.location)

    ccache_dir = tempfile.mkdtemp()
    ccache_name = os.path.join(ccache_dir, 'ccache')
    try:
        try:
            host_princ = str('host/%s@%s' % (api.env.host, api.env.realm))
            kinit_keytab(host_princ, paths.KRB5_KEYTAB, ccache_name)
            os.environ['KRB5CCNAME'] = ccache_name
        except gssapi.exceptions.GSSError as e:
            sys.exit("Failed to obtain host TGT: %s" % e)

        # Finalize API when TGT obtained using host keytab exists
        api.finalize()

        # Now we have a TGT, connect to IPA
        try:
            api.Backend.rpcclient.connect()
        except errors.KerberosError as e:
            sys.exit('Cannot connect to the server due to ' + str(e))
        try:
            # Use the RPC directly so older servers are supported
            api.Backend.rpcclient.forward(
                'automountlocation_show',
                ipautil.fsdecode(options.location),
                version=u'2.0',
            )
        except errors.VersionError as e:
            sys.exit('This client is incompatible: ' + str(e))
        except errors.NotFound:
            sys.exit(
                "Automount location '%s' does not exist" % options.location
            )
        except errors.PublicError as e:
            sys.exit(
                "Cannot connect to the server due to generic error: %s"
                % str(e)
            )
    finally:
        shutil.rmtree(ccache_dir)

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

    try:
        if not options.sssd:
            tasks.enable_ldap_automount(statestore)
        configure_nfs(fstore, statestore, options)
        if options.sssd:
            configure_autofs_sssd(fstore, statestore, autodiscover, options)
        else:
            configure_xml(fstore)
            configure_autofs(
                fstore, statestore, autodiscover, server, options
            )
        configure_autofs_common(fstore, statestore, options)
    except Exception as e:
        logger.debug('Raised exception %s', e)
        print("Installation failed. Rolling back changes.")
        uninstall(fstore, statestore)
        return 1

    return 0
Ejemplo n.º 9
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