diff --git a/README-idrange.md b/README-idrange.md index 8855f0ef94a4aaa953fc56dbf4eceba0ad9b8492..0f584ab7db14f4e8eea1ff0a612e9a6c69678120 100644 --- a/README-idrange.md +++ b/README-idrange.md @@ -175,8 +175,8 @@ Variable | Description | Required `rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | no `secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | no `dom_sid` \| `ipanttrusteddomainsid` | Domain SID of the trusted domain. | no -`dom_name` \| `ipanttrusteddomainname` | Name of the trusted domain. | no `idrange_type` \| `iparangetype` | ID range type, one of `ipa-ad-trust`, `ipa-ad-trust-posix`, `ipa-local`. Only valid if idrange does not exist. | no +`dom_name` \| `ipanttrusteddomainname` | Name of the trusted domain. Can only be used when `ipaapi_context: server`. | no `auto_private_groups` \| `ipaautoprivategroups` | Auto creation of private groups, one of `true`, `false`, `hybrid`. | no `delete_continue` \| `continue` | Continuous mode: don't stop on errors. Valid only if `state` is `absent`. Default: `no` (bool) | no `state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 88d12116110f934cb4d72785be4d25ed7b635239..82f48e85a21db7704e0e236eb7ec30f59c438a27 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -139,6 +139,13 @@ else: return fstore.has_files() + # Try to import dcerpc + try: + import ipaserver.dcerpc # pylint: disable=no-member + _dcerpc_bindings_installed = True # pylint: disable=invalid-name + except ImportError: + _dcerpc_bindings_installed = False # pylint: disable=invalid-name + if six.PY3: unicode = str @@ -221,6 +228,8 @@ else: ldap_cache: Control use of LDAP cache layer. (bool) """ + global _dcerpc_bindings_installed # pylint: disable=C0103,W0603 + env = Env() env._bootstrap() env._finalize_core(**dict(DEFAULT_CONFIG)) @@ -252,6 +261,7 @@ else: backend = api.Backend.ldap2 else: backend = api.Backend.rpcclient + _dcerpc_bindings_installed = False if not backend.isconnected(): backend.connect(ccache=os.environ.get('KRB5CCNAME', None)) @@ -701,6 +711,42 @@ else: print(jsonify(kwargs)) sys.exit(0) + def __get_domain_validator(): + if not _dcerpc_bindings_installed: + raise ipalib_errors.NotFound( + reason=( + 'Cannot perform SID validation without Samba 4 support ' + 'installed. Make sure you have installed server-trust-ad ' + 'sub-package of IPA on the server' + ) + ) + + # pylint: disable=no-member + domain_validator = ipaserver.dcerpc.DomainValidator(api) + # pylint: enable=no-member + + if not domain_validator.is_configured(): + raise ipalib_errors.NotFound( + reason=( + 'Cross-realm trusts are not configured. Make sure you ' + 'have run ipa-adtrust-install on the IPA server first' + ) + ) + + return domain_validator + + def get_trusted_domain_sid_from_name(dom_name): + """ + Given a trust domain name, returns the domain SID. + + Returns unicode string representation for a given trusted domain name + or None if SID for the given trusted domain name could not be found. + """ + domain_validator = __get_domain_validator() + sid = domain_validator.get_sid_from_domain_name(dom_name) + + return unicode(sid) if sid is not None else None + class IPAParamMapping(Mapping): """ Provides IPA API mapping to playbook parameters or computed values. diff --git a/plugins/modules/ipaidrange.py b/plugins/modules/ipaidrange.py index 78553f944fce216fdf794399571f60a9f81d67f0..b9e5dd9827e5d7d4492847a51fa0808cc70647d7 100644 --- a/plugins/modules/ipaidrange.py +++ b/plugins/modules/ipaidrange.py @@ -74,7 +74,9 @@ options: required: false aliases: ["ipanttrusteddomainsid"] dom_name: - description: Domain name of the trusted domain. + description: | + Domain name of the trusted domain. Can only be used when + `ipaapi_context: server`. type: string required: false aliases: ["ipanttrusteddomainname"] @@ -134,7 +136,7 @@ RETURN = """ from ansible.module_utils.ansible_freeipa_module import \ - IPAAnsibleModule, compare_args_ipa + IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name from ansible.module_utils import six if six.PY3: @@ -154,7 +156,7 @@ def find_idrange(module, name): def gen_args( base_id, range_size, rid_base, secondary_rid_base, idrange_type, dom_sid, - auto_private_groups + dom_name, auto_private_groups ): _args = {} # Integer parameters are stored as strings. @@ -169,6 +171,8 @@ def gen_args( _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: @@ -230,6 +234,7 @@ def main(): 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") @@ -278,7 +283,7 @@ def main(): # Generate args args = gen_args( base_id, range_size, rid_base, secondary_rid_base, - idrange_type, dom_sid, auto_private_groups + idrange_type, dom_sid, dom_name, auto_private_groups ) # Found the idrange diff --git a/setup.cfg b/setup.cfg index 6c4f672c5cf2e826f6b60c138ee0905557d661a1..10edc5023b37549a066e790e5afa682cda340bfc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -71,7 +71,8 @@ ignored-modules = ipaplatform, ipaplatform.paths, ipaplatform.tasks, ipapython.admintool, ipaserver.install.installutils, ipaserver.install.server.install, ipaserver.install, - ipaclient.install.ipachangeconf, ipaclient.install.client + ipaclient.install.ipachangeconf, ipaclient.install.client, + ipaserver.dcerpc [pylint.REFACTORING] max-nested-blocks = 9 diff --git a/tests/idrange/test_idrange.yml b/tests/idrange/test_idrange.yml index da5aa2b600538ff44c8be8d80c9913377027a7a3..5c4da9404006f1d4d0b5e847c5b1a80001d750be 100644 --- a/tests/idrange/test_idrange.yml +++ b/tests/idrange/test_idrange.yml @@ -227,6 +227,50 @@ name: ad_id_range state: absent + # Create trust with range_type: ipa-ad-trust-posix + - name: Create trust with range_type 'ipa-ad-trust' + include_tasks: tasks_set_trust.yml + vars: + trust_base_id: 10000000 + trust_range_size: 200000 + trust_range_type: ipa-ad-trust + + - name: Ensure AD-trust idrange is present, with dom_name + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_id_range + base_id: 150000000 + range_size: 200000 + rid_base: 1000000 + idrange_type: ipa-ad-trust + dom_name: "{{ adserver.domain }}" + auto_private_groups: "false" + register: result + failed_when: not result.changed or result.failed + + # Remove trust and idrange + - name: Remove test trust. + include_tasks: tasks_remove_trust.yml + + - name: Ensure AD-trust idrange is absent + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_id_range + state: absent + + # Remove trust and idrange + - name: Remove test trust. + include_tasks: tasks_remove_trust.yml + + - name: Ensure AD-trust idrange is absent + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_id_range + state: absent + # Create trust with range_type: ipa-ad-trust-posix - name: Create trust with range_type 'ipa-ad-trust-posix' include_tasks: tasks_set_trust.yml @@ -260,6 +304,51 @@ register: result failed_when: result.changed or result.failed + - name: Check if AD-trust-posix idrange is present, using dom_name + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_posix_id_range + base_id: 150000000 + range_size: 200000 + idrange_type: ipa-ad-trust-posix + dom_name: "{{ adserver.domain }}" + check_mode: yes + register: result + failed_when: result.changed or result.failed + + # Remove trust and idrange + - name: Remove test trust. + include_tasks: tasks_remove_trust.yml + + - name: Ensure AD-trust idrange is absent + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_posix_id_range + state: absent + + # Create trust with range_type: ipa-ad-trust-posix + - name: Create trust with range_type 'ipa-ad-trust-posix' + include_tasks: tasks_set_trust.yml + vars: + trust_base_id: 10000000 + trust_range_size: 2000000 + trust_range_type: ipa-ad-trust-posix + + # Can't use secondary_rid_base or rid_base with "ad-trust-posix" + - name: Ensure AD-trust-posix idrange is present, with dom_name + ipaidrange: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: ad_posix_id_range + base_id: 150000000 + range_size: 200000 + idrange_type: ipa-ad-trust-posix + dom_name: "{{ adserver.domain }}" + register: result + failed_when: not result.changed or result.failed + always: # CLEANUP TEST ITEMS - name: Remove test trust.