plugins/infrastructure/ansible-workflows/skills/ansible-secrets/SKILL.md
Secure secrets handling in Ansible with Infisical vault integration, no_log directive enforcement, and a reusable Infisical lookup task for safe credential retrieval.
npx skillsauth add basher83/lunar-claude ansible-secretsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Secure secrets handling with Infisical integration and proper security practices.
┌──────────────┐
│ Ansible │
│ Playbook │
└──────┬───────┘
│
│ include_tasks: infisical-secret-lookup.yml
│
▼
┌──────────────────┐
│ Infisical Lookup │
│ Task │
└──────┬───────────┘
│
├─> Try Universal Auth (preferred)
│ - INFISICAL_UNIVERSAL_AUTH_CLIENT_ID
│ - INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET
│
├─> Fallback to Environment Variable (optional)
│ - Uses specified fallback_env_var
│
▼
┌──────────────┐
│ Infisical │ (Vault)
│ API │
└──────────────┘
The repository provides a reusable task for secret retrieval at ansible/tasks/infisical-secret-lookup.yml.
- name: Retrieve Proxmox password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'PROXMOX_PASSWORD'
secret_var_name: 'proxmox_password'
infisical_project_id: '7b832220-24c0-45bc-a5f1-ce9794a31259'
infisical_env: 'prod'
infisical_path: '/proxmox-cluster'
# Now use the secret
- name: Create Proxmox user
community.proxmox.proxmox_user:
api_password: "{{ proxmox_password }}"
# ... other config ...
no_log: true
- name: Retrieve database password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
fallback_env_var: 'DB_PASSWORD' # Falls back to $DB_PASSWORD
infisical_project_id: '7b832220-24c0-45bc-a5f1-ce9794a31259'
infisical_env: 'prod'
infisical_path: '/database'
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| secret_name | Yes | - | Name of secret in Infisical |
| secret_var_name | Yes | - | Variable name to store secret |
| infisical_project_id | No | (repo default) | Infisical project ID |
| infisical_env | No | prod | Environment (prod, dev, staging) |
| infisical_path | No | /apollo-13/vault | Path within project |
| fallback_env_var | No | - | Env var to use as fallback |
| allow_empty | No | false | Allow empty secret values |
Set environment variables before running playbooks:
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="ua-abc123"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="secret-xyz789"
cd ansible
uv run ansible-playbook playbooks/my-playbook.yml
For local development or CI without Infisical:
export PROXMOX_PASSWORD="local-dev-password"
cd ansible
uv run ansible-playbook playbooks/my-playbook.yml
On tasks that handle secrets:
- name: Set database password
ansible.builtin.command: set-password {{ password }}
no_log: true
- name: Deploy config with secrets
ansible.builtin.template:
src: config.j2
dest: /etc/app/config.yml
no_log: true
# BAD - Exposes secrets
- name: Create user
community.proxmox.proxmox_user:
api_password: "my-password-123" # EXPOSED!
# GOOD
- name: Retrieve password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'PROXMOX_PASSWORD'
secret_var_name: 'proxmox_password'
- name: Create user
community.proxmox.proxmox_user:
api_password: "{{ proxmox_password }}"
no_log: true
Add validation for critical secrets:
- name: Get database password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
- name: Validate password complexity
ansible.builtin.assert:
that:
- db_password | length >= 16
fail_msg: "Password doesn't meet complexity requirements"
no_log: true
Retrieve secrets only when needed:
# GOOD - Retrieve only when needed
- name: System tasks (no secrets)
ansible.builtin.apt:
name: nginx
state: present
- name: Get credentials (only when needed)
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
- name: Configure database connection
ansible.builtin.template:
src: db-config.j2
dest: /etc/app/db.yml
no_log: true
Separate secrets by environment:
# Production
- name: Get prod secret
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
infisical_env: 'prod'
infisical_path: '/production/database'
# Development
- name: Get dev secret
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
infisical_env: 'dev'
infisical_path: '/development/database'
---
- name: Deploy application with secrets
hosts: app_servers
become: true
vars:
infisical_project_id: '7b832220-24c0-45bc-a5f1-ce9794a31259'
infisical_env: 'prod'
infisical_path: '/app-config'
tasks:
- name: Retrieve database password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'DB_PASSWORD'
secret_var_name: 'db_password'
- name: Retrieve API key
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'API_KEY'
secret_var_name: 'api_key'
- name: Retrieve Redis password
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'REDIS_PASSWORD'
secret_var_name: 'redis_password'
- name: Deploy application config
ansible.builtin.template:
src: app-config.j2
dest: /etc/app/config.yml
owner: app
group: app
mode: '0600'
no_log: true
name: Deploy
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Infisical
env:
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
run: |
echo "INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=$INFISICAL_CLIENT_ID" >> $GITHUB_ENV
echo "INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=$INFISICAL_CLIENT_SECRET" >> $GITHUB_ENV
- name: Run Ansible
run: |
cd ansible
uv run ansible-playbook playbooks/deploy.yml
Error: Missing Infisical authentication credentials
Solution:
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="ua-abc123"
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="secret-xyz789"
Error: Failed to retrieve secret from Infisical
Check:
Error: Secret validation failed (empty value)
Solutions:
# Option 1: Allow empty (not recommended for required secrets)
- name: Get optional secret
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'OPTIONAL_KEY'
secret_var_name: 'optional_key'
allow_empty: true
# Option 2: Use fallback
- name: Get secret with fallback
ansible.builtin.include_tasks: tasks/infisical-secret-lookup.yml
vars:
secret_name: 'API_KEY'
secret_var_name: 'api_key'
fallback_env_var: 'DEFAULT_API_KEY'
For detailed secrets management patterns, consult:
references/secrets-management.md - Infisical integration patterns, no_log best practices, credential securitytesting
Audit and improve CLAUDE.md files in repositories. Use when user asks to check, audit, update, improve, or fix CLAUDE.md files. Scans for all CLAUDE.md files, evaluates quality against templates, outputs quality report, then makes targeted updates. Also use when the user mentions "CLAUDE.md maintenance" or "project memory optimization".
tools
Operational tooling for Talos Linux Kubernetes clusters via Sidero Omni with Proxmox infrastructure provider, covering machine classes, CEL storage selectors, and provider lifecycle management.
tools
Best practices for git workflow automation including atomic commits, branch naming, conventional commit format, and changelog generation.
tools
Summarize the current state of the git repository