Skip to content
Crow CI

Integrations

Crow CI supports external secret store integrations, allowing you to fetch secrets directly from services like HashiCorp Vault or OpenBao during pipeline execution.

While Crow CI provides a built-in secret store using from_secret, integrations enable you to:

  • Centralize secret management across your infrastructure
  • Use existing secret rotation policies
  • Leverage enterprise secret management features
  • Access secrets without duplicating them in Crow CI
TypeDescription
vaultHashiCorp Vault / OpenBao via AppRole authentication
azure_key_vaultAzure Key Vault via Service Principal authentication
infisicalInfisical via Universal Auth (Machine Identity)
  1. Navigate to Integrations in the sidebar

  2. Click Add integration

  3. Configure the integration:

    • Name: A descriptive name for the integration
    • Type: Select the integration type (e.g., HashiCorp Vault)
    • Configuration: Provider-specific settings (see below)
  4. Configure access control via allowlists (users, organizations, or repositories that can use this integration)

  5. Click Save to create the integration

When configuring a Vault integration, provide the following settings:

SettingRequiredDescription
Vault AddressYesFull URL to your Vault server
Role IDYesAppRole Role ID for authentication
Secret IDYesAppRole Secret ID for authentication
Auth PathNoMount path for AppRole auth (default: approle)
Mount PathNoSecrets engine mount path (default: secret)
NamespaceNoVault Enterprise namespace (leave empty for OSS)
Skip TLS VerifyNoSkip TLS certificate verification (not recommended for production)
CA CertificateNoCustom CA certificate for TLS verification

To configure AppRole authentication in Vault:

# Enable AppRole auth method
vault auth enable approle

# Create a policy for Crow CI
vault policy write crow-ci - <<EOF
path "secret/data/crow/*" {
  capabilities = ["read"]
}
EOF

# Create an AppRole
vault write auth/approle/role/crow-ci \
  token_policies="crow-ci" \
  token_ttl=1h \
  token_max_ttl=4h

# Get the Role ID
vault read auth/approle/role/crow-ci/role-id

# Generate a Secret ID
vault write -f auth/approle/role/crow-ci/secret-id

When configuring an Azure Key Vault integration, provide the following settings:

SettingRequiredDescription
Vault URLYesFull URL to your Key Vault (e.g., https://my-vault.vault.azure.net)
Tenant IDYesAzure AD (Entra ID) Tenant ID
Client IDYesService Principal Application (Client) ID
Client SecretYesService Principal Client Secret

To configure a Service Principal for Crow CI:

# Create a Service Principal
az ad sp create-for-rbac --name crow-ci --skip-assignment

# Note the appId (Client ID), password (Client Secret), and tenant (Tenant ID)

# Grant the Service Principal access to your Key Vault
az keyvault set-policy \
  --name my-vault \
  --spn <appId> \
  --secret-permissions get list

Alternatively, if using Azure RBAC for Key Vault access control, assign the Key Vault Secrets User role:

az role assignment create \
  --role "Key Vault Secrets User" \
  --assignee <appId> \
  --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault-name>

Azure Key Vault secrets are single-valued (each secret name maps to one value), unlike Vault’s key-value pairs. Use path for the secret name and set key to "value" by convention:

steps:
  - name: deploy
    image: alpine
    environment:
      DB_PASSWORD:
        from_secret:
          integration: "my-azure-kv"
          path: 'prod-db-password'    # Azure Key Vault secret name
          key: 'value'                # Convention for single-valued secrets

When configuring an Infisical integration, provide the following settings:

SettingRequiredDescription
Site URLYesYour Infisical instance URL (default: https://app.infisical.com)
Client IDYesMachine Identity Client ID
Client SecretYesMachine Identity Client Secret
Project IDYesThe Infisical project ID where secrets are stored
EnvironmentYesEnvironment slug (e.g., dev, staging, prod)
Secret PathNoFolder path for secrets (default: /)
  1. In Infisical, go to Organization Settings > Machine Identities and create a new identity

  2. Under the identity, add Universal Auth and note the Client ID and Client Secret

  3. Go to your Project Settings > Access Control > Machine Identities, add the identity, and assign the Viewer role (or a custom role with read access)

  4. Note your Project ID from the project’s URL or settings page

Infisical secrets are scoped by project, environment, and path (configured in the integration). Use path for the secret key name and set key to "value" by convention:

steps:
  - name: deploy
    image: alpine
    environment:
      DB_PASSWORD:
        from_secret:
          integration: "infisical-prod"
          path: 'DATABASE_PASSWORD'   # Infisical secret key name
          key: 'value'                # Convention for single-valued secrets

Both internal (Crow CI) and external (Vault, Azure Key Vault, Infisical) secrets use the same from_secret keyword. The difference is in the value:

  • String value = internal secret (from Crow CI’s secret store)
  • Object value = external secret (from an integration like Vault)
steps:
  - name: deploy
    image: alpine
    environment:
      # Internal secret from Crow CI
      API_KEY:
        from_secret: my_api_key
steps:
  - name: deploy
    image: alpine
    environment:
      # External secret from Vault
      API_KEY:
        from_secret:
          integration: 1              # Integration ID or name
          path: 'crow/myapp'
          key: 'api_key'
FieldRequiredDescription
integrationYesIntegration ID (number) or name (string)
pathYesSecret path (Vault), secret name (Azure Key Vault), or key name (Infisical)
keyYesKey within the secret (Vault) or "value" (Azure Key Vault, Infisical)
versionNoSpecific version to fetch (default: 0 = latest)

You can reference integrations by their name for better readability:

steps:
  - name: deploy
    image: alpine
    environment:
      API_KEY:
        from_secret:
          integration: "vault-prod"   # Use integration name instead of ID
          path: 'crow/myapp'
          key: 'api_key'

External secrets work in both environment and settings:

steps:
  - name: publish
    image: codefloe.com/crowci/buildx:latest
    settings:
      registry: registry.example.com
      repo: myorg/myapp
      tags: <your-tag>
      username: myuser
      password:
        from_secret:
          integration: 1
          path: 'crow/docker'
          key: 'password'

Integrations use allowlists to control which pipelines can access secrets:

  • User allowlist: Specific users who can use this integration
  • Organization allowlist: All repositories in specified organizations
  • Repository allowlist: Specific repositories

You can use both internal and external secrets in the same pipeline:

steps:
  - name: build
    image: alpine
    environment:
      # Internal secret from Crow CI (string value)
      INTERNAL_TOKEN:
        from_secret: my_token
      # External secret from Vault (object value)
      EXTERNAL_API_KEY:
        from_secret:
          integration: "vault-prod"
          path: 'crow/api'
          key: 'key'

External secret fetching uses strict error handling:

  • If the external secret store is unreachable, the pipeline fails immediately
  • If a secret path or key doesn’t exist, the pipeline fails with a clear error
  • There are no silent fallbacks to prevent security issues

Best practices:

  • Use dedicated AppRoles with minimal permissions
  • Enable secret rotation in your Vault instance
  • Limit integration access via allowlists
  • Avoid logging secret values in pipeline output
  • Use TLS and verify certificates in production

After creating an integration, use the Test Connection button to verify connectivity:

  • Tests authentication (AppRole for Vault, Service Principal for Azure Key Vault, Universal Auth for Infisical)
  • Verifies network connectivity to the secret store
  • Does not access any actual secrets

A successful test shows “Connection test successful”.