Skip to content
Snippets Groups Projects
Select Git revision
  • b211b50b2d4d1d0725b017609340537e7523f203
  • master default protected
  • v1.14.7
  • v1.14.6
  • v1.14.5
  • v1.14.4
  • v1.14.3
  • v1.14.2
  • v1.14.1
  • v1.14.0
  • v1.13.2
  • v1.13.1
  • v1.13.0
  • v1.12.1
  • v1.12.0
  • v1.11.1
  • v1.11.0
  • v1.10.0
  • v1.9.2
  • v1.9.1
  • v1.9.0
  • v1.8.4
22 results

setup.py

Blame
  • ipaidrange.py 10.83 KiB
    # -*- coding: utf-8 -*-
    
    # Authors:
    #   Rafael Guterres Jeffman <rjeffman@redhat.com>
    #   Thomas Woerner <twoerner@redhat.com>
    #
    # Copyright (C) 2022 Red Hat
    # see file 'COPYING' for use and warranty information
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    from __future__ import (absolute_import, division, print_function)
    
    __metaclass__ = type
    
    ANSIBLE_METADATA = {
        "metadata_version": "1.0",
        "supported_by": "community",
        "status": ["preview"],
    }
    
    DOCUMENTATION = """
    ---
    module: ipaidrange
    short_description: Manage FreeIPA idrange
    description: Manage FreeIPA idrange
    extends_documentation_fragment:
      - ipamodule_base_docs
      - ipamodule_base_docs.delete_continue
    options:
      name:
        description: The list of idrange name strings.
        type: list
        elements: str
        required: true
        aliases: ["cn"]
      base_id:
        description: First Posix ID of the range.
        type: int
        required: false
        aliases: ["ipabaseid"]
      range_size:
        description: Number of IDs in the range.
        type: int
        required: false
        aliases: ["ipaidrangesize"]
      rid_base:
        description: First RID of the corresponding RID range.
        type: int
        required: false
        aliases: ["ipabaserid"]
      secondary_rid_base:
        description: First RID of the secondary RID range.
        type: int
        required: false
        aliases: ["ipasecondarybaserid"]
      idrange_type:
        description: ID range type.
        type: str
        required: false
        choices: ["ipa-ad-trust", "ipa-ad-trust-posix", "ipa-local"]
        aliases: ["iparangetype"]
      dom_sid:
        description: Domain SID of the trusted domain.
        type: str
        required: false
        aliases: ["ipanttrusteddomainsid"]
      dom_name:
        description: |
          Domain name of the trusted domain. Can only be used when
          `ipaapi_context: server`.
        type: str
        required: false
        aliases: ["ipanttrusteddomainname"]
      auto_private_groups:
        description: Auto creation of private groups.
        type: str
        required: false
        choices: ["true", "false", "hybrid"]
        aliases: ["ipaautoprivategroups"]
      state:
        description: The state to ensure.
        type: str
        choices: ["present", "absent"]
        default: present
        required: false
    author:
      - Rafael Guterres Jeffman (@rjeffman)
      - Thomas Woerner (@t-woerner)
    """
    
    EXAMPLES = """
    # Ensure local domain idrange is present
    - ipaidrange:
        ipaadmin_password: SomeADMINpassword
        name: id_range
        base_id: 150000000
        range_size: 200000
        rid_base: 1000000
        secondary_rid_base: 200000000
    
    # Ensure local domain idrange is absent
    - ipaidrange:
        ipaadmin_password: SomeADMINpassword
        name: id_range
        state: absent
    
    # Ensure AD-trust idrange is present
    - ipaidrange:
        name: id_range
        base_id: 150000000
        range_size: 200000
        rid_base: 1000000
        idrange_type: ipa-ad-trust
        dom_sid: S-1-5-21-2870384104-3340008087-3140804251
        auto_private_groups: "false"
    
    # Ensure AD-trust idrange is present, with range type ad-trust-posix,
    # and using domain name
    - ipaidrange:
        name: id_range
        base_id: 150000000
        range_size: 200000
        rid_base: 1000000
        idrange_type: ipa-ad-trust-posix
        dom_name: ad.ipa.test
        auto_private_groups: "hybrid"
    """
    
    RETURN = """
    """
    
    
    from ansible.module_utils.ansible_freeipa_module import \
        IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name
    from ansible.module_utils import six
    
    if six.PY3:
        unicode = str
    
    
    def find_idrange(module, name):
        """Find if a idrange with the given name already exist."""
        try:
            _result = module.ipa_command("idrange_show", name, {"all": True})
        except Exception:  # pylint: disable=broad-except
            # An exception is raised if idrange name is not found.
            return None
        else:
            return _result["result"]
    
    
    def gen_args(
        base_id, range_size, rid_base, secondary_rid_base, idrange_type, dom_sid,
        dom_name, auto_private_groups
    ):
        _args = {}
        # Integer parameters are stored as strings.
        # Converting them here allows the proper use of compare_args_ipa.
        if base_id is not None:
            _args["ipabaseid"] = base_id
        if range_size is not None:
            _args["ipaidrangesize"] = range_size
        if rid_base is not None:
            _args["ipabaserid"] = rid_base
        if secondary_rid_base is not None:
            _args["ipasecondarybaserid"] = secondary_rid_base
        if idrange_type is not None:
            _args["iparangetype"] = idrange_type
        if dom_name is not None:
            dom_sid = get_trusted_domain_sid_from_name(dom_name)
        if dom_sid is not None:
            _args["ipanttrusteddomainsid"] = dom_sid
        if auto_private_groups is not None:
            _args["ipaautoprivategroups"] = auto_private_groups
        return _args
    
    
    def main():
        ansible_module = IPAAnsibleModule(
            argument_spec=dict(
                # general
                name=dict(type="list", elements="str", aliases=["cn"],
                          required=True),
                # present
                base_id=dict(required=False, type='int',
                             aliases=["ipabaseid"], default=None),
                range_size=dict(required=False, type='int',
                                aliases=["ipaidrangesize"], default=None),
                rid_base=dict(required=False, type='int',
                              aliases=["ipabaserid"], default=None),
                secondary_rid_base=dict(required=False, type='int', default=None,
                                        aliases=["ipasecondarybaserid"]),
                idrange_type=dict(required=False, aliases=["iparangetype"],
                                  type="str", default=None,
                                  choices=["ipa-ad-trust", "ipa-ad-trust-posix",
                                           "ipa-local"]),
                dom_sid=dict(required=False, type='str', default=None,
                             aliases=["ipanttrusteddomainsid"]),
                dom_name=dict(required=False, type='str', default=None,
                              aliases=["ipanttrusteddomainname"]),
                auto_private_groups=dict(required=False, type='str', default=None,
                                         aliases=["ipaautoprivategroups"],
                                         choices=['true', 'false', 'hybrid']),
                # state
                state=dict(type="str", default="present",
                           choices=["present", "absent"]),
            ),
            mutually_exclusive=[
                ["dom_sid", "secondary_rid_base"],
                ["dom_name", "secondary_rid_base"],
                ["dom_sid", "dom_name"],
            ],
            supports_check_mode=True,
            ipa_module_options=["delete_continue"],
        )
    
        ansible_module._ansible_debug = True
    
        # Get parameters
    
        # general
        names = ansible_module.params_get("name")
        delete_continue = ansible_module.params_get("delete_continue")
    
        # present
        base_id = ansible_module.params_get("base_id")
        range_size = ansible_module.params_get("range_size")
        rid_base = ansible_module.params_get("rid_base")
        secondary_rid_base = ansible_module.params_get("secondary_rid_base")
        idrange_type = ansible_module.params_get("idrange_type")
        dom_sid = ansible_module.params_get("dom_sid")
        dom_name = ansible_module.params_get("dom_name")
        auto_private_groups = \
            ansible_module.params_get_lowercase("auto_private_groups")
    
        # state
        state = ansible_module.params_get("state")
    
        # Check parameters
    
        invalid = []
    
        if state == "present":
            if len(names) != 1:
                ansible_module.fail_json(
                    msg="Only one idrange can be added at a time.")
    
        if state == "absent":
            if len(names) < 1:
                ansible_module.fail_json(msg="No name given.")
            invalid = [
                "base_id", "range_size", "idrange_type", "dom_sid", "dom_name",
                "rid_base", "secondary_rid_base", "auto_private_groups"
            ]
    
        ansible_module.params_fail_used_invalid(invalid, state)
    
        # Init
    
        changed = False
        exit_args = {}
    
        range_types = {
            "Active Directory domain range": "ipa-ad-trust",
            "Active Directory trust range with POSIX attributes":
                "ipa-ad-trust-posix",
            "local domain range": "ipa-local",
        }
    
        # Connect to IPA API
        with ansible_module.ipa_connect():
    
            commands = []
            for name in names:
                # Make sure idrange exists
                res_find = find_idrange(ansible_module, name)
    
                # Create command
                if state == "present":
    
                    # Generate args
                    args = gen_args(
                        base_id, range_size, rid_base, secondary_rid_base,
                        idrange_type, dom_sid, dom_name, auto_private_groups
                    )
    
                    # Found the idrange
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(
                            ansible_module, args, res_find, ignore=["iparangetype"]
                        ):
                            res_type = range_types.get(
                                res_find.get("iparangetype")[0]
                            )
                            if res_type == "local_id_range":
                                ansible_module.fail_json(
                                    "Cannot modify local IPA domain idrange."
                                )
    
                            arg_type = args.get("iparangetype")
                            if arg_type:
                                if arg_type != res_type:
                                    ansible_module.fail_json(
                                        "Cannot modify idrange type."
                                    )
                                del args["iparangetype"]
                            commands.append([name, "idrange_mod", args])
                    else:
                        commands.append([name, "idrange_add", args])
    
                elif state == "absent":
                    if res_find is not None:
                        commands.append([
                            name,
                            "idrange_del",
                            {"continue": delete_continue or False}
                        ])
    
                else:
                    ansible_module.fail_json(msg="Unkown state '%s'" % state)
    
            # Execute commands
    
            changed = ansible_module.execute_ipa_commands(commands)
    
        # Done
    
        ansible_module.exit_json(changed=changed, **exit_args)
    
    
    if __name__ == "__main__":
        main()