Exemple #1
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
                     **options):
        assert isinstance(dn, DN)
        associateddomain = entry_attrs.get('associateddomain')
        add_domain = entry_attrs.get('add_domain')
        del_domain = entry_attrs.get('del_domain')
        force = options.get('force')

        if associateddomain:
            if add_domain or del_domain:
                raise errors.MutuallyExclusiveError(reason=_(
                    "you cannot specify the --domain option together with --add-domain or --del-domain"
                ))
            if get_domain_name() not in associateddomain:
                raise errors.ValidationError(
                    name='domain',
                    error=_("cannot delete domain of IPA server"))
            if not force:
                bad_domains = [
                    d for d in associateddomain if not has_soa_or_ns_record(d)
                ]
                if bad_domains:
                    bad_domains = ', '.join(bad_domains)
                    raise errors.ValidationError(
                        name='domain',
                        error=_("no SOA or NS records found for domains: %s" %
                                bad_domains))
            return dn

        # If --add-domain or --del-domain options were provided, read
        # the curent list from LDAP, modify it, and write the changes back
        domains = ldap.get_entry(dn)['associateddomain']

        if add_domain:
            if not force and not has_soa_or_ns_record(add_domain):
                raise errors.ValidationError(
                    name='add_domain',
                    error=_("no SOA or NS records found for domain %s" %
                            add_domain))
            del entry_attrs['add_domain']
            domains.append(add_domain)

        if del_domain:
            if del_domain == get_domain_name():
                raise errors.ValidationError(
                    name='del_domain',
                    error=_("cannot delete domain of IPA server"))
            del entry_attrs['del_domain']
            try:
                domains.remove(del_domain)
            except ValueError:
                raise errors.AttrValueNotFound(attr='associateddomain',
                                               value=del_domain)

        entry_attrs['associateddomain'] = domains
        return dn
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys,
                     **options):
        assert isinstance(dn, DN)
        associateddomain = entry_attrs.get('associateddomain')
        add_domain = entry_attrs.get('add_domain')
        del_domain = entry_attrs.get('del_domain')
        force = options.get('force')

        current_domain = get_domain_name()

        # User specified the list of domains explicitly
        if associateddomain:
            if add_domain or del_domain:
                raise errors.MutuallyExclusiveError(reason=_(
                    "The --domain option cannot be used together "
                    "with --add-domain or --del-domain. Use --domain "
                    "to specify the whole realm domain list explicitly, "
                    "to add/remove individual domains, use "
                    "--add-domain/del-domain."))

            # Make sure our domain is included in the list
            if current_domain not in associateddomain:
                raise errors.ValidationError(
                    name='realmdomain list',
                    error=_("IPA server domain cannot be omitted"))

            # Validate that each domain satisfies the requirements
            # for realmdomain
            self.validate_domains(domains=associateddomain, force=force)

            return dn

        # If --add-domain or --del-domain options were provided, read
        # the curent list from LDAP, modify it, and write the changes back
        domains = ldap.get_entry(dn)['associateddomain']

        if add_domain:
            self.validate_domains(domains=[add_domain], force=force)
            del entry_attrs['add_domain']
            domains.append(add_domain)

        if del_domain:
            if del_domain == current_domain:
                raise errors.ValidationError(
                    name='del_domain',
                    error=_("IPA server domain cannot be deleted"))
            del entry_attrs['del_domain']

            try:
                domains.remove(del_domain)
            except ValueError:
                raise errors.AttrValueNotFound(attr='associateddomain',
                                               value=del_domain)

        entry_attrs['associateddomain'] = domains
        return dn
