Overview
The Secrets Store CSI Driver mode provides secret management for clusters where External Secrets Operator cannot be installed due to organizational policies, cluster restrictions, or existing CSI driver deployments.When to Use CSI Driver vs External Secrets Operator:Use CSI Secret Store when:
- External Secrets Operator cannot be installed in your cluster
- Secrets Store CSI Driver is already deployed
- Cluster policies restrict which operators can run
- You have flexibility to install ESO
- You need multi-backend support (Vault, GCP, etc.)
- You prefer a more declarative secret management approach
How It Works
The CSI Secret Store integration uses three components:- SecretProviderClass: Defines which AWS Secrets Manager secrets to fetch and how to map them to Kubernetes Secret keys
- CSI Syncer Deployment: A minimal pod that mounts the CSI volume to materialize the Kubernetes Secret (the CSI driver requires an active mount)
- Kubernetes Secrets: Standard
crewai-platform-secretsconsumed by workloads (identical to inline or ESO modes)
- CSI driver materializes secrets via volume mounts instead of a controller reconciliation loop
- Requires a pod to keep the volume mounted (handled automatically by the chart’s
csi-syncerdeployment) - Currently supports AWS Secrets Manager only (ESO supports multiple backends)
Prerequisites
Before enabling CSI Secret Store mode, ensure the following components are installed in your cluster:1. Secrets Store CSI Driver
Install the core CSI driver withsyncSecret.enabled=true:
2. AWS Provider for Secrets Store CSI Driver
Install the AWS-specific provider, pinned to a release tag:3. IAM Permissions
Configure IAM permissions for the pods to access AWS Secrets Manager. Choose one method:- IRSA (Recommended for EKS)
- Node IAM Role
- EKS Pod Identity
IAM Roles for Service Accounts (IRSA) provides fine-grained, pod-level permissions.Create IAM Policy:Create IAM Role with Trust Policy:Reference the Role in Helm Values:
Setup Instructions
1. Prepare Secrets in AWS Secrets Manager
Create secrets in AWS Secrets Manager with the required structure.Platform Secrets
Create a secret containing all platform keys as a flat JSON object:Property Names: The chart expects lowercase, underscore-separated property names by default. Use
csiSecret.propertyMap to override if your secrets use different naming conventions.Database Password Secret
Create a separate secret for the database password:OAuth Secrets (Optional)
If using the OAuth service (oauth.enabled: true), create OAuth secrets:
- Separate OAuth Secret
2. Configure Helm Values
Create avalues.yaml file with CSI Secret Store configuration:
3. Deploy the Chart
Install or upgrade the chart with CSI Secret Store enabled:- SecretProviderClass Created (hook weight
-40): Defines which secrets to fetch - CSI Syncer Deployed (hook weight
-40): Pod mounts CSI volume, materializing the Secret - Wait Job Runs (hook weight
-20): Validates all required keys are present - Migrations Run (hook weights
-5,0): Database schema updates - Workloads Start: Web, worker, and other pods consume the synced secrets
4. Verify Secret Synchronization
Check that secrets were successfully materialized:Configuration Scenarios
GitHub App Integration
When using GitHub App authentication (envVars.GITHUB_APP_ID set), add these properties to your platform secret:
envVars.GITHUB_APP_ID is configured.
Auth Provider Integration
When using external auth providers (envVars.AUTH_PROVIDER set), add the provider-specific secret:
- Microsoft Entra ID
- Auth0
- Okta
OAuth Provider Credentials
When the OAuth service is enabled, the chart requests each configured provider’s credentials automatically. You do not list them inoauthPropertyMap.
Base credentials only. The chart expands each provider’s base client ID and
secret across all of that provider’s product integrations, exactly as inline
mode does. Configuring Google means storing two properties, not sixteen:
google_client_id and google_client_secret become GOOGLE_CAL_*,
GOOGLE_GMAIL_*, GOOGLE_DRIVE_*, GOOGLE_CONTACTS_*, GOOGLE_SHEETS_*,
GOOGLE_SLIDES_* and GOOGLE_DOCS_*. Microsoft behaves the same way across
Outlook, OneDrive, SharePoint, Teams, Word and Excel, including the tenant ID
when you set one.oauth.secrets:
Example (Google and Microsoft):
oauth.secrets.* blocks declare which providers are in use, which is what
tells the chart to request their properties. In CSI mode the values themselves
come from the backend, so the secret fields do not need to hold the real value.
When to use oauthPropertyMap
Only two cases need it:
-
Renaming a backend property. If your secret stores the Google client
secret as
google_oauth_secretrather thangoogle_client_secret: -
A product-specific credential that differs from the provider default.
If Gmail uses a different client than the rest of your Google integration,
list that key so it is sourced from its own property instead of inheriting
the base one:
oauthPropertyMap always wins over the fan-out for that one key;
every other key keeps inheriting the provider default.
See the OAuth Provider Credentials table
for the complete list of keys the OAuth Secret can carry.
Optional Services
Wharf Service (wharf.enabled: true):
cube.enabled: true):
Rotating Secrets
To rotate secrets in CSI Secret Store mode:1. Update Secret in AWS Secrets Manager
2. Trigger Secret Re-sync
The CSI driver periodically polls for updates (default: 2 minutes). To force immediate update, restart the CSI syncer pod:3. Restart Workloads
Pods do not automatically reload secrets from the Secret resource. Trigger a rolling restart:Automatic Rotation: Unlike External Secrets Operator (which supports
reloadOnChange annotations), CSI mode requires manual pod restarts after secret updates. Consider implementing an automated restart mechanism if frequent rotation is required.Limitations and Considerations
Compared to External Secrets Operator
Unsupported Features
TLS Auto-Generation: The chart’sweb.tls.autoGenerate feature is not compatible with CSI mode. Alternatives:
- Store certificates in AWS Secrets Manager (properties:
platform_ssl_key,platform_ssl_cert,crew_ssl_cert,crew_ssl_key) - Terminate TLS externally (load balancer or ingress controller)
lookup + randAlphaNum in GitOps workflows.
Security Best Practices
- Least Privilege IAM: Grant only
secretsmanager:GetSecretValueandsecretsmanager:DescribeSecretfor specific secret ARNs - Separate Secrets: Use different secrets for database, OAuth, and platform secrets for rotation isolation
- Enable CloudTrail: Audit secret access via AWS CloudTrail logs
- Rotate Regularly: Implement a secret rotation schedule (database passwords, API keys, etc.)
- Use IRSA: Prefer IRSA over node IAM roles for fine-grained permissions
Troubleshooting
Pods in CrashLoopBackOff
Symptom: Workload pods crash with “missing environment variable” errors. Cause: Secret not synced or missing required keys. Solution:-
Check CSI syncer pod status:
-
Verify SecretProviderClass configuration:
-
Check IAM permissions (pod should have
secretsmanager:GetSecretValue): -
Validate secret exists in AWS Secrets Manager:
Wait Job Timeout
Symptom: Pre-upgrade wait job times out before secrets sync. Cause: CSI driver not installed or misconfigured. Solution:-
Verify CSI driver is running:
-
Check if
syncSecret.enabled=true:Output should include--enable-secret-rotation=true.
IAM Permission Errors
Symptom: CSI driver logs showAccessDeniedException from AWS Secrets Manager.
Solution:
-
Verify IAM role permissions:
-
Check IRSA trust policy (if using IRSA):
-
Verify ServiceAccount annotation:
Should contain
eks.amazonaws.com/role-arn: arn:aws:iam::...annotation.
Secret Property Not Found
Symptom: CSI driver logs showProperty not found: <property_name>.
Cause: JSON property name mismatch between AWS secret and chart expectations.
Solution:
Use csiSecret.propertyMap to override property names:
Related Documentation
- CSI Secret Reference - Complete configuration reference
- External Secrets Operator - Alternative secret management
- Secrets Configuration - Direct secret values (inline mode)
- AWS IAM Setup Guide - AWS-specific IAM and IRSA configuration
