mirror of
https://github.com/Infisical/ansible-collection.git
synced 2025-08-01 11:44:29 -07:00
Compare commits
19 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7f992d3e59 | ||
|
89ab21f235 | ||
|
510e8c666f |
||
|
728bc04de1 |
||
|
189c664df7 | ||
|
50e046d71e | ||
|
3f11722a9d | ||
|
59f556f769 | ||
|
324514d92e | ||
|
29d09a401d |
||
|
054c8eecda | ||
|
3734effe53 | ||
|
4bda5c777a | ||
|
414ce80fc3 |
||
|
dd71333296 |
||
|
8d44160447 | ||
|
c154f3a039 |
||
|
521d5f9a95 |
||
|
aa65ac1bef |
6 changed files with 146 additions and 45 deletions
56
.github/workflows/distribute.yaml
vendored
56
.github/workflows/distribute.yaml
vendored
|
@ -1,21 +1,47 @@
|
|||
---
|
||||
name: Deploy Collection
|
||||
|
||||
# Trigger the workflow however you prefer
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
push:
|
||||
tags:
|
||||
- "*.*.*"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get the version name from the tags
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
|
||||
- name: Build and Deploy Collection
|
||||
uses: artis3n/ansible_galaxy_collection@v2
|
||||
with:
|
||||
api_key: "${{ secrets.GALAXY_API_KEY }}"
|
||||
galaxy_version: "${{ env.RELEASE_VERSION }}"
|
||||
release-galaxy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build and Deploy Collection
|
||||
uses: artis3n/ansible_galaxy_collection@v2
|
||||
with:
|
||||
api_key: "${{ secrets.GALAXY_API_KEY }}"
|
||||
galaxy_version: "${{ github.ref_name }}"
|
||||
|
||||
release-docker:
|
||||
needs: release-galaxy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: 🔧 Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: 🔧 Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: 🐋 Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
build-args: VERSION=${{ github.ref_name }}
|
||||
context: docker
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
infisical/ansible-collection:latest
|
||||
infisical/ansible-collection:${{ github.ref_name }}
|
||||
|
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
.venv/**/*
|
||||
ansible.cfg
|
||||
inventory
|
||||
test.yml
|
||||
__pycache__
|
||||
infisical-vault-1.0.0.tar.gz
|
10
README.md
10
README.md
|
@ -1,6 +1,8 @@
|
|||
# Infisical Collection
|
||||
This Ansible Infisical collection includes a variety of Ansible content to help automate the management of Infisical services. This collection is maintained by the Infisical team.
|
||||
|
||||
[View full documentation](https://galaxy.ansible.com/ui/repo/published/infisical/vault/)
|
||||
|
||||
## Ansible version compatibility
|
||||
|
||||
Tested with the Ansible Core >= 2.12.0 versions, and the current development version of Ansible. Ansible Core versions prior to 2.12.0 have not been tested.
|
||||
|
@ -15,12 +17,12 @@ Requires Python 3.7 or greater.
|
|||
|
||||
You can install the Infisical collection with the Ansible Galaxy CLI:
|
||||
|
||||
ansible-galaxy collection install maidul98.infisical_vault
|
||||
ansible-galaxy collection install infisical.vault
|
||||
|
||||
The python module dependencies are not installed by `ansible-galaxy`. They can
|
||||
be manually installed using pip:
|
||||
|
||||
pip install infisical
|
||||
pip install infisical-python
|
||||
|
||||
## Using this collection
|
||||
|
||||
|
@ -29,10 +31,10 @@ You can either call modules by their Fully Qualified Collection Name (FQCN), suc
|
|||
```yaml
|
||||
---
|
||||
vars:
|
||||
read_all_secrets_within_scope: "{{ lookup('infisical.vault.read_secrets', token='<>', path='/', env_slug='dev', url='https://spotify.infisical.com') }}"
|
||||
read_all_secrets_within_scope: "{{ lookup('infisical.vault.read_secrets', 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" }]
|
||||
|
||||
read_secret_by_name_within_scope: "{{ lookup('infisical.vault.read_secrets', token='<>', path='/', env_slug='dev', 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" }]
|
||||
```
|
||||
|
||||
|
|
25
docker/Dockerfile
Normal file
25
docker/Dockerfile
Normal file
|
@ -0,0 +1,25 @@
|
|||
FROM python:3.11-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV ANSIBLE_HOST_KEY_CHECKING=false
|
||||
ENV ANSIBLE_STDOUT_CALLBACK=yaml
|
||||
ENV ANSIBLE_CALLBACKS_ENABLED=profile_tasks
|
||||
|
||||
ARG VERSION
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
openssh-client \
|
||||
sshpass \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install --no-cache-dir ansible infisicalsdk
|
||||
|
||||
RUN ansible-galaxy collection install infisical.vault==${VERSION}
|
||||
|
||||
WORKDIR /ansible
|
||||
|
||||
RUN mkdir -p /root/.ansible
|
||||
|
||||
# Set default command
|
||||
CMD ["/bin/bash"]
|
|
@ -2,7 +2,7 @@
|
|||
# The namespace of the collection. This can be a company/brand/organization or product namespace under which all
|
||||
# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with
|
||||
# underscores or numbers and cannot contain consecutive underscores
|
||||
namespace: infisical_inc
|
||||
namespace: infisical
|
||||
|
||||
# The name of the collection. Has the same character restrictions as 'namespace'
|
||||
name: vault
|
||||
|
@ -62,7 +62,7 @@ issues: https://github.com/Infisical/ansible-collection/issues
|
|||
# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This
|
||||
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
|
||||
# and '.git' are always filtered. Mutually exclusive with 'manifest'
|
||||
build_ignore: []
|
||||
build_ignore: ["/docker/*"]
|
||||
# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a
|
||||
# list of MANIFEST.in style
|
||||
# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key
|
||||
|
|
|
@ -3,9 +3,9 @@ from ansible.plugins.lookup import LookupBase
|
|||
|
||||
HAS_INFISICAL = False
|
||||
try:
|
||||
from infisical import InfisicalClient
|
||||
from infisical_sdk import InfisicalSDKClient
|
||||
HAS_INFISICAL = True
|
||||
except ImportError:
|
||||
except ImportError as e:
|
||||
HAS_INFISICAL = False
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
|
@ -19,10 +19,17 @@ description:
|
|||
- Secrets can be located either by their name for individual secret loopups or by environment/folder path to return all secrets within the given scope.
|
||||
|
||||
options:
|
||||
token:
|
||||
description: The Infisical token used to authenticate
|
||||
universal_auth_client_id:
|
||||
description: The Machine Identity Client ID used to authenticate
|
||||
env:
|
||||
- name: INFISICAL_TOKEN
|
||||
- name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_ID
|
||||
required: True
|
||||
type: string
|
||||
version_added: 1.0.0
|
||||
universal_auth_client_secret:
|
||||
description: The Machine Identity Client Secret used to authenticate
|
||||
env:
|
||||
- name: UNIVERSAL_AUTH_MACHINE_IDENTITY_CLIENT_SECRET
|
||||
required: True
|
||||
type: string
|
||||
version_added: 1.0.0
|
||||
|
@ -44,6 +51,11 @@ options:
|
|||
required: True
|
||||
type: string
|
||||
version_added: 1.0.0
|
||||
project_id:
|
||||
description: "The ID of the project where the secrets are stored"
|
||||
required: True
|
||||
type: string
|
||||
version_added: 1.0.0
|
||||
secret_name:
|
||||
description: The name of the secret that should be fetched. The name should be exactly as it appears in Infisical
|
||||
required: False
|
||||
|
@ -53,51 +65,81 @@ options:
|
|||
|
||||
EXAMPLES = r"""
|
||||
vars:
|
||||
read_all_secrets_within_scope: "{{ lookup('infisical_vault', token='<>', 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" }]
|
||||
|
||||
read_secret_by_name_within_scope: "{{ lookup('infisical_vault', token='<>', path='/', env_slug='dev', 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" }]
|
||||
"""
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
self.set_options(var_options=variables, direct=kwargs)
|
||||
|
||||
if not HAS_INFISICAL:
|
||||
raise AnsibleError("Please pip install infisical to use the infisical_vault lookup module.")
|
||||
raise AnsibleError("Please pip install infisicalsdk to use the infisical_vault lookup module.")
|
||||
|
||||
infisical_token = self.get_option("token")
|
||||
machine_identity_client_id = self.get_option("universal_auth_client_id")
|
||||
machine_identity_client_secret = self.get_option("universal_auth_client_secret")
|
||||
url = self.get_option("url")
|
||||
|
||||
if not infisical_token:
|
||||
raise AnsibleError("Infisical token is required")
|
||||
# Check if the required environment variables are set
|
||||
if not machine_identity_client_id or not machine_identity_client_secret:
|
||||
raise AnsibleError("Please provide the universal_auth_client_id and universal_auth_client_secret")
|
||||
|
||||
# Initialize the Infisical client
|
||||
client = InfisicalClient(token=infisical_token, site_url=url)
|
||||
client = InfisicalSDKClient(host=url)
|
||||
|
||||
client.auth.universal_auth.login(
|
||||
machine_identity_client_id,
|
||||
machine_identity_client_secret
|
||||
)
|
||||
|
||||
secretName = kwargs.get('secret_name')
|
||||
envSlug = kwargs.get('env_slug')
|
||||
path = kwargs.get('path')
|
||||
project_id = kwargs.get('project_id')
|
||||
|
||||
if secretName:
|
||||
return self.get_single_secret(client, secretName, envSlug, path)
|
||||
return self.get_single_secret(
|
||||
client,
|
||||
project_id,
|
||||
secretName,
|
||||
envSlug,
|
||||
path
|
||||
)
|
||||
else:
|
||||
return self.get_all_secrets(client, envSlug, path)
|
||||
return self.get_all_secrets(client, project_id, envSlug, path)
|
||||
|
||||
def get_single_secret(self, client, secret_name, environment, path):
|
||||
def get_single_secret(
|
||||
self,
|
||||
client,
|
||||
project_id,
|
||||
secret_name,
|
||||
environment,
|
||||
path
|
||||
):
|
||||
try:
|
||||
print(secret_name, environment, path)
|
||||
secret = client.get_secret(secret_name=secret_name, environment=environment, path=path)
|
||||
return [{"value": s.secret_value, "key": s.secret_name}]
|
||||
secret = client.secrets.get_secret_by_name(
|
||||
secret_name=secret_name,
|
||||
project_id=project_id,
|
||||
environment_slug=environment,
|
||||
secret_path=path
|
||||
)
|
||||
|
||||
return [{"value": secret.secretValue, "key": secret.secretKey}]
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise AnsibleError(f"Error fetching all secrets {e}")
|
||||
raise AnsibleError(f"Error fetching single secret {e}")
|
||||
|
||||
def get_all_secrets(self, client, environment="dev", path="/"):
|
||||
def get_all_secrets(self, client, project_id, environment="dev", path="/"):
|
||||
try:
|
||||
secrets = client.get_all_secrets(environment=environment, path=path)
|
||||
return [{"value": s.secret_value, "key": s.secret_name} for s in secrets]
|
||||
secrets = client.secrets.list_secrets(
|
||||
project_id=project_id,
|
||||
environment_slug=environment,
|
||||
secret_path=path
|
||||
)
|
||||
|
||||
return [{"value": s.secretValue, "key": s.secretKey} for s in secrets.secrets]
|
||||
except Exception as e:
|
||||
raise AnsibleError(f"Error fetching all secrets {e}")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue