ansible-collections / microsoft.ad

Ansible collection for Active Directory management
GNU General Public License v3.0
39 stars 22 forks source link

Jinja2 templating support in inventory #101

Closed Gianlu closed 6 months ago

Gianlu commented 7 months ago
SUMMARY

Hello, This PR contains some modifications in order to suppor Jinja2 templating in ldap inventory.

ISSUE TYPE
COMPONENT NAME
ADDITIONAL INFORMATION

I have to to target an inventory directory to multiple Active Directory so I can't use environment variables.

$ tree inventory/
inventory/
├── 00_ad1.microsoft.ad.ldap.yml
├── 00_ad2.microsoft.ad.ldap.yml
├── 00_ad3.microsoft.ad.ldap.yml
└── 99_final.yml

I added a couple of lines in order to make connection options more dynamic and supporting Jinja2 templating as already implemented in other inventory plugins.

plugin: microsoft.ad.ldap
server: mydomain.local.lcl
port: 389
username: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=path/to/my/secret:ad_credential_user') }}@{{ lookup('community.hashi_vault.hashi_vault', 'secret=path/to/my/secret:ad_credential_realm') }}"
password: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=path/to/my/secret:ad_credential_password') }}"

Bye

softwarefactory-project-zuul[bot] commented 7 months ago

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/abc4af1332294dc7a2a4a18bcf7d3566

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 55s :heavy_check_mark: build-ansible-collection SUCCESS in 7m 59s

softwarefactory-project-zuul[bot] commented 7 months ago

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/8d1413c5e2d34b53bea1df17a25578f7

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 44s :heavy_check_mark: build-ansible-collection SUCCESS in 7m 33s

jborean93 commented 7 months ago

Thanks for the PR, I didn't want to add a commit directly but here is a commit of some changes I think would be nice to have with a slightly different approach. I've also added a few more connection options and updated the documentation to reflect these new changes.

Please let me know if you disagree with any of the suggestions here or think there is a better option.

diff --git a/plugins/doc_fragments/ldap_connection.py b/plugins/doc_fragments/ldap_connection.py
index 9300881..327c1ba 100644
--- a/plugins/doc_fragments/ldap_connection.py
+++ b/plugins/doc_fragments/ldap_connection.py
@@ -31,6 +31,7 @@ options:
       installed.
     - See R(LDAP authentication,ansible_collections.microsoft.ad.docsite.guide_ldap_connection.authentication)
       for more information.
+    - This option can be set using a Jinja2 template value.
     choices:
     - simple
     - certificate
@@ -47,6 +48,7 @@ options:
       certificate validation.
     - If omitted, the default CA store used for validation is dependent on
       the current Python settings.
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_CA_CERT
@@ -60,6 +62,7 @@ options:
       hostname checks performed by TLS.
     - See R(Certificate validation,ansible_collections.microsoft.ad.docsite.guide_ldap_connection.cert_validation)
       for more information.
+    - This option can be set using a Jinja2 template value.
     choices:
     - always
     - ignore
@@ -80,6 +83,7 @@ options:
     - Use I(certificate_key) if the certificate specified does not contain the
       key.
     - Use I(certificate_password) if the key is encrypted with a password.
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_CERTIFICATE
@@ -89,6 +93,7 @@ options:
     - The value can either be a path to a file containing the key in the PEM or
       DER encoded form, or it can be the string of a PEM encoded key.
     - Use I(certificate_password) if the key is encrypted with a password.
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_CERTIFICATE_KEY
@@ -96,6 +101,7 @@ options:
     description:
     - The password used to decrypt the certificate key specified by
       I(certificate) or I(certificate_key).
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_CERTIFICATE_PASSWORD
@@ -103,6 +109,7 @@ options:
     description:
     - The timeout in seconds to wait until the connection is established before
       failing.
+    - This option can be set using a Jinja2 template value.
     default: 5
     type: int
     env:
@@ -117,6 +124,7 @@ options:
     - If using C(auth_protocol=simple) over LDAP without TLS then this must be
       set to C(False). As no encryption is used, all traffic will be in
       plaintext and should be avoided.
+    - This option can be set using a Jinja2 template value.
     default: true
     type: bool
     env:
@@ -129,6 +137,7 @@ options:
     - If I(auth_protocol) is C(negotiate), C(kerberos), or C(ntlm) and no
       password is specified, it will attempt to use the local cached credential
       specified by I(username) if available.
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_PASSWORD
@@ -137,6 +146,7 @@ options:
     - The LDAP port to use for the connection.
     - Port 389 is used for LDAP and port 686 is used for LDAPS.
     - Defaults to port C(636) if C(tls_mode=ldaps) otherwise C(389).
+    - This option can be set using a Jinja2 template value.
     type: int
     env:
     - name: MICROSOFT_AD_LDAP_PORT
@@ -147,6 +157,7 @@ options:
       C(default_realm) setting and with an SRV DNS lookup.
     - See R(Server lookup,ansible_collections.microsoft.ad.docsite.guide_ldap_connection.server_lookup)
       for more information.
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_SERVER
@@ -159,6 +170,7 @@ options:
       operation before the authentication bind.
     - It is recommended to use C(ldaps) over C(start_tls) if TLS is going to be
       used.
+    - This option can be set using a Jinja2 template value.
     choices:
     - ldaps
     - start_tls
@@ -173,6 +185,7 @@ options:
     - If I(auth_protocol) is C(negotiate), C(kerberos), or C(ntlm) and no
       username is specified, it will attempt to use the local cached credential
       if available, for example one retrieved by C(kinit).
+    - This option can be set using a Jinja2 template value.
     type: str
     env:
     - name: MICROSOFT_AD_LDAP_USERNAME
diff --git a/plugins/inventory/ldap.py b/plugins/inventory/ldap.py
index ca76f09..0a329da 100644
--- a/plugins/inventory/ldap.py
+++ b/plugins/inventory/ldap.py
@@ -84,6 +84,9 @@ notes:
   information.
 - This plugin is a tech preview and the module options are subject to change
   based on feedback received.
+- Unless specified otherwise in the option description, the value specified in
+  the config file is used as is. Only the LDAP connection options allow using
+  a Jinja2 template.
 extends_documentation_fragment:
 - constructed
 - microsoft.ad.ldap_connection
@@ -125,6 +128,11 @@ auth_protocol: kerberos
 tls_mode: ldaps
 ca_cert: /home/user/certs/ldap.pem

+# The username and password can be retrieved using a template with a lookup.
+# Other connection options can also be set this way, the option description
+# tells you whether it can be set to a template.
+username: '{{ lookup("ansible.builtin.env", "LDAP_USERNAME") }}'
+password: '{{ lookup("ansible.builtin.env", "LDAP_PASSWORD") }}'

 ##############################################
 #               Search Options               #
@@ -312,13 +320,30 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
                 "inventory_hostname": inventory_hostname
             }
         connection_options = self.get_options()
-        template_fields = ['username', 'password', 'server', 'tls_mode', 'auth_protocol', 'ca_cert',
-                           'cert_validation', 'certificate', 'certificate_key', 'certificate_key', 'encrypt']
-        for t in template_fields:
-            if t in connection_options.keys():
-                if self.templar.is_template(connection_options[t]):
-                    self.display.vvv("detemplating option %s" % t)
-                    connection_options[t] = self.templar.template(variable=connection_options[t], disable_lookups=False)
+
+        # These options are in ../doc_fragments/ldap_connection.py
+        template_fields = {
+            'auth_protocol',
+            'ca_cert',
+            'cert_validation',
+            'certificate',
+            'certificate_key',
+            'certificate_password',
+            'connection_timeout',
+            'encrypt',
+            'password',
+            'port',
+            'server',
+            'tls_mode',
+            'username',
+        }
+        for option_name, option_value in connection_options.items():
+            if option_name in template_fields and self.templar.is_template(option_value):
+                self.display.vvv(f"Templating option {option_name}")
+                connection_options[option_name] = self.templar.template(
+                    variable=option_value,
+                    disable_lookups=False,
+                )

         laps_decryptor = LAPSDecryptor(**connection_options)
         with create_ldap_connection(**connection_options) as client:
softwarefactory-project-zuul[bot] commented 6 months ago

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/38a8a70601e54e638c82a323eed1965e

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 27s :heavy_check_mark: build-ansible-collection SUCCESS in 8m 36s

softwarefactory-project-zuul[bot] commented 6 months ago

Build succeeded. https://ansible.softwarefactory-project.io/zuul/buildset/7bb5e5cb3369468a82a59170aab1901b

:heavy_check_mark: ansible-galaxy-importer SUCCESS in 4m 18s :heavy_check_mark: build-ansible-collection SUCCESS in 9m 19s

jborean93 commented 6 months ago

@Gianlu thanks for the new feature. I’ve just pushed 2 commits that include the gist above and some tests as I’m wanting to include this change in the upcoming release.

Gianlu commented 6 months ago

Thanks, sorry but I'm very busy in last weeks.

jborean93 commented 6 months ago

All good, appreciate you putting up the PR in the first place!