summaryrefslogtreecommitdiffstats
path: root/ansible_collections/microsoft/ad/plugins/action
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/microsoft/ad/plugins/action
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/microsoft/ad/plugins/action')
-rw-r--r--ansible_collections/microsoft/ad/plugins/action/__init__.py0
-rw-r--r--ansible_collections/microsoft/ad/plugins/action/debug_ldap_client.py176
-rw-r--r--ansible_collections/microsoft/ad/plugins/action/domain.py34
-rw-r--r--ansible_collections/microsoft/ad/plugins/action/domain_controller.py34
-rw-r--r--ansible_collections/microsoft/ad/plugins/action/membership.py8
5 files changed, 252 insertions, 0 deletions
diff --git a/ansible_collections/microsoft/ad/plugins/action/__init__.py b/ansible_collections/microsoft/ad/plugins/action/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/action/__init__.py
diff --git a/ansible_collections/microsoft/ad/plugins/action/debug_ldap_client.py b/ansible_collections/microsoft/ad/plugins/action/debug_ldap_client.py
new file mode 100644
index 000000000..a33f21dda
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/action/debug_ldap_client.py
@@ -0,0 +1,176 @@
+# Copyright (c) 2023 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import importlib
+import importlib.metadata
+import typing as t
+import traceback
+
+
+from ansible.plugins.action import ActionBase
+from ansible.utils.display import Display
+
+display = Display()
+
+try:
+ import dns.resolver
+
+ HAS_DNSRESOLVER = True
+except Exception:
+ HAS_DNSRESOLVER = False
+
+
+try:
+ import krb5
+
+ HAS_KRB5 = True
+except Exception:
+ HAS_KRB5 = False
+
+
+class ActionModule(ActionBase):
+ def run(
+ self,
+ tmp: t.Optional[str] = None,
+ task_vars: t.Optional[t.Dict[str, t.Any]] = None,
+ ) -> t.Dict[str, t.Any]:
+ self._supports_check_mode = True
+ self._supports_async = True
+
+ result = super().run(tmp=tmp, task_vars=task_vars)
+ del tmp
+
+ kerb_info = self._get_kerberos_info()
+
+ dns_info: t.Dict[str, t.Any] = {}
+ default_realm = kerb_info.get("default_realm", None)
+ if default_realm:
+ dns_info = self._get_server_lookup_info(default_realm)
+
+ result.update(
+ {
+ "dns": dns_info,
+ "kerberos": kerb_info,
+ "packages": {
+ "dnspython": self._import_lib("dns.resolver", package_name="dnspython"),
+ "dpapi_ng": self._import_lib("dpapi_ng", package_name="dpapi-ng"),
+ "krb5": self._import_lib("krb5"),
+ "pyspnego": self._import_lib("spnego", package_name="pyspnego"),
+ "sansldap": self._import_lib("sansldap"),
+ },
+ }
+ )
+
+ return result
+
+ def _get_kerberos_info(self) -> t.Dict[str, t.Any]:
+ if not HAS_KRB5:
+ return {}
+
+ res: t.Dict[str, t.Any] = {
+ "exception": None,
+ "default_realm": None,
+ "default_cc": {},
+ }
+
+ try:
+ ctx = krb5.init_context()
+ except Exception:
+ res["exception"] = traceback.format_exc()
+
+ if not ctx:
+ return res
+
+ try:
+ res["default_realm"] = krb5.get_default_realm(ctx).decode("utf-8")
+ except Exception:
+ res["exception"] = traceback.format_exc()
+
+ res["default_cc"] = self._get_kerberos_cc_info(ctx)
+
+ return res
+
+ def _get_kerberos_cc_info(
+ self,
+ ctx: "krb5.Context",
+ ) -> t.Dict[str, t.Any]:
+ creds: t.List[t.Dict[str, t.Any]] = []
+ res: t.Dict[str, t.Any] = {
+ "exception": None,
+ "name": None,
+ "principal": None,
+ "creds": creds,
+ }
+
+ try:
+ default_cc = krb5.cc_default(ctx)
+ except Exception:
+ res["exception"] = traceback.format_exc()
+
+ if not default_cc:
+ return res
+
+ try:
+ res["name"] = str(default_cc)
+ res["principal"] = str(default_cc.principal)
+ for cred in default_cc:
+ # cred attrs added in krb5 0.5.0
+ creds.append(
+ {
+ "client": str(getattr(cred, "client", "krb5 too old")),
+ "server": str(getattr(cred, "server", "krb5 too old")),
+ }
+ )
+ except Exception:
+ res["exception"] = traceback.format_exc()
+
+ return res
+
+ def _get_server_lookup_info(
+ self,
+ default_realm: str,
+ ) -> t.Dict[str, t.Any]:
+ if not HAS_DNSRESOLVER:
+ return {}
+
+ records: t.List[t.Dict[str, t.Any]] = []
+ res: t.Dict[str, t.Any] = {
+ "exception": None,
+ "default_server": None,
+ "default_port": None,
+ "records": records,
+ }
+
+ try:
+ srv_record = f"_ldap._tcp.dc._msdcs.{default_realm}"
+
+ for rec in dns.resolver.resolve(srv_record, "SRV"):
+ records.append(
+ {
+ "target": str(rec.target),
+ "port": rec.port,
+ "weight": rec.weight,
+ "priority": rec.priority,
+ }
+ )
+
+ highest_record = next(iter(sorted(records, key=lambda k: (k["priority"], -k["weight"]))), None)
+ if highest_record:
+ res["default_server"] = highest_record["target"].rstrip(".")
+ res["default_port"] = highest_record["port"]
+
+ except Exception:
+ res["exception"] = traceback.format_exc()
+
+ return res
+
+ def _import_lib(
+ self,
+ name: str,
+ package_name: t.Optional[str] = None,
+ ) -> str:
+ try:
+ importlib.import_module(name)
+ return importlib.metadata.version(package_name or name)
+ except Exception:
+ return traceback.format_exc()
diff --git a/ansible_collections/microsoft/ad/plugins/action/domain.py b/ansible_collections/microsoft/ad/plugins/action/domain.py
new file mode 100644
index 000000000..36cdb26e5
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/action/domain.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2022 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import typing as t
+
+from ..plugin_utils._module_with_reboot import ActionModuleWithReboot
+
+
+class ActionModule(ActionModuleWithReboot):
+ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
+ super().__init__(*args, **kwargs)
+ self._ran_once = False
+
+ def _ad_should_rerun(self, result: t.Dict[str, t.Any]) -> bool:
+ ran_once = self._ran_once
+ self._ran_once = True
+
+ if ran_once or not result.get("_do_action_reboot", False):
+ return False
+
+ if self._task.check_mode:
+ # Assume that on a rerun it will not have failed and that it
+ # ran successfull.
+ result["failed"] = False
+ result.pop("msg", None)
+ return False
+
+ else:
+ return True
+
+ def _ad_process_result(self, result: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
+ result.pop("_do_action_reboot", None)
+
+ return result
diff --git a/ansible_collections/microsoft/ad/plugins/action/domain_controller.py b/ansible_collections/microsoft/ad/plugins/action/domain_controller.py
new file mode 100644
index 000000000..36cdb26e5
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/action/domain_controller.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2022 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import typing as t
+
+from ..plugin_utils._module_with_reboot import ActionModuleWithReboot
+
+
+class ActionModule(ActionModuleWithReboot):
+ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
+ super().__init__(*args, **kwargs)
+ self._ran_once = False
+
+ def _ad_should_rerun(self, result: t.Dict[str, t.Any]) -> bool:
+ ran_once = self._ran_once
+ self._ran_once = True
+
+ if ran_once or not result.get("_do_action_reboot", False):
+ return False
+
+ if self._task.check_mode:
+ # Assume that on a rerun it will not have failed and that it
+ # ran successfull.
+ result["failed"] = False
+ result.pop("msg", None)
+ return False
+
+ else:
+ return True
+
+ def _ad_process_result(self, result: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
+ result.pop("_do_action_reboot", None)
+
+ return result
diff --git a/ansible_collections/microsoft/ad/plugins/action/membership.py b/ansible_collections/microsoft/ad/plugins/action/membership.py
new file mode 100644
index 000000000..5eea8d120
--- /dev/null
+++ b/ansible_collections/microsoft/ad/plugins/action/membership.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2022 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from ..plugin_utils._module_with_reboot import ActionModuleWithReboot
+
+
+class ActionModule(ActionModuleWithReboot):
+ ...