External Secrets Operator Setup for OpenStack Service Accounts
The External Secrets Operator (ESO) integration allows UnderStack to securely manage OpenStack service account credentials from external secret stores. This enables scenarios where Keystone runs in one cluster while other OpenStack services run in separate clusters, with credentials synchronized via ESO.
Overview
The ESO setup provides:
- Centralized credential management - Store OpenStack service credentials in external systems (Vault, AWS Secrets Manager, etc.)
- Multi-cluster support - Share credentials between clusters running different OpenStack services
- Automatic synchronization - ESO keeps credentials in sync across environments
- Security isolation - Avoid hardcoded credentials in Helm charts
Architecture
flowchart LR
ESS["`External Secret Store
(Vault/AWS/etc)`"] --> ESO[External Secrets Operator]
ESO --> KS[Kubernetes Secret per OpenStack Service]
KS --> OSH[OpenStack Helm Charts]
Generated Resources
For each OpenStack service, the ESO integration creates:
- Service Account Secrets - Individual secrets for each service account usage (admin, user, neutron, etc.)
- Configuration Secrets - oslo.config compatible config file snippets for the services
- ClusterSecretStore or SecretStore- Connection configuration to the external secret store where the credentials are sourced from
Configuration
1. Enable ESO Integration
In your $DEPLOY_NAME/helm-configs/openstack.yaml
:
keystoneServiceUsers:
enabled: true
secretStore:
kind: "ClusterSecretStore" # or "SecretStore" for namespaced
name: "openstack"
keystoneInterface: "internal"
# Optional: Add ArgoCD external links to secrets in your secret store UI
externalLinkAnnotationTemplate: "https://vault.example.com/ui/vault/secrets/secret/show{{ .remoteRef }}"
2. Configure Service Accounts
Define the service accounts for each OpenStack component:
keystoneServiceUsers:
services:
nova:
- usage: admin
remoteRef: "/openstack/admin-keystone-password"
- usage: user
remoteRef: "/openstack/nova-keystone-password"
- usage: neutron
remoteRef: "/openstack/nova-keystone-password"
- usage: service
remoteRef: "/openstack/nova-keystone-password"
section: "service_user"
ironic:
- usage: admin
remoteRef: "/openstack/admin-keystone-password"
- usage: user
remoteRef: "/openstack/ironic-keystone-password"
- usage: glance
remoteRef: "/openstack/ironic-keystone-password"
- usage: neutron
remoteRef: "/openstack/ironic-keystone-password"
3. Service Account Usage Types
Each service requires specific usage types:
admin
- Administrative user for OpenStack Helm's$SERVICE-ks-user
Jobs (creates/manages service users)user
- Primary service user for thekeystone_authtoken
section- Custom sections - Additional service-to-service authentication (neutron, glance, etc.)
4. External Secret Store Setup
UnderStack's 'openstack' component a ClusterSecretStore
will be created
that uses Kubernetes authentication:
# Generated automatically by the openstack component
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openstack
spec:
provider:
kubernetes:
remoteNamespace: openstack
server:
caProvider:
type: ConfigMap
name: kube-root-ca.crt
key: ca.crt
namespace: openstack
auth:
serviceAccount:
name: eso-openstack
namespace: openstack
Secrets Organization
Remote References
Store secrets in your external secret store with these expected fields:
Generated Kubernetes Secrets
For each service, ESO creates:
Individual service account secrets:
nova-keystone-admin
- Admin credentials for novanova-keystone-user
- Primary nova service credentialsnova-keystone-neutron
- Nova-to-neutron credentials
Configuration file secrets:
nova-ks-etc
- Containsnova_auth.conf
with OSLO config sections
Example Generated Configuration
For the nova service example above, the nova-ks-etc
secret contains:
[keystone_authtoken]
username=nova-service-user
password=secret-password
region_name=RegionOne
[neutron]
username=nova-service-user
password=secret-password
region_name=RegionOne
[service_user]
username=nova-service-user
password=secret-password
region_name=RegionOne
Migration from Static Secrets
Current State Assessment
Check your existing secret management:
grep -A 10 "keystoneServiceUsers:" $DEPLOY_NAME/helm-configs/openstack.yaml
Migration Steps
- Populate External Secret Store
Store your existing credentials in the external secret store with the remoteRef paths configured in your keystoneServiceUsers.services
.
- Enable ESO Integration
Update your openstack.yaml
configuration to enable ESO and configure the service accounts.
- Deploy and Verify
kubectl get secret nova-keystone-user -n openstack -o yaml
- Clean Up Legacy Secrets
Once verified, remove the old static secret generation from your deployment automation.
Troubleshooting
External Secret Sync Issues
Missing Service Account Permissions
The ESO service account needs access to read secrets from the source namespace:
kubectl auth can-i get secrets --as=system:serviceaccount:<namespace>:<serviceaccountname> [-n <namespace>]
kubectl auth can-i get secrets/admin-keystone-password --as=system:serviceaccount:openstack:eso-openstack -n openstack
Configuration Validation
kubectl get secret nova-ks-etc -n openstack -o jsonpath='{.data.nova_auth\.conf}' | base64 -d
Security Considerations
Access Control
- ESO service account has minimal required permissions
- Secrets are scoped to the
openstack
namespace - External secret store access follows principle of least privilege
Secret Rotation
- ESO automatically syncs updated credentials from the external store
- Refresh interval is configurable (default: 1 hour)
- Rolling updates of OpenStack services pick up new credentials
Audit Trail
- ESO provides audit logs for secret synchronization
- External secret stores maintain access logs
- ArgoCD external link annotations help track secret sources
Related Documentation
- Configuring OpenStack - Main OpenStack component configuration and basic ESO setup
- Component Configuration - General component patterns
- External Secrets Operator Documentation - Official ESO documentation