Keep the personal half of the desktop in one place, and ask before installing it
Agent instructions, skills, SSH host aliases and expansion triggers are worth having identical on every machine one person owns, and belong in none of the shared configuration. They live in user/ now, with a manifest saying where each piece goes and a link-user stage that puts it there. That stage does nothing unless the machine said yes. Somebody who clones Panama to try the desktop keeps their own ~/.claude/CLAUDE.md exactly where it was; the question names the destinations and defaults to no. Anything displaced goes to config/old rather than being deleted. ~/.claude/CLAUDE.md and ~/.codex/AGENTS.md were byte-identical copies of one file, which is the drift this exists to prevent. Also adds the vitals toggles for the battery and Claude usage readouts, which had preferences and no way to reach them.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: infisical-user-setup-guide
|
||||
description: "Interactive setup guide for using Infisical as a secret management tool in your projects. Helps users integrate Infisical into local development (CLI), Docker containers (build-time and runtime secret injection), CI/CD pipelines (GitHub Actions, GitLab CI), Kubernetes (Operator + CRDs), and application code (Node.js, Python, Go, Java, .NET, Ruby SDKs). Also walks through choosing and configuring machine identity auth methods (Universal Auth, AWS Auth, Kubernetes Auth, OIDC, etc.). Use this skill whenever someone asks about: using Infisical, injecting secrets, infisical run, infisical init, connecting their app to Infisical, Docker secrets, Kubernetes secrets operator, machine identity setup, SDK initialization, CI/CD secret injection, or 'how do I get my secrets into my app'."
|
||||
---
|
||||
|
||||
# Infisical User Setup Guide
|
||||
|
||||
You are an interactive setup assistant helping users integrate Infisical into their projects. Unlike a self-hosting guide, this skill is for people who *use* Infisical (cloud or self-hosted) to manage secrets and need help getting secrets into their applications, containers, pipelines, and infrastructure.
|
||||
|
||||
## How to use this skill
|
||||
|
||||
Start by understanding what the user is trying to do:
|
||||
|
||||
1. **Local development** — They want secrets injected into their dev workflow (CLI)
|
||||
2. **Docker** — They want secrets in their containers at build time or runtime
|
||||
3. **CI/CD** — They want secrets in GitHub Actions, GitLab CI, or other pipelines
|
||||
4. **Kubernetes** — They want the Infisical Operator syncing secrets to K8s
|
||||
5. **Application code** — They want to fetch secrets programmatically via an SDK
|
||||
6. **Auth setup** — They need to create a machine identity and choose an auth method
|
||||
|
||||
Read the relevant reference file(s), then walk them through step by step. Don't dump everything at once.
|
||||
|
||||
## Reference files
|
||||
|
||||
| File | When to read |
|
||||
|------|-------------|
|
||||
| `references/cli-setup.md` | User wants CLI-based local dev or basic `infisical run` usage |
|
||||
| `references/docker-integration.md` | User wants secrets in Docker containers (build or runtime) |
|
||||
| `references/kubernetes-operator.md` | User wants the K8s Operator, InfisicalSecret CRD, or dynamic secrets in K8s |
|
||||
| `references/sdks.md` | User wants to fetch secrets from application code (any language) |
|
||||
| `references/cicd-integration.md` | User wants secrets in GitHub Actions, GitLab CI, or other CI/CD |
|
||||
| `references/machine-identity-auth.md` | User needs to create a machine identity or choose an auth method |
|
||||
|
||||
## Guiding principles
|
||||
|
||||
- **Start with their platform.** Ask what they're running on (AWS, GCP, K8s, local, etc.) before recommending an auth method or integration approach.
|
||||
- **Recommend zero-secret auth when possible.** If they're on AWS, recommend AWS Auth. On K8s, recommend Kubernetes Auth. In GitHub Actions, recommend OIDC Auth. Only fall back to Universal Auth (Client ID/Secret) when platform-native options aren't available.
|
||||
- **CLI-first for local dev.** For developers working locally, the CLI (`infisical run -- <command>`) is almost always the right starting point. It's the simplest path to "my app has secrets."
|
||||
- **SDK for application code.** If they need secrets in application logic (not just env vars), point them to the SDK for their language.
|
||||
- **Warn about deprecated patterns.** Service Tokens (`st.*` prefix) and API Keys are deprecated. Always guide toward machine identities.
|
||||
- **Security-conscious.** Never generate secrets, tokens, or credentials on the user's behalf. Guide them to generate these themselves. Never log or display secret values.
|
||||
@@ -0,0 +1,112 @@
|
||||
# CI/CD Integration
|
||||
|
||||
How to get Infisical secrets into CI/CD pipelines. The recommended approach depends on the platform.
|
||||
|
||||
## GitHub Actions (OIDC — recommended)
|
||||
|
||||
Zero-secret integration using GitHub's built-in OIDC tokens. No stored secrets needed in GitHub.
|
||||
|
||||
### Step 1: Create a machine identity with OIDC auth
|
||||
|
||||
In the Infisical dashboard:
|
||||
1. Go to Organization Settings > Access Control > Machine Identities
|
||||
2. Create an identity and assign a role
|
||||
3. Add OIDC Auth with these settings:
|
||||
- **OIDC Discovery URL**: `https://token.actions.githubusercontent.com`
|
||||
- **Issuer**: `https://token.actions.githubusercontent.com`
|
||||
- **Subject**: `repo:<owner>/<repo>:<context>` (e.g., `repo:acme/api:ref:refs/heads/main`)
|
||||
- **Audiences**: Your GitHub org URL (e.g., `https://github.com/acme`)
|
||||
4. Add the identity to your project with appropriate permissions
|
||||
|
||||
### Step 2: Configure the workflow
|
||||
|
||||
```yaml
|
||||
name: Deploy
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Fetch secrets from Infisical
|
||||
uses: Infisical/[email protected]
|
||||
with:
|
||||
method: "oidc"
|
||||
identity-id: "<your-identity-id>"
|
||||
project-slug: "your-project"
|
||||
env-slug: "prod"
|
||||
|
||||
- name: Use secrets
|
||||
run: |
|
||||
echo "Secrets are now available as env vars"
|
||||
# e.g., $DATABASE_URL, $API_KEY
|
||||
```
|
||||
|
||||
**Key parameters for the action:**
|
||||
- `method`: `"oidc"` for OIDC auth
|
||||
- `identity-id`: The machine identity ID (public, safe to commit)
|
||||
- `project-slug`: Your Infisical project slug
|
||||
- `env-slug`: Environment (dev, staging, prod)
|
||||
|
||||
### Troubleshooting GitHub Actions OIDC
|
||||
|
||||
- Ensure `id-token: write` permission is set
|
||||
- Subject must exactly match the repo and context (branch, tag, or environment)
|
||||
- Audience must match the GitHub org URL
|
||||
- Project and environment slugs must match what's configured in Infisical
|
||||
|
||||
## GitLab CI
|
||||
|
||||
### Option 1: CLI with machine identity token
|
||||
|
||||
```yaml
|
||||
image: ubuntu
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- apt update && apt install -y curl bash
|
||||
- curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash
|
||||
- apt-get install -y infisical
|
||||
- export INFISICAL_TOKEN=$(infisical login --method=universal-auth
|
||||
--client-id=$INFISICAL_CLIENT_ID
|
||||
--client-secret=$INFISICAL_CLIENT_SECRET
|
||||
--plain --silent)
|
||||
- infisical run --projectId=$INFISICAL_PROJECT_ID --env=prod -- npm run build
|
||||
```
|
||||
|
||||
Store `INFISICAL_CLIENT_ID` and `INFISICAL_CLIENT_SECRET` as GitLab CI/CD variables (Settings > CI/CD > Variables).
|
||||
|
||||
### Option 2: OIDC auth (if GitLab supports it for your setup)
|
||||
|
||||
GitLab CI can issue OIDC tokens via `CI_JOB_JWT` or `id_tokens`. Configure similarly to GitHub Actions — create a machine identity with OIDC auth, set the issuer to your GitLab instance, and use the JWT to authenticate.
|
||||
|
||||
## Other CI/CD platforms
|
||||
|
||||
For any CI platform, the pattern is:
|
||||
|
||||
1. **Create a machine identity** with an appropriate auth method
|
||||
2. **Install the CLI** in the pipeline
|
||||
3. **Authenticate**: `infisical login --method=universal-auth --client-id=... --client-secret=... --plain --silent`
|
||||
4. **Inject secrets**: `infisical run -- <your-build-command>`
|
||||
|
||||
If the CI platform supports OIDC (e.g., CircleCI, Bitbucket), prefer OIDC Auth for zero-secret integration. Otherwise, use Universal Auth with Client ID/Secret stored as CI variables.
|
||||
|
||||
## Secret syncs (alternative approach)
|
||||
|
||||
Instead of fetching secrets at build time, Infisical can sync secrets directly into your CI/CD platform's native secret store (e.g., GitLab CI/CD Variables). This is a one-way push configured in the Infisical dashboard. Useful if you don't want to install the CLI in your pipeline, but less flexible than runtime injection.
|
||||
|
||||
## Security best practices for CI/CD
|
||||
|
||||
- **Prefer OIDC over stored credentials** when possible — no secrets to rotate or leak
|
||||
- **Scope machine identities tightly** — give each pipeline its own identity with minimum permissions
|
||||
- **Use environment-specific identities** — don't let a staging pipeline access production secrets
|
||||
- **Pin CLI version** in CI to avoid surprises from upstream updates
|
||||
@@ -0,0 +1,177 @@
|
||||
# CLI Setup for Local Development
|
||||
|
||||
The Infisical CLI is the fastest way to get secrets into a local development workflow. It injects secrets as environment variables into any process — no code changes needed.
|
||||
|
||||
## Installation
|
||||
|
||||
Guide the user based on their OS:
|
||||
|
||||
| Platform | Command |
|
||||
|----------|---------|
|
||||
| macOS | `brew install infisical/get-cli/infisical` |
|
||||
| Debian/Ubuntu | `curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' \| sudo bash && sudo apt-get install -y infisical` |
|
||||
| RedHat/CentOS/Amazon | `curl -1sLf 'https://artifacts-cli.infisical.com/setup.rpm.sh' \| sudo bash && sudo yum install -y infisical` |
|
||||
| Alpine | `curl -1sLf 'https://artifacts-cli.infisical.com/setup.alpine.sh' \| sudo bash && sudo apk add --no-cache infisical` |
|
||||
| Arch Linux | `yay -S infisical-bin` |
|
||||
| Windows (Scoop) | `scoop install infisical` |
|
||||
| Windows (Winget) | `winget install infisical` |
|
||||
| npm (any platform) | `npm install -g @infisical/cli` |
|
||||
|
||||
For production or CI, recommend pinning to a specific version for consistency.
|
||||
|
||||
## Login
|
||||
|
||||
```bash
|
||||
# Browser-based login (default — opens browser)
|
||||
infisical login
|
||||
|
||||
# Interactive terminal login (useful in containers, WSL2, Codespaces)
|
||||
infisical login --interactive
|
||||
|
||||
# Machine identity login (for automated environments)
|
||||
infisical login --method=universal-auth \
|
||||
--client-id=<client-id> \
|
||||
--client-secret=<client-secret>
|
||||
```
|
||||
|
||||
The CLI stores tokens in the system keyring. Users can switch between accounts with `infisical user`.
|
||||
|
||||
### Self-hosted or EU Cloud
|
||||
|
||||
By default the CLI connects to `https://app.infisical.com`. To use a different instance:
|
||||
|
||||
```bash
|
||||
# Option 1: Environment variable (recommended)
|
||||
export INFISICAL_API_URL="https://your-instance.com"
|
||||
|
||||
# Option 2: Flag on every command
|
||||
infisical login --domain="https://your-instance.com"
|
||||
|
||||
# Option 3: Interactive login prompts for region
|
||||
infisical login
|
||||
```
|
||||
|
||||
## Initialize a project
|
||||
|
||||
```bash
|
||||
cd /path/to/your/project
|
||||
infisical init
|
||||
```
|
||||
|
||||
This creates `.infisical.json` — a non-sensitive file that links the directory to an Infisical project. Safe to commit to git.
|
||||
|
||||
```json
|
||||
{
|
||||
"workspaceId": "63ee5410a45f7a1ed39ba118",
|
||||
"defaultEnvironment": "dev",
|
||||
"gitBranchToEnvironmentMapping": {
|
||||
"main": "prod",
|
||||
"staging": "staging",
|
||||
"develop": "dev"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `gitBranchToEnvironmentMapping` is optional but convenient — it auto-selects the environment based on the current git branch.
|
||||
|
||||
## Run your app with secrets
|
||||
|
||||
```bash
|
||||
# Basic — injects all secrets from the project as env vars
|
||||
infisical run -- npm run dev
|
||||
|
||||
# Specify environment
|
||||
infisical run --env=staging -- npm run dev
|
||||
|
||||
# Specify a folder path within the project
|
||||
infisical run --path=/apps/backend -- npm run dev
|
||||
|
||||
# Watch mode — auto-restarts when secrets change
|
||||
infisical run --watch -- npm run dev
|
||||
|
||||
# Multiple chained commands
|
||||
infisical run --command="npm run build && npm run start"
|
||||
```
|
||||
|
||||
This works with any framework or language — the secrets appear as standard environment variables in the child process.
|
||||
|
||||
## Manage secrets from the CLI
|
||||
|
||||
```bash
|
||||
# List all secrets
|
||||
infisical secrets
|
||||
|
||||
# Get specific secrets
|
||||
infisical secrets get API_KEY DATABASE_URL
|
||||
|
||||
# Set secrets
|
||||
infisical secrets set API_KEY=sk-1234 DATABASE_URL=postgres://...
|
||||
|
||||
# Set from a file
|
||||
infisical secrets set CERT=@/path/to/cert.pem
|
||||
|
||||
# Bulk import from .env
|
||||
infisical secrets set --file=./.env
|
||||
|
||||
# Delete secrets
|
||||
infisical secrets delete API_KEY
|
||||
|
||||
# Generate example .env from current secrets (redacted values)
|
||||
infisical secrets generate-example-env > .example-env
|
||||
```
|
||||
|
||||
## Export secrets to files
|
||||
|
||||
```bash
|
||||
# .env format (default)
|
||||
infisical export > .env
|
||||
|
||||
# Shell-ready (with export keyword)
|
||||
infisical export --format=dotenv-export > .env
|
||||
|
||||
# JSON
|
||||
infisical export --format=json > secrets.json
|
||||
|
||||
# YAML
|
||||
infisical export --format=yaml > secrets.yaml
|
||||
```
|
||||
|
||||
## Useful flags (apply to most commands)
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|---------|
|
||||
| `--env` | Environment slug (default: `dev`) |
|
||||
| `--path` | Folder path within the project (default: `/`) |
|
||||
| `--projectId` | Override project from `.infisical.json` |
|
||||
| `--expand` | Expand `${VAR}` references (default: true) |
|
||||
| `--include-imports` | Include imported secrets (default: true) |
|
||||
| `--tags` | Filter by comma-separated tags |
|
||||
| `--token` | Machine identity token (alternative to `INFISICAL_TOKEN` env var) |
|
||||
|
||||
## Secret scanning
|
||||
|
||||
The CLI can scan for leaked secrets in git history:
|
||||
|
||||
```bash
|
||||
# Scan git history
|
||||
infisical scan
|
||||
|
||||
# Scan only staged changes (pre-commit)
|
||||
infisical scan git-changes --staged
|
||||
|
||||
# Install as git pre-commit hook
|
||||
infisical scan install --pre-commit-hook
|
||||
```
|
||||
|
||||
## Offline support
|
||||
|
||||
The CLI caches previously fetched secrets. If the Infisical server is unreachable, `infisical run` falls back to the cache automatically.
|
||||
|
||||
## Terminal security tip
|
||||
|
||||
Prevent secrets from appearing in shell history:
|
||||
|
||||
```bash
|
||||
# Add to ~/.bashrc or ~/.zshrc
|
||||
export HISTIGNORE="*infisical secrets set*:$HISTIGNORE"
|
||||
```
|
||||
@@ -0,0 +1,130 @@
|
||||
# Docker Integration
|
||||
|
||||
How to get Infisical secrets into Docker containers. There are two main patterns: runtime injection (recommended) and build-time injection.
|
||||
|
||||
## Pattern 1: Runtime injection with `infisical run` (Recommended)
|
||||
|
||||
The cleanest approach — secrets are fetched fresh when the container starts. Nothing is baked into the image.
|
||||
|
||||
### Step 1: Install the CLI in your Dockerfile
|
||||
|
||||
```dockerfile
|
||||
# For Debian/Ubuntu-based images
|
||||
RUN apt-get update && apt-get install -y curl bash \
|
||||
&& curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash \
|
||||
&& apt-get install -y infisical
|
||||
|
||||
# For Alpine-based images
|
||||
RUN apk add --no-cache curl bash \
|
||||
&& curl -1sLf 'https://artifacts-cli.infisical.com/setup.alpine.sh' | bash \
|
||||
&& apk add --no-cache infisical
|
||||
```
|
||||
|
||||
### Step 2: Wrap your start command with `infisical run`
|
||||
|
||||
```dockerfile
|
||||
CMD ["infisical", "run", "--projectId", "<project-id>", "--", "node", "server.js"]
|
||||
```
|
||||
|
||||
### Step 3: Pass the auth token when running the container
|
||||
|
||||
```bash
|
||||
# First, obtain an access token via machine identity
|
||||
export INFISICAL_TOKEN=$(infisical login \
|
||||
--method=universal-auth \
|
||||
--client-id=<client-id> \
|
||||
--client-secret=<client-secret> \
|
||||
--plain --silent)
|
||||
|
||||
# Run the container with the token
|
||||
docker run --env INFISICAL_TOKEN=$INFISICAL_TOKEN my-app:latest
|
||||
```
|
||||
|
||||
**Important**: The user should generate and manage their own client ID and secret. Never generate these values on their behalf. Guide them to create a machine identity in the Infisical dashboard.
|
||||
|
||||
### Shell script approach (more flexible)
|
||||
|
||||
For more control, use an entrypoint script:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
# entrypoint.sh
|
||||
|
||||
# Authenticate and get access token
|
||||
export INFISICAL_TOKEN=$(infisical login \
|
||||
--method=universal-auth \
|
||||
--client-id=$INFISICAL_CLIENT_ID \
|
||||
--client-secret=$INFISICAL_CLIENT_SECRET \
|
||||
--plain --silent)
|
||||
|
||||
# Run the app with secrets injected
|
||||
exec infisical run \
|
||||
--token $INFISICAL_TOKEN \
|
||||
--projectId $INFISICAL_PROJECT_ID \
|
||||
--env $INFISICAL_ENV \
|
||||
-- "$@"
|
||||
```
|
||||
|
||||
```dockerfile
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
Then run with:
|
||||
|
||||
```bash
|
||||
docker run \
|
||||
-e INFISICAL_CLIENT_ID=<client-id> \
|
||||
-e INFISICAL_CLIENT_SECRET=<client-secret> \
|
||||
-e INFISICAL_PROJECT_ID=<project-id> \
|
||||
-e INFISICAL_ENV=prod \
|
||||
my-app:latest
|
||||
```
|
||||
|
||||
## Pattern 2: Export secrets as .env file
|
||||
|
||||
Useful with Docker Compose or when you need an env file:
|
||||
|
||||
```bash
|
||||
# Export secrets to a file
|
||||
infisical export --env=prod --format=dotenv > .env
|
||||
|
||||
# Use with docker run
|
||||
docker run --env-file .env my-app:latest
|
||||
|
||||
# Use with docker compose
|
||||
docker compose --env-file .env up
|
||||
```
|
||||
|
||||
**Caveat**: This writes secrets to disk. Make sure `.env` is in `.gitignore` and `.dockerignore`.
|
||||
|
||||
## Pattern 3: Docker Compose with infisical run
|
||||
|
||||
Wrap the entire compose command:
|
||||
|
||||
```bash
|
||||
infisical run -- docker compose up
|
||||
```
|
||||
|
||||
This injects secrets as environment variables into the `docker compose` process, which then passes them to containers via `environment:` directives in your compose file.
|
||||
|
||||
## Auth method selection for Docker
|
||||
|
||||
| Running where? | Recommended auth |
|
||||
|---------------|-----------------|
|
||||
| Local Docker Desktop | Universal Auth (Client ID/Secret) |
|
||||
| AWS ECS/Fargate | AWS Auth (uses task IAM role, zero-secret) |
|
||||
| GCP Cloud Run | GCP Auth (uses service identity, zero-secret) |
|
||||
| Azure Container Instances | Azure Auth (uses managed identity, zero-secret) |
|
||||
| Kubernetes (Docker in K8s) | Kubernetes Auth (uses service account, zero-secret) |
|
||||
| Generic cloud VM | Universal Auth |
|
||||
|
||||
See `machine-identity-auth.md` for details on setting up each auth method.
|
||||
|
||||
## Important notes
|
||||
|
||||
- **Never bake secrets into Docker images.** Don't use `ENV` or `ARG` for real secrets in Dockerfiles — they persist in image layers.
|
||||
- **Service Tokens are deprecated.** If the user mentions `st.*` tokens, guide them to machine identities instead.
|
||||
- **Pin the CLI version in production Dockerfiles** to avoid unexpected behavior from auto-updates.
|
||||
@@ -0,0 +1,238 @@
|
||||
# Kubernetes Operator
|
||||
|
||||
The Infisical Secrets Operator syncs secrets from Infisical into Kubernetes Secrets, so pods can consume them as env vars or volume mounts without application-level SDK integration.
|
||||
|
||||
## Supported versions
|
||||
|
||||
Kubernetes: 1.29 – 1.33. Distributions: EKS, GKE, AKS, OKE, OpenShift.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Add the Helm repo
|
||||
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
|
||||
helm repo update
|
||||
|
||||
# Cluster-wide install
|
||||
helm install --generate-name infisical-helm-charts/secrets-operator
|
||||
|
||||
# Namespace-scoped install (if you want to limit the operator's reach)
|
||||
helm install operator-namespaced infisical-helm-charts/secrets-operator \
|
||||
--namespace my-namespace \
|
||||
--set scopedNamespaces=my-namespace \
|
||||
--set scopedRBAC=true
|
||||
```
|
||||
|
||||
## Connecting to Infisical
|
||||
|
||||
By default the operator talks to `https://app.infisical.com/api`. For self-hosted instances, configure via ConfigMap:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: infisical-config
|
||||
namespace: infisical-operator-system
|
||||
data:
|
||||
hostAPI: https://your-instance.com/api
|
||||
```
|
||||
|
||||
For in-cluster Infisical: `http://<service-name>.<namespace>.svc.cluster.local:4000/api`
|
||||
|
||||
For custom/self-signed CA certificates:
|
||||
|
||||
```yaml
|
||||
data:
|
||||
hostAPI: https://your-instance.com/api
|
||||
tls.caRef.secretName: custom-ca-certificate
|
||||
tls.caRef.secretNamespace: default
|
||||
tls.caRef.key: ca.crt
|
||||
```
|
||||
|
||||
## CRD 1: InfisicalSecret (pull secrets into K8s)
|
||||
|
||||
This is the most common use case — syncing secrets from Infisical into a Kubernetes Secret.
|
||||
|
||||
### Step 1: Create auth credentials
|
||||
|
||||
```bash
|
||||
kubectl create secret generic universal-auth-credentials \
|
||||
--from-literal=clientId="<your-client-id>" \
|
||||
--from-literal=clientSecret="<your-client-secret>"
|
||||
```
|
||||
|
||||
**Important**: The user should create their own machine identity and credentials in the Infisical dashboard. Never generate these on their behalf.
|
||||
|
||||
### Step 2: Create the InfisicalSecret resource
|
||||
|
||||
```yaml
|
||||
apiVersion: secrets.infisical.com/v1alpha1
|
||||
kind: InfisicalSecret
|
||||
metadata:
|
||||
name: my-app-secrets
|
||||
spec:
|
||||
hostAPI: https://app.infisical.com/api
|
||||
syncConfig:
|
||||
resyncInterval: 60s
|
||||
instantUpdates: false
|
||||
|
||||
authentication:
|
||||
universalAuth:
|
||||
secretsScope:
|
||||
projectSlug: my-project
|
||||
envSlug: prod
|
||||
secretsPath: "/"
|
||||
credentialsRef:
|
||||
secretName: universal-auth-credentials
|
||||
secretNamespace: default
|
||||
|
||||
managedKubeSecretReferences:
|
||||
- secretName: my-app-managed-secret
|
||||
secretNamespace: default
|
||||
creationPolicy: "Orphan"
|
||||
```
|
||||
|
||||
### Step 3: Use in your deployment
|
||||
|
||||
```yaml
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: my-app-managed-secret
|
||||
```
|
||||
|
||||
### Auth methods for Kubernetes
|
||||
|
||||
**Universal Auth** (shown above) — simplest, works anywhere.
|
||||
|
||||
**Kubernetes Auth** (recommended for K8s) — zero-secret, uses pod service account tokens:
|
||||
|
||||
1. Create a token reviewer service account with `system:auth-delegator` role
|
||||
2. Create a service account for your workload
|
||||
3. Configure the identity with Kubernetes Auth in the Infisical dashboard
|
||||
4. Reference in the CRD:
|
||||
|
||||
```yaml
|
||||
authentication:
|
||||
kubernetesAuth:
|
||||
identityId: <identity-id>
|
||||
secretsScope:
|
||||
projectSlug: my-project
|
||||
envSlug: prod
|
||||
secretsPath: "/"
|
||||
serviceAccountRef:
|
||||
name: my-service-account
|
||||
namespace: default
|
||||
```
|
||||
|
||||
With `autoCreateServiceAccountToken: true`, the operator handles token lifecycle automatically.
|
||||
|
||||
### Resync interval
|
||||
|
||||
- Default: 1 minute (if instantUpdates=false), 1 hour (if instantUpdates=true)
|
||||
- Minimum: 5 seconds
|
||||
- Format: `[number][unit]` — `s`, `m`, `h`, `d`, `w`
|
||||
|
||||
### Templating
|
||||
|
||||
Use Go templates with Sprig functions to transform secrets:
|
||||
|
||||
```yaml
|
||||
managedKubeSecretReferences:
|
||||
- secretName: my-tls-secret
|
||||
secretNamespace: default
|
||||
template:
|
||||
data:
|
||||
tls.crt: "{{ .secrets.TLS_CERT | b64dec }}"
|
||||
tls.key: "{{ .secrets.TLS_KEY | b64dec }}"
|
||||
```
|
||||
|
||||
## CRD 2: InfisicalPushSecret (push K8s secrets to Infisical)
|
||||
|
||||
Pushes secrets from Kubernetes into Infisical — useful for bootstrapping or migration.
|
||||
|
||||
```yaml
|
||||
apiVersion: secrets.infisical.com/v1alpha1
|
||||
kind: InfisicalPushSecret
|
||||
metadata:
|
||||
name: push-to-infisical
|
||||
spec:
|
||||
resyncInterval: 1m
|
||||
hostAPI: https://app.infisical.com/api
|
||||
updatePolicy: Replace # None (skip if exists) or Replace (overwrite)
|
||||
deletionPolicy: Delete # None (leave in Infisical) or Delete (remove when CRD deleted)
|
||||
|
||||
destination:
|
||||
projectId: <project-id>
|
||||
environmentSlug: prod
|
||||
secretsPath: /
|
||||
|
||||
push:
|
||||
secret:
|
||||
secretName: my-k8s-secret
|
||||
secretNamespace: default
|
||||
|
||||
authentication:
|
||||
universalAuth:
|
||||
credentialsRef:
|
||||
secretName: universal-auth-credentials
|
||||
secretNamespace: default
|
||||
```
|
||||
|
||||
## CRD 3: InfisicalDynamicSecret (dynamic secret leases)
|
||||
|
||||
Generates short-lived credentials (e.g., database passwords) and syncs them to K8s:
|
||||
|
||||
```yaml
|
||||
apiVersion: secrets.infisical.com/v1alpha1
|
||||
kind: InfisicalDynamicSecret
|
||||
metadata:
|
||||
name: dynamic-db-creds
|
||||
spec:
|
||||
hostAPI: https://app.infisical.com/api
|
||||
|
||||
dynamicSecret:
|
||||
secretName: postgres-dynamic
|
||||
projectId: <project-id>
|
||||
secretsPath: /
|
||||
environmentSlug: prod
|
||||
|
||||
leaseRevocationPolicy: Revoke # Revoke lease when CRD is deleted
|
||||
leaseTTL: 30m # Max 24h
|
||||
|
||||
managedSecretReference:
|
||||
secretName: db-credentials
|
||||
secretNamespace: default
|
||||
creationPolicy: Orphan
|
||||
|
||||
authentication:
|
||||
universalAuth:
|
||||
credentialsRef:
|
||||
secretName: universal-auth-credentials
|
||||
secretNamespace: default
|
||||
```
|
||||
|
||||
The operator automatically rotates the lease before expiration.
|
||||
|
||||
## Monitoring
|
||||
|
||||
The operator exposes Prometheus metrics. Enable ServiceMonitor:
|
||||
|
||||
```yaml
|
||||
# In Helm values
|
||||
telemetry:
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
interval: 30s
|
||||
```
|
||||
|
||||
Key metrics: `controller_runtime_reconcile_total`, `controller_runtime_reconcile_errors_total`, `controller_runtime_reconcile_time_seconds`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Check the status of an InfisicalSecret:
|
||||
|
||||
```bash
|
||||
kubectl get infisicalsecret my-app-secrets -o yaml
|
||||
```
|
||||
|
||||
Look at `status.conditions` for error details. Common issues: wrong project slug, missing permissions on the machine identity, credentials secret not found.
|
||||
@@ -0,0 +1,150 @@
|
||||
# Machine Identity Authentication
|
||||
|
||||
This reference covers how to create machine identities and choose the right authentication method. A machine identity is how any non-human workload (app, container, CI job, serverless function) authenticates with Infisical to access secrets.
|
||||
|
||||
## Concept
|
||||
|
||||
A machine identity is like an IAM User (AWS), Service Account (GCP), or Service Principal (Azure). It:
|
||||
1. Has a name and role determining what it can access
|
||||
2. Has an authentication method determining how it proves its identity
|
||||
3. Authenticates → receives a short-lived access token
|
||||
4. Uses that token for API requests
|
||||
|
||||
## Creating a machine identity
|
||||
|
||||
### Organization-level (access to multiple projects)
|
||||
|
||||
1. Go to **Organization Settings > Access Control > Machine Identities**
|
||||
2. Click **Create Identity**
|
||||
3. Name it descriptively (e.g., `prod-api-server`, `github-actions-deploy`)
|
||||
4. Assign an organization-level role
|
||||
5. After creation, add it to specific projects with project-level roles
|
||||
|
||||
### Project-level (scoped to one project)
|
||||
|
||||
1. Go to **Project > Access Control > Machine Identities**
|
||||
2. Click **Add Identity**
|
||||
3. Name it and assign a project role
|
||||
|
||||
## Choosing an auth method
|
||||
|
||||
**Decision tree** — recommend based on the user's platform:
|
||||
|
||||
| Platform | Auth method | Why |
|
||||
|----------|------------|-----|
|
||||
| **AWS** (EC2, Lambda, ECS, Fargate, EKS) | AWS Auth | Zero-secret — uses IAM role, no credentials to manage |
|
||||
| **Kubernetes** | Kubernetes Auth | Zero-secret — uses pod service account token |
|
||||
| **GCP** (Compute, Cloud Run, GKE, Cloud Functions) | GCP Auth | Zero-secret — uses GCP identity token |
|
||||
| **Azure** (VMs, ACI, App Service, AKS) | Azure Auth | Zero-secret — uses managed identity |
|
||||
| **GitHub Actions** | OIDC Auth | Zero-secret — uses GitHub's built-in OIDC token |
|
||||
| **GitLab CI** | OIDC Auth | Zero-secret — uses GitLab's CI_JOB_JWT |
|
||||
| **Any OIDC provider** | OIDC Auth | Zero-secret — uses provider's JWT |
|
||||
| **SPIFFE/SPIRE** | SPIFFE Auth | Zero-secret — uses JWT-SVID |
|
||||
| **mTLS environments** | TLS Cert Auth | Uses X.509 client certificate |
|
||||
| **Enterprise LDAP/AD** | LDAP Auth | Uses LDAP bind credentials |
|
||||
| **Any platform (simple)** | Universal Auth | Client ID + Client Secret — works everywhere |
|
||||
| **Quick testing** | Token Auth | Static bearer token — simplest but least secure |
|
||||
|
||||
**General rule**: If a zero-secret option exists for the user's platform, recommend it. Zero-secret auth means no credentials to store, rotate, or leak.
|
||||
|
||||
## Auth method details
|
||||
|
||||
### Universal Auth
|
||||
|
||||
Works anywhere. The workload exchanges a Client ID + Client Secret for a short-lived access token.
|
||||
|
||||
**Setup in Infisical dashboard:**
|
||||
1. On the machine identity, add Universal Auth (this is the default)
|
||||
2. Configure: Access Token TTL, Max TTL, Max Number of Uses, Trusted IPs
|
||||
3. Create a Client Secret (can have its own TTL and usage limits)
|
||||
4. Hand the Client ID and Client Secret to the workload
|
||||
|
||||
**API call:**
|
||||
```
|
||||
POST /api/v1/auth/universal-auth/login
|
||||
{ "clientId": "<id>", "clientSecret": "<secret>" }
|
||||
→ { "accessToken": "<short-lived-token>" }
|
||||
```
|
||||
|
||||
**CLI:**
|
||||
```bash
|
||||
infisical login --method=universal-auth \
|
||||
--client-id=<id> --client-secret=<secret>
|
||||
```
|
||||
|
||||
**Lockout protection**: 3 failed attempts in 30s → 5-minute lockout. Configurable.
|
||||
|
||||
### AWS Auth
|
||||
|
||||
For AWS workloads with IAM roles. The workload signs an `sts:GetCallerIdentity` request and sends the signature to Infisical for verification. No Infisical credentials stored on the machine.
|
||||
|
||||
**Setup:**
|
||||
1. Add AWS Auth to the machine identity
|
||||
2. Configure: STS endpoint, Allowed Principal ARNs, Allowed Account IDs
|
||||
3. The workload uses its IAM role to authenticate automatically
|
||||
|
||||
Works with: EC2 (instance profile), Lambda (execution role), ECS/Fargate (task role), EKS with IRSA.
|
||||
|
||||
### Kubernetes Auth
|
||||
|
||||
For pods in Kubernetes clusters. The pod's service account token is verified via the Kubernetes TokenReview API.
|
||||
|
||||
**Setup:**
|
||||
1. Create a token reviewer service account with `system:auth-delegator` role
|
||||
2. Add Kubernetes Auth to the machine identity
|
||||
3. Configure: K8s API host, CA cert, token reviewer JWT, allowed namespaces/service accounts
|
||||
4. Pods authenticate using their service account token — no secrets needed
|
||||
|
||||
**Review modes:**
|
||||
- `Api`: Operator calls K8s API directly
|
||||
- `Gateway`: Routes through Infisical Gateway (for external clusters)
|
||||
|
||||
### GCP Auth
|
||||
|
||||
For GCP workloads. Two modes:
|
||||
- **Compute Engine (`gce`)**: Uses instance metadata for identity tokens. Configure allowed projects, zones.
|
||||
- **IAM (`iam`)**: Uses service account credentials. Configure allowed service account emails.
|
||||
|
||||
### Azure Auth
|
||||
|
||||
For Azure workloads with managed identities. Configure: Tenant ID, Resource, Allowed Service Principal IDs.
|
||||
|
||||
### OIDC Auth
|
||||
|
||||
For any OIDC-compliant provider (GitHub Actions, GitLab CI, custom IdPs). Verifies JWTs against the provider's discovery endpoint.
|
||||
|
||||
**Setup:**
|
||||
1. Add OIDC Auth to the machine identity
|
||||
2. Configure: Discovery URL, Bound Issuer, Bound Audiences, Bound Subject, Bound Claims
|
||||
3. The workload sends its OIDC JWT to Infisical for verification
|
||||
|
||||
### Token Auth
|
||||
|
||||
Simplest option — a pre-generated bearer token. No exchange needed; the workload uses it directly. Good for quick testing, but less secure (long-lived, static).
|
||||
|
||||
**Setup:** Create a token in the UI, copy it, hand it to the workload.
|
||||
|
||||
### SPIFFE Auth
|
||||
|
||||
For SPIFFE/SPIRE environments. Verifies JWT-SVIDs against the SPIRE trust bundle. Supports static or HTTPS-based trust bundle distribution. FIPS-compliant (only RS/PS/ES algorithms, no Ed25519).
|
||||
|
||||
### TLS Certificate Auth
|
||||
|
||||
For mTLS environments. The workload presents an X.509 client certificate, verified against a configured CA. Constraints on allowed Common Names.
|
||||
|
||||
### LDAP Auth
|
||||
|
||||
For enterprise LDAP/Active Directory environments. Workload authenticates with LDAP bind credentials. Supports lockout protection.
|
||||
|
||||
## Design best practices
|
||||
|
||||
- **One identity per application** — limits blast radius if compromised
|
||||
- **Separate by security tier** — payments, PII, and general services get different identities
|
||||
- **Consolidate replicas** — 10 replicas of the same app with identical needs = 1 identity
|
||||
- **Kubernetes: one identity per namespace** as a starting point
|
||||
- **Think blast radius** — "if this identity is compromised, what can the attacker access?"
|
||||
|
||||
## Deprecated approaches (do not use)
|
||||
|
||||
- **Service Tokens** (`st.*` prefix): Legacy, limited API access. Use machine identities instead.
|
||||
- **API Keys** (`X-API-Key` header): Deprecated, the backend rejects these.
|
||||
@@ -0,0 +1,242 @@
|
||||
# SDK Integration
|
||||
|
||||
For applications that need to fetch secrets programmatically — not just as environment variables, but within application logic. All SDKs follow the same pattern: initialize → authenticate → fetch secrets.
|
||||
|
||||
All SDKs cache secrets and fall back to cached values if requests fail. If no cache exists, they fall back to `process.env` (or equivalent).
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Language | Package | Min version |
|
||||
|----------|---------|-------------|
|
||||
| Node.js | `@infisical/sdk` | Node 20+ (v5+) |
|
||||
| Python | `infisicalsdk` | Python 3.7+ |
|
||||
| Go | `github.com/infisical/go-sdk` | Go 1.19+ |
|
||||
| Java | `com.infisical:sdk` | Java 11+ |
|
||||
| .NET | `Infisical.Sdk` | .NET 6+ |
|
||||
| Ruby | `infisical-sdk` | Ruby 2.7+ |
|
||||
|
||||
## Node.js
|
||||
|
||||
```bash
|
||||
npm install @infisical/sdk
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { InfisicalSDK } from '@infisical/sdk';
|
||||
|
||||
const client = new InfisicalSDK({
|
||||
siteUrl: "https://app.infisical.com" // optional, this is the default
|
||||
});
|
||||
|
||||
// Authenticate with a machine identity
|
||||
await client.auth().universalAuth.login({
|
||||
clientId: "<machine-identity-client-id>",
|
||||
clientSecret: "<machine-identity-client-secret>"
|
||||
});
|
||||
|
||||
// List all secrets
|
||||
const secrets = await client.secrets().listSecrets({
|
||||
environment: "dev",
|
||||
projectId: "<your-project-id>",
|
||||
secretPath: "/"
|
||||
});
|
||||
|
||||
// Get a single secret
|
||||
const secret = await client.secrets().getSecret({
|
||||
secretName: "API_KEY",
|
||||
environment: "prod",
|
||||
projectId: "<your-project-id>"
|
||||
});
|
||||
console.log(secret.secretValue);
|
||||
|
||||
// Create a secret
|
||||
await client.secrets().createSecret({
|
||||
secretName: "NEW_KEY",
|
||||
secretValue: "value",
|
||||
environment: "dev",
|
||||
projectId: "<your-project-id>"
|
||||
});
|
||||
```
|
||||
|
||||
Also supports: `updateSecret`, `deleteSecret`, dynamic secrets (leases), KMS encrypt/decrypt.
|
||||
|
||||
## Python
|
||||
|
||||
```bash
|
||||
pip install infisicalsdk
|
||||
```
|
||||
|
||||
```python
|
||||
from infisical_sdk import InfisicalSDKClient
|
||||
|
||||
client = InfisicalSDKClient(
|
||||
host="https://app.infisical.com",
|
||||
cache_ttl=60 # seconds, None to disable
|
||||
)
|
||||
|
||||
client.auth.universal_auth.login(
|
||||
client_id="<client-id>",
|
||||
client_secret="<client-secret>"
|
||||
)
|
||||
|
||||
# List secrets
|
||||
secrets = client.secrets.list_secrets(
|
||||
project_id="<project-id>",
|
||||
environment_slug="dev",
|
||||
secret_path="/"
|
||||
)
|
||||
|
||||
# Get one secret
|
||||
secret = client.secrets.get_secret(
|
||||
secret_name="API_KEY",
|
||||
project_id="<project-id>",
|
||||
environment_slug="prod"
|
||||
)
|
||||
print(secret.secret_value)
|
||||
```
|
||||
|
||||
Auth methods: Universal Auth, AWS IAM, OIDC, LDAP, Token Auth.
|
||||
|
||||
## Go
|
||||
|
||||
```bash
|
||||
go get github.com/infisical/go-sdk
|
||||
```
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
infisical "github.com/infisical/go-sdk"
|
||||
)
|
||||
|
||||
func main() {
|
||||
client := infisical.NewInfisicalClient(context.Background(), infisical.Config{
|
||||
SiteUrl: "https://app.infisical.com",
|
||||
AutoTokenRefresh: true,
|
||||
})
|
||||
|
||||
_, err := client.Auth().UniversalAuthLogin("CLIENT_ID", "CLIENT_SECRET")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
secret, err := client.Secrets().Retrieve(infisical.RetrieveSecretOptions{
|
||||
SecretKey: "API_KEY",
|
||||
Environment: "prod",
|
||||
ProjectID: "YOUR_PROJECT_ID",
|
||||
SecretPath: "/",
|
||||
})
|
||||
fmt.Println(secret.SecretValue)
|
||||
}
|
||||
```
|
||||
|
||||
Auth methods: Universal Auth, GCP (ID Token & IAM), AWS IAM, Azure, Kubernetes, JWT, LDAP, OCI.
|
||||
|
||||
**Note**: Set `AutoTokenRefresh: true` for long-running processes. For multiple clients, manage context cancellation properly to avoid leaked goroutines.
|
||||
|
||||
## Java
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.infisical</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>{version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
```java
|
||||
var sdk = new InfisicalSdk(
|
||||
new SdkConfig.Builder()
|
||||
.withSiteUrl("https://app.infisical.com")
|
||||
.build()
|
||||
);
|
||||
|
||||
sdk.Auth().UniversalAuthLogin("CLIENT_ID", "CLIENT_SECRET");
|
||||
|
||||
var secret = sdk.Secrets().GetSecret(
|
||||
"API_KEY", // secret name
|
||||
"<project-id>", // project ID
|
||||
"prod", // environment
|
||||
"/", // path
|
||||
null, null, null // optional: expandRefs, includeImports, type
|
||||
);
|
||||
System.out.println(secret.getValue());
|
||||
```
|
||||
|
||||
## .NET
|
||||
|
||||
```bash
|
||||
dotnet add package Infisical.Sdk
|
||||
```
|
||||
|
||||
```csharp
|
||||
var settings = new InfisicalSdkSettingsBuilder()
|
||||
.WithHostUri("https://app.infisical.com")
|
||||
.Build();
|
||||
|
||||
var client = new InfisicalClient(settings);
|
||||
|
||||
await client.Auth().UniversalAuth().LoginAsync("<client-id>", "<client-secret>");
|
||||
|
||||
var secrets = await client.Secrets().ListAsync(new ListSecretsOptions {
|
||||
EnvironmentSlug = "prod",
|
||||
SecretPath = "/",
|
||||
ProjectId = "<project-id>",
|
||||
SetSecretsAsEnvironmentVariables = true // optional: auto-set as env vars
|
||||
});
|
||||
```
|
||||
|
||||
## Ruby
|
||||
|
||||
```bash
|
||||
gem install infisical-sdk
|
||||
```
|
||||
|
||||
```ruby
|
||||
require 'infisical-sdk'
|
||||
|
||||
client = InfisicalSDK::InfisicalClient.new('https://app.infisical.com')
|
||||
|
||||
client.auth.universal_auth(
|
||||
client_id: 'CLIENT_ID',
|
||||
client_secret: 'CLIENT_SECRET'
|
||||
)
|
||||
|
||||
secret = client.secrets.get(
|
||||
secret_name: 'API_KEY',
|
||||
project_id: '<project-id>',
|
||||
environment: 'prod'
|
||||
)
|
||||
puts secret.secret_value
|
||||
```
|
||||
|
||||
Cache default: 5 minutes. Set to 0 to disable.
|
||||
|
||||
## When to use SDK vs. CLI
|
||||
|
||||
| Scenario | Use |
|
||||
|----------|-----|
|
||||
| Local dev, any framework | CLI (`infisical run -- ...`) |
|
||||
| Docker containers | CLI (see `docker-integration.md`) |
|
||||
| Need secrets in application logic (not just env vars) | SDK |
|
||||
| Dynamic secrets / leases | SDK |
|
||||
| KMS encrypt/decrypt | SDK |
|
||||
| Kubernetes pods | Operator (see `kubernetes-operator.md`) or SDK |
|
||||
| CI/CD pipelines | CLI or OIDC action (see `cicd-integration.md`) |
|
||||
|
||||
## Auth method availability by SDK
|
||||
|
||||
All SDKs support Universal Auth. Cloud-native auth varies:
|
||||
|
||||
| Auth method | Node | Python | Go | Java | .NET | Ruby |
|
||||
|------------|------|--------|-----|------|------|------|
|
||||
| Universal Auth | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| AWS IAM | Yes | Yes | Yes | — | — | Yes |
|
||||
| GCP | — | — | Yes | — | — | Yes |
|
||||
| Azure | — | — | Yes | — | — | Yes |
|
||||
| Kubernetes | — | — | Yes | — | — | Yes |
|
||||
| OIDC | — | Yes | — | — | — | — |
|
||||
| LDAP | — | Yes | Yes | — | Yes | — |
|
||||
Reference in New Issue
Block a user