This commit is contained in:
Daniel Hougaard 2025-08-25 19:38:15 +02:00
commit 8bc1ba7281
3 changed files with 24 additions and 8 deletions

2
.gitignore vendored
View file

@ -4,3 +4,5 @@ inventory
test.yml test.yml
__pycache__ __pycache__
infisical-vault-1.0.0.tar.gz infisical-vault-1.0.0.tar.gz
.vscode

View file

@ -22,7 +22,7 @@ You can install the Infisical collection with the Ansible Galaxy CLI:
The python module dependencies are not installed by `ansible-galaxy`. They can The python module dependencies are not installed by `ansible-galaxy`. They can
be manually installed using pip: be manually installed using pip:
pip install infisical-python pip install infisicalsdk
## Using this collection ## Using this collection
@ -38,6 +38,6 @@ vars:
# {"SECRET_KEY_1": "secret-value-1", "SECRET_KEY_2": "secret-value-2"} -> Can be accessed as secrets.SECRET_KEY_1 # {"SECRET_KEY_1": "secret-value-1", "SECRET_KEY_2": "secret-value-2"} -> Can be accessed as secrets.SECRET_KEY_1
read_secret_by_name_within_scope: "{{ lookup('infisical.vault.read_secrets', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', secret_name='HOST', url='https://spotify.infisical.com') }}" read_secret_by_name_within_scope: "{{ lookup('infisical.vault.read_secrets', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', secret_name='HOST', url='https://spotify.infisical.com') }}"
# [{ "key": "HOST", "value": "google.com" }] # { "key": "HOST", "value": "google.com" }
``` ```

View file

@ -23,6 +23,7 @@ options:
description: The Machine Identity Client ID used to authenticate description: The Machine Identity Client ID used to authenticate
env: env:
- name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_ID - name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_ID
- name: INFISICAL_UNIVERSAL_AUTH_CLIENT_ID
required: True required: True
type: string type: string
version_added: 1.0.0 version_added: 1.0.0
@ -30,6 +31,7 @@ options:
description: The Machine Identity Client Secret used to authenticate description: The Machine Identity Client Secret used to authenticate
env: env:
- name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_SECRET - name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_SECRET
- name: INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET
required: True required: True
type: string type: string
version_added: 1.0.0 version_added: 1.0.0
@ -57,10 +59,15 @@ options:
type: string type: string
version_added: 1.0.0 version_added: 1.0.0
secret_name: secret_name:
description: The name of the secret that should be fetched. The name should be exactly as it appears in Infisical description: The name of the secret that should be fetched. The name should be exactly as it appears in Infisical.
required: False required: False
type: string type: string
version_added: 1.0.0 version_added: 1.0.0
as_dict:
description: "Return the listed secrets as a dictionary within a list instead of a list of key-value pairs (defaults to False). When True, returns [{'SECRET_KEY': 'secret_value', ...}] instead of [{'key': 'SECRET_KEY', 'value': 'secret_value'}, ...]. This only applies when reading all secrets within a scope, not when reading a single secret by name."
required: False
type: bool
version_added: 1.0.0
""" """
EXAMPLES = r""" EXAMPLES = r"""
@ -68,6 +75,9 @@ vars:
read_all_secrets_within_scope: "{{ lookup('infisical_vault', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', url='https://spotify.infisical.com') }}" read_all_secrets_within_scope: "{{ lookup('infisical_vault', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', url='https://spotify.infisical.com') }}"
# [{ "key": "HOST", "value": "google.com" }, { "key": "SMTP", "value": "gmail.smtp.edu" }] # [{ "key": "HOST", "value": "google.com" }, { "key": "SMTP", "value": "gmail.smtp.edu" }]
read_all_secrets_as_dict: "{{ lookup('infisical_vault', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', as_dict=True, url='https://spotify.infisical.com') }}"
# {"HOST": "google.com", "SMTP": "gmail.smtp.edu"}
read_secret_by_name_within_scope: "{{ lookup('infisical_vault', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', secret_name='HOST', url='https://spotify.infisical.com') }}" read_secret_by_name_within_scope: "{{ lookup('infisical_vault', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', secret_name='HOST', url='https://spotify.infisical.com') }}"
# [{ "key": "HOST", "value": "google.com" }] # [{ "key": "HOST", "value": "google.com" }]
""" """
@ -75,6 +85,7 @@ vars:
class LookupModule(LookupBase): class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs): def run(self, terms, variables=None, **kwargs):
self.set_options(var_options=variables, direct=kwargs) self.set_options(var_options=variables, direct=kwargs)
if not HAS_INFISICAL: if not HAS_INFISICAL:
raise AnsibleError("Please pip install infisicalsdk to use the infisical_vault lookup module.") raise AnsibleError("Please pip install infisicalsdk to use the infisical_vault lookup module.")
@ -95,6 +106,7 @@ class LookupModule(LookupBase):
) )
secretName = kwargs.get('secret_name') secretName = kwargs.get('secret_name')
asDict = kwargs.get('as_dict')
envSlug = kwargs.get('env_slug') envSlug = kwargs.get('env_slug')
path = kwargs.get('path') path = kwargs.get('path')
project_id = kwargs.get('project_id') project_id = kwargs.get('project_id')
@ -105,10 +117,10 @@ class LookupModule(LookupBase):
project_id, project_id,
secretName, secretName,
envSlug, envSlug,
path path,
) )
else: else:
return self.get_all_secrets(client, project_id, envSlug, path) return self.get_all_secrets(client, project_id, envSlug, path, asDict)
def get_single_secret( def get_single_secret(
self, self,
@ -128,10 +140,9 @@ class LookupModule(LookupBase):
return [{"value": secret.secretValue, "key": secret.secretKey}] return [{"value": secret.secretValue, "key": secret.secretKey}]
except Exception as e: except Exception as e:
print(e)
raise AnsibleError(f"Error fetching single secret {e}") raise AnsibleError(f"Error fetching single secret {e}")
def get_all_secrets(self, client, project_id, environment="dev", path="/"): def get_all_secrets(self, client, project_id, environment="dev", path="/", asDict=False):
try: try:
secrets = client.secrets.list_secrets( secrets = client.secrets.list_secrets(
project_id=project_id, project_id=project_id,
@ -139,7 +150,10 @@ class LookupModule(LookupBase):
secret_path=path secret_path=path
) )
return [{"value": s.secretValue, "key": s.secretKey} for s in secrets.secrets] if asDict:
return [{s.secretKey: s.secretValue for s in secrets.secrets}]
else:
return [{"value": s.secretValue, "key": s.secretKey} for s in secrets.secrets]
except Exception as e: except Exception as e:
raise AnsibleError(f"Error fetching all secrets {e}") raise AnsibleError(f"Error fetching all secrets {e}")