Skip to content

Commit

Permalink
Jinja2 templating support in inventory (#101)
Browse files Browse the repository at this point in the history
Jinja2 templating support in inventory (#101)

---------

Co-authored-by: Gianluca Salvo <[email protected]>
Co-authored-by: Jordan Borean <[email protected]>
  • Loading branch information
3 people authored Mar 19, 2024
1 parent 2c488fb commit 9af202e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
3 changes: 3 additions & 0 deletions changelogs/fragments/templating_support.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- >-
Added support for Jinja2 templating in ldap inventory.
13 changes: 13 additions & 0 deletions plugins/doc_fragments/ldap_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ModuleDocFragment:
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
Expand All @@ -47,6 +48,7 @@ class ModuleDocFragment:
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
Expand All @@ -60,6 +62,7 @@ class ModuleDocFragment:
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
Expand All @@ -80,6 +83,7 @@ class ModuleDocFragment:
- 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
Expand All @@ -89,20 +93,23 @@ class ModuleDocFragment:
- 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
certificate_password:
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
connection_timeout:
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:
Expand All @@ -117,6 +124,7 @@ class ModuleDocFragment:
- 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:
Expand All @@ -129,6 +137,7 @@ class ModuleDocFragment:
- 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
Expand All @@ -137,6 +146,7 @@ class ModuleDocFragment:
- 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
Expand All @@ -147,6 +157,7 @@ class ModuleDocFragment:
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
Expand All @@ -159,6 +170,7 @@ class ModuleDocFragment:
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
Expand All @@ -173,6 +185,7 @@ class ModuleDocFragment:
- 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
Expand Down
34 changes: 33 additions & 1 deletion plugins/inventory/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
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
Expand Down Expand Up @@ -125,6 +128,11 @@
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 #
Expand Down Expand Up @@ -311,8 +319,32 @@ def parse(
custom_attributes["inventory_hostname"] = {
"inventory_hostname": inventory_hostname
}

connection_options = self.get_options()

# 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:
schema = LDAPSchema.load_schema(client)
Expand Down
17 changes: 17 additions & 0 deletions tests/integration/targets/inventory_ldap/roles/test/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@
assert:
that: *default-assertion

- import_tasks: invoke.yml
vars:
scenario: LDAP through lookup templates
inventory:
plugin: microsoft.ad.ldap
server: !unsafe '{{ lookup("ansible.builtin.env", "LDAP_SERVER") }}'
username: !unsafe '{{ lookup("ansible.builtin.env", "LDAP_USERNAME") }}'
password: !unsafe '{{ lookup("ansible.builtin.env", "LDAP_PASSWORD") }}'
environment:
LDAP_SERVER: '{{ ldap_server }}'
LDAP_USERNAME: '{{ ldap_user }}'
LDAP_PASSWORD: '{{ ldap_pass }}'

- name: assert LDAP through lookup templates
assert:
that: *default-assertion

- import_tasks: invoke.yml
vars:
scenario: LDAPS
Expand Down

0 comments on commit 9af202e

Please sign in to comment.