Exemple #3
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        assert isinstance(dn, DN)
        associateddomain = entry_attrs.get('associateddomain')
        add_domain = entry_attrs.get('add_domain')
        del_domain = entry_attrs.get('del_domain')
        force = options.get('force')

        if associateddomain:
            if add_domain or del_domain:
                raise errors.MutuallyExclusiveError(reason=_("you cannot specify the --domain option together with --add-domain or --del-domain"))
            if get_domain_name() not in associateddomain:
                raise errors.ValidationError(name='domain', error=_("cannot delete domain of IPA server"))
            if not force:
                bad_domains = [d for d in associateddomain if not has_soa_or_ns_record(d)]
                if bad_domains:
                    bad_domains = ', '.join(bad_domains)
                    raise errors.ValidationError(name='domain', error=_("no SOA or NS records found for domains: %s" % bad_domains))
            return dn

        # If --add-domain or --del-domain options were provided, read
        # the curent list from LDAP, modify it, and write the changes back
        domains = ldap.get_entry(dn)['associateddomain']

        if add_domain:
            if not force and not has_soa_or_ns_record(add_domain):
                raise errors.ValidationError(name='add_domain', error=_("no SOA or NS records found for domain %s" % add_domain))
            del entry_attrs['add_domain']
            domains.append(add_domain)

        if del_domain:
            if del_domain == get_domain_name():
                raise errors.ValidationError(name='del_domain', error=_("cannot delete domain of IPA server"))
            del entry_attrs['del_domain']
            try:
                domains.remove(del_domain)
            except ValueError:
                raise errors.AttrValueNotFound(attr='associateddomain', value=del_domain)

        entry_attrs['associateddomain'] = domains
        return dn
Exemple #4
0
    def __init__(self, dm_password=None, sub_dict={},
                 online=True, ldapi=False):
        '''
        :parameters:
            dm_password
                Directory Manager password
            sub_dict
                substitution dictionary
            online
                Do an online LDAP update or use an experimental LDIF updater
            ldapi
                Bind using ldapi. This assumes autobind is enabled.

        Data Structure Example:
        -----------------------

        dn_by_rdn_count = {
            3: 'cn=config,dc=example,dc=com':
            4: 'cn=bob,ou=people,dc=example,dc=com',
        }

        all_updates = [
            {
                'dn': 'cn=config,dc=example,dc=com',
                'default': [
                    dict(attr='attr1', value='default1'),
                ],
                'updates': [
                    dict(action='action', attr='attr1', value='value1'),
                    dict(action='replace', attr='attr2', value=['old', 'new']),
                ]
            },
            {
                'dn': 'cn=bob,ou=people,dc=example,dc=com',
                'default': [
                    dict(attr='attr3', value='default3'),
                ],
                'updates': [
                    dict(action='action', attr='attr3', value='value3'),
                    dict(action='action', attr='attr4', value='value4'),
                }
            }
        ]

        Please notice the replace action requires two values in list

        The default and update lists are "dispositions"

        Plugins:

        Plugins has to be specified in update file to be executed, using
        'plugin' directive

        Example:
        plugin: update_uniqueness_plugins_to_new_syntax

        Each plugin returns two values:

        1. restart: dirsrv will be restarted AFTER this update is
                     applied.
        2. updates: A list of updates to be applied.

        The value of an update is a dictionary with the following possible
        values:
          - dn: DN, equal to the dn attribute
          - updates: list of updates against the dn
          - default: list of the default entry to be added if it doesn't
                     exist
          - deleteentry: list of dn's to be deleted (typically single dn)

        For example, this update file:

          dn: cn=global_policy,cn=$REALM,cn=kerberos,$SUFFIX
          replace:krbPwdLockoutDuration:10::600
          replace: krbPwdMaxFailure:3::6

        Generates this list which contain the update dictionary:

        [
          {
            'dn': 'cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com',
            'updates': [
              dict(action='replace', attr='krbPwdLockoutDuration',
                   value=['10','600']),
              dict(action='replace', attr='krbPwdMaxFailure',
                   value=['3','6']),
            ]
          }
        ]

        Here is another example showing how a default entry is configured:

          dn: cn=Managed Entries,cn=etc,$SUFFIX
          default: objectClass: nsContainer
          default: objectClass: top
          default: cn: Managed Entries

        This generates:

        [
          {
            'dn': 'cn=Managed Entries,cn=etc,dc=example,dc=com',
            'default': [
              dict(attr='objectClass', value='nsContainer'),
              dict(attr='objectClass', value='top'),
              dict(attr='cn', value='Managed Entries'),
            ]
          }
        ]

        Note that the variable substitution in both examples has been completed.

        Either may make changes directly in LDAP or can return updates in
        update format.

        '''
        log_mgr.get_logger(self, True)
        self.sub_dict = sub_dict
        self.dm_password = dm_password
        self.conn = None
        self.modified = False
        self.online = online
        self.ldapi = ldapi
        self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
        self.realm = None
        self.socket_name = (
            paths.SLAPD_INSTANCE_SOCKET_TEMPLATE %
            api.env.realm.replace('.', '-')
        )
        self.ldapuri = 'ldapi://%s' % ipautil.format_netloc(
            self.socket_name
        )
        suffix = None

        if sub_dict.get("REALM"):
            self.realm = sub_dict["REALM"]
        else:
            self.realm = api.env.realm
            suffix = ipautil.realm_to_suffix(self.realm) if self.realm else None

        if suffix is not None:
            assert isinstance(suffix, DN)
        domain = ipautil.get_domain_name()
        libarch = self._identify_arch()

        fqdn = installutils.get_fqdn()
        if fqdn is None:
            raise RuntimeError("Unable to determine hostname")

        if not self.sub_dict.get("REALM") and self.realm is not None:
            self.sub_dict["REALM"] = self.realm
        if not self.sub_dict.get("FQDN"):
            self.sub_dict["FQDN"] = fqdn
        if not self.sub_dict.get("DOMAIN"):
            self.sub_dict["DOMAIN"] = domain
        if not self.sub_dict.get("SUFFIX") and suffix is not None:
            self.sub_dict["SUFFIX"] = suffix
        if not self.sub_dict.get("ESCAPED_SUFFIX"):
            self.sub_dict["ESCAPED_SUFFIX"] = str(suffix)
        if not self.sub_dict.get("LIBARCH"):
            self.sub_dict["LIBARCH"] = libarch
        if not self.sub_dict.get("TIME"):
            self.sub_dict["TIME"] = int(time.time())
        if not self.sub_dict.get("DOMAIN") and domain is not None:
            self.sub_dict["DOMAIN"] = domain
        if not self.sub_dict.get("MIN_DOMAIN_LEVEL"):
            self.sub_dict["MIN_DOMAIN_LEVEL"] = str(constants.MIN_DOMAIN_LEVEL)
        if not self.sub_dict.get("MAX_DOMAIN_LEVEL"):
            self.sub_dict["MAX_DOMAIN_LEVEL"] = str(constants.MAX_DOMAIN_LEVEL)
        if not self.sub_dict.get("STRIP_ATTRS"):
            self.sub_dict["STRIP_ATTRS"] = "%s" % (
                " ".join(constants.REPL_AGMT_STRIP_ATTRS),)
        if not self.sub_dict.get("EXCLUDES"):
            self.sub_dict["EXCLUDES"] = "(objectclass=*) $ EXCLUDE %s" % (
                " ".join(constants.REPL_AGMT_EXCLUDES),)
        if not self.sub_dict.get("TOTAL_EXCLUDES"):
            self.sub_dict["TOTAL_EXCLUDES"] = "(objectclass=*) $ EXCLUDE " + \
                " ".join(constants.REPL_AGMT_TOTAL_EXCLUDES)
        self.api = create_api(mode=None)
        self.api.bootstrap(in_server=True, context='updates')
        self.api.finalize()
        if online:
            # Try out the connection/password
            # (This will raise if the server is not available)
            self.create_connection()
            self.close_connection()
        else:
            raise RuntimeError("Offline updates are not supported.")
Exemple #5
0
    def __init__(self,
                 dm_password,
                 sub_dict={},
                 live_run=True,
                 online=True,
                 ldapi=False,
                 plugins=False):
        '''
        :parameters:
            dm_password
                Directory Manager password
            sub_dict
                substitution dictionary
            live_run
                Apply the changes or just test
            online
                Do an online LDAP update or use an experimental LDIF updater
            ldapi
                Bind using ldapi. This assumes autobind is enabled.
            plugins
                execute the pre/post update plugins

        Data Structure Example:
        -----------------------

        dn_by_rdn_count = {
            3: 'cn=config,dc=example,dc=com':
            4: 'cn=bob,ou=people,dc=example,dc=com',
        }

        all_updates = {
        'dn': 'cn=config,dc=example,dc=com':
            {
                'dn': 'cn=config,dc=example,dc=com',
                'default': ['attr1':default1'],
                'updates': ['action:attr1:value1',
                            'action:attr2:value2]
            },
        'dn': 'cn=bob,ou=people,dc=example,dc=com':
            {
                'dn': 'cn=bob,ou=people,dc=example,dc=com',
                'default': ['attr3':default3'],
                'updates': ['action:attr3:value3',
                            'action:attr4:value4],
            }
        }

        The default and update lists are "dispositions"


        '''
        log_mgr.get_logger(self, True)
        self.sub_dict = sub_dict
        self.live_run = live_run
        self.dm_password = dm_password
        self.conn = None
        self.modified = False
        self.online = online
        self.ldapi = ldapi
        self.plugins = plugins
        self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
        self.realm = None
        suffix = None

        if sub_dict.get("REALM"):
            self.realm = sub_dict["REALM"]
        else:
            krbctx = krbV.default_context()
            try:
                self.realm = krbctx.default_realm
                suffix = ipautil.realm_to_suffix(self.realm)
            except krbV.Krb5Error:
                self.realm = None
                suffix = None

        if suffix is not None:
            assert isinstance(suffix, DN)
        domain = ipautil.get_domain_name()
        libarch = self._identify_arch()

        fqdn = installutils.get_fqdn()
        if fqdn is None:
            raise RuntimeError("Unable to determine hostname")
        fqhn = fqdn  # Save this for the sub_dict variable
        if self.ldapi:
            fqdn = "ldapi://%%2fvar%%2frun%%2fslapd-%s.socket" % "-".join(
                self.realm.split("."))

        if not self.sub_dict.get("REALM") and self.realm is not None:
            self.sub_dict["REALM"] = self.realm
        if not self.sub_dict.get("FQDN"):
            self.sub_dict["FQDN"] = fqhn
        if not self.sub_dict.get("DOMAIN"):
            self.sub_dict["DOMAIN"] = domain
        if not self.sub_dict.get("SUFFIX") and suffix is not None:
            self.sub_dict["SUFFIX"] = suffix
        if not self.sub_dict.get("ESCAPED_SUFFIX"):
            self.sub_dict["ESCAPED_SUFFIX"] = str(suffix)
        if not self.sub_dict.get("LIBARCH"):
            self.sub_dict["LIBARCH"] = libarch
        if not self.sub_dict.get("TIME"):
            self.sub_dict["TIME"] = int(time.time())
        if not self.sub_dict.get("DOMAIN") and domain is not None:
            self.sub_dict["DOMAIN"] = domain

        if online:
            # Try out the connection/password
            try:
                conn = ipaldap.IPAdmin(fqdn,
                                       ldapi=self.ldapi,
                                       realm=self.realm)
                if self.dm_password:
                    conn.do_simple_bind(binddn=DN(('cn', 'directory manager')),
                                        bindpw=self.dm_password)
                elif os.getegid() == 0:
                    try:
                        # autobind
                        conn.do_external_bind(self.pw_name)
                    except errors.NotFound:
                        # Fall back
                        conn.do_sasl_gssapi_bind()
                else:
                    conn.do_sasl_gssapi_bind()
                conn.unbind()
            except (ldap.CONNECT_ERROR, ldap.SERVER_DOWN):
                raise RuntimeError("Unable to connect to LDAP server %s" %
                                   fqdn)
            except ldap.INVALID_CREDENTIALS:
                raise RuntimeError(
                    "The password provided is incorrect for LDAP server %s" %
                    fqdn)
            except ldap.LOCAL_ERROR, e:
                raise RuntimeError('%s' % e.args[0].get('info', '').strip())
Exemple #6
0
    def __init__(self, dm_password, sub_dict={}, live_run=True,
                 online=True, ldapi=False, plugins=False):
        '''
        :parameters:
            dm_password
                Directory Manager password
            sub_dict
                substitution dictionary
            live_run
                Apply the changes or just test
            online
                Do an online LDAP update or use an experimental LDIF updater
            ldapi
                Bind using ldapi. This assumes autobind is enabled.
            plugins
                execute the pre/post update plugins

        Data Structure Example:
        -----------------------

        dn_by_rdn_count = {
            3: 'cn=config,dc=example,dc=com':
            4: 'cn=bob,ou=people,dc=example,dc=com',
        }

        all_updates = {
        'dn': 'cn=config,dc=example,dc=com':
            {
                'dn': 'cn=config,dc=example,dc=com',
                'default': ['attr1':default1'],
                'updates': ['action:attr1:value1',
                            'action:attr2:value2]
            },
        'dn': 'cn=bob,ou=people,dc=example,dc=com':
            {
                'dn': 'cn=bob,ou=people,dc=example,dc=com',
                'default': ['attr3':default3'],
                'updates': ['action:attr3:value3',
                            'action:attr4:value4],
            }
        }

        The default and update lists are "dispositions"


        '''
        log_mgr.get_logger(self, True)
        self.sub_dict = sub_dict
        self.live_run = live_run
        self.dm_password = dm_password
        self.conn = None
        self.modified = False
        self.online = online
        self.ldapi = ldapi
        self.plugins = plugins
        self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
        self.realm = None
        suffix = None

        if sub_dict.get("REALM"):
            self.realm = sub_dict["REALM"]
        else:
            krbctx = krbV.default_context()
            try:
                self.realm = krbctx.default_realm
                suffix = ipautil.realm_to_suffix(self.realm)
            except krbV.Krb5Error:
                self.realm = None
                suffix = None

        if suffix is not None:
            assert isinstance(suffix, DN)
        domain = ipautil.get_domain_name()
        libarch = self._identify_arch()

        fqdn = installutils.get_fqdn()
        if fqdn is None:
            raise RuntimeError("Unable to determine hostname")
        fqhn = fqdn # Save this for the sub_dict variable
        if self.ldapi:
            fqdn = "ldapi://%%2fvar%%2frun%%2fslapd-%s.socket" % "-".join(
                self.realm.split(".")
            )

        if not self.sub_dict.get("REALM") and self.realm is not None:
            self.sub_dict["REALM"] = self.realm
        if not self.sub_dict.get("FQDN"):
            self.sub_dict["FQDN"] = fqhn
        if not self.sub_dict.get("DOMAIN"):
            self.sub_dict["DOMAIN"] = domain
        if not self.sub_dict.get("SUFFIX") and suffix is not None:
            self.sub_dict["SUFFIX"] = suffix
        if not self.sub_dict.get("ESCAPED_SUFFIX"):
            self.sub_dict["ESCAPED_SUFFIX"] = str(suffix)
        if not self.sub_dict.get("LIBARCH"):
            self.sub_dict["LIBARCH"] = libarch
        if not self.sub_dict.get("TIME"):
            self.sub_dict["TIME"] = int(time.time())
        if not self.sub_dict.get("DOMAIN") and domain is not None:
            self.sub_dict["DOMAIN"] = domain

        if online:
            # Try out the connection/password
            # (This will raise if the server is not available)
            self.create_connection()
            self.conn.unbind()
            self.conn = None
        else:
            raise RuntimeError("Offline updates are not supported.")
Exemple #7
0
    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
        assert isinstance(dn, DN)
        associateddomain = entry_attrs.get('associateddomain')
        add_domain = entry_attrs.get('add_domain')
        del_domain = entry_attrs.get('del_domain')
        force = options.get('force')

        current_domain = get_domain_name()

        # User specified the list of domains explicitly
        if associateddomain:
            if add_domain or del_domain:
                raise errors.MutuallyExclusiveError(
                    reason=_(
                        "The --domain option cannot be used together "
                        "with --add-domain or --del-domain. Use --domain "
                        "to specify the whole realm domain list explicitly, "
                        "to add/remove individual domains, use "
                        "--add-domain/del-domain.")
                )

            # Make sure our domain is included in the list
            if current_domain not in associateddomain:
                raise errors.ValidationError(
                    name='realmdomain list',
                    error=_("IPA server domain cannot be omitted")
                )

            # Validate that each domain satisfies the requirements
            # for realmdomain
            self.validate_domains(domains=associateddomain, force=force)

            return dn

        # If --add-domain or --del-domain options were provided, read
        # the curent list from LDAP, modify it, and write the changes back
        domains = ldap.get_entry(dn)['associateddomain']

        if add_domain:
            self.validate_domains(domains=[add_domain], force=force)
            del entry_attrs['add_domain']
            domains.append(add_domain)

        if del_domain:
            if del_domain == current_domain:
                raise errors.ValidationError(
                    name='del_domain',
                    error=_("IPA server domain cannot be deleted")
                )
            del entry_attrs['del_domain']

            try:
                domains.remove(del_domain)
            except ValueError:
                raise errors.AttrValueNotFound(
                    attr='associateddomain',
                    value=del_domain
                )

        entry_attrs['associateddomain'] = domains
        return dn