Skip to content

Commit 37e5b2d

Browse files
committed
proposal: add new CRD OpenStackClusterIdentity
Signed-off-by: Bharath Nallapeta <[email protected]>
1 parent 57ae27e commit 37e5b2d

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# OpenStackClusterIdentity for Centralized Credential Management
2+
3+
## Metadata
4+
5+
- **Authors**: @bnallapeta
6+
- **Reviewers**: CAPO maintainers
7+
- **Status**: Proposed
8+
- **Creation Date**: 2025-07-22
9+
- **Last Updated**: 2025-07-22
10+
11+
## Summary
12+
13+
This proposal introduces `OpenStackClusterIdentity`, a cluster-scoped resource for centralized OpenStack credential management in CAPO. This enables multi-tenant environments to share credentials across namespaces while maintaining proper access controls, following patterns from AWS and Azure Cluster API providers.
14+
15+
## Motivation
16+
17+
### Goals
18+
- Enable centralized storage of OpenStack credentials in cluster-scoped resources
19+
- Provide fine-grained namespace access controls for credential usage
20+
- Maintain 100% backward compatibility with existing OpenStackCluster resources
21+
- Support manual, gradual migration without breaking existing deployments
22+
- Follow established patterns from other Cluster API providers (AWS, Azure)
23+
24+
### Non-Goals
25+
- Automatic migration of existing deployments
26+
- Integration with external secret management systems
27+
- Breaking changes to existing API or functionality
28+
29+
### User Stories
30+
31+
#### Story 1: Platform Administrator
32+
As a platform administrator managing multiple tenant namespaces, I want to store OpenStack credentials centrally in a secure namespace (e.g., `capo-system`), control which tenant namespaces can use specific credentials, and rotate credentials in one place without updating every namespace.
33+
34+
#### Story 2: Tenant User
35+
As a tenant user in namespace `team-a`, I want to create OpenStack clusters using centrally managed credentials without managing OpenStack secrets in my namespace, with clear error messages if I don't have permission to use specific credentials.
36+
37+
#### Story 3: Multi-Region Setup
38+
As an administrator managing clusters across multiple OpenStack regions, I want to create region-specific cluster identities with appropriate credentials and allow tenants to use different regional credentials based on their needs.
39+
40+
### API Design
41+
42+
#### New OpenStackClusterIdentity Resource (Cluster-scoped)
43+
44+
```go
45+
type OpenStackClusterIdentity struct {
46+
metav1.TypeMeta `json:",inline"`
47+
metav1.ObjectMeta `json:"metadata,omitempty"`
48+
Spec OpenStackClusterIdentitySpec `json:"spec,omitempty"`
49+
Status OpenStackClusterIdentityStatus `json:"status,omitempty"`
50+
}
51+
52+
type OpenStackClusterIdentitySpec struct {
53+
// SecretRef references the secret containing OpenStack credentials
54+
SecretRef OpenStackCredentialSecretReference `json:"secretRef"`
55+
56+
// AllowedNamespaces defines which namespaces can use this identity
57+
// +optional
58+
AllowedNamespaces []string `json:"allowedNamespaces,omitempty"`
59+
60+
// NamespaceSelector selects allowed namespaces via labels
61+
// +optional
62+
NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"`
63+
}
64+
65+
type OpenStackCredentialSecretReference struct {
66+
Name string `json:"name"`
67+
Namespace string `json:"namespace"`
68+
}
69+
70+
type OpenStackClusterIdentityStatus struct {
71+
Ready bool `json:"ready"`
72+
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
73+
}
74+
75+
type OpenStackClusterIdentityReference struct {
76+
Name string `json:"name"`
77+
}
78+
```
79+
80+
**Enhanced OpenStackCluster:**
81+
```go
82+
type OpenStackClusterSpec struct {
83+
// ... existing fields unchanged ...
84+
85+
// ClusterIdentityRef references a cluster-scoped identity (NEW)
86+
// Takes precedence over IdentityRef if specified
87+
// +optional
88+
ClusterIdentityRef *OpenStackClusterIdentityReference `json:"clusterIdentityRef,omitempty"`
89+
90+
// IdentityRef references namespace-local secret (EXISTING - unchanged)
91+
// +kubebuilder:validation:Required
92+
IdentityRef OpenStackIdentityReference `json:"identityRef"`
93+
}
94+
```
95+
96+
### Implementation Details
97+
98+
#### Credential Resolution Logic
99+
The scope factory will implement dual-path credential resolution:
100+
101+
```go
102+
func (f *providerScopeFactory) resolveCredentials(obj infrav1.IdentityRefProvider) {
103+
// Priority 1: Check for cluster identity reference
104+
if clusterRef := obj.GetClusterIdentityRef(); clusterRef != nil {
105+
return f.newScopeFromClusterIdentity(clusterRef)
106+
}
107+
108+
// Priority 2: Fall back to existing namespace identity behavior
109+
return f.newScopeFromNamespaceIdentity(obj.GetIdentityRef())
110+
}
111+
```
112+
113+
**Key Edge Cases:**
114+
- Both references specified: Use `clusterIdentityRef`, log warning
115+
- Identity deletion: Clusters show degraded status, don't fail
116+
- Permission changes: Dynamic re-validation during reconciliation
117+
- Invalid access: Clear error messages with namespace authorization checks
118+
119+
**RBAC Requirements:**
120+
```yaml
121+
rules:
122+
- apiGroups: [""]
123+
resources: ["secrets", "namespaces"]
124+
verbs: ["get"]
125+
- apiGroups: ["infrastructure.cluster.x-k8s.io"]
126+
resources: ["openstackclusteridentities"]
127+
verbs: ["get", "list", "watch"]
128+
```
129+
130+
### Backward Compatibility
131+
132+
- Existing `identityRef` field remains required and fully functional
133+
- Clusters without `clusterIdentityRef` work exactly as before
134+
- `clusterIdentityRef` takes precedence when both are specified
135+
136+
#### Migration Strategy
137+
- **No forced migration**: Existing deployments continue working indefinitely
138+
- **Manual opt-in**: Users choose when to adopt cluster identities
139+
- **Gradual adoption**: Mix of old and new approaches supported
140+
- **Clear documentation**: Step-by-step migration guides and examples
141+
142+
### Testing Strategy
143+
144+
**Unit Tests**: API validation, dual-path credential resolution, RBAC permission checking, edge cases
145+
**Integration Tests**: End-to-end credential resolution, cross-namespace access validation, permission enforcement
146+
**E2E Tests**: Full cluster lifecycle with cluster identity, mixed deployments, runtime permission changes
147+
**Security Tests**: Unauthorized access attempts, RBAC boundary enforcement, audit trail verification
148+
149+
## Risks and Mitigations
150+
151+
| Risk | Mitigation |
152+
|------|------------|
153+
| Cross-namespace RBAC complexity | Extensive testing, clear documentation, validation webhooks |
154+
| Security boundary violations | Strict validation, audit logging, security review |
155+
| Migration complexity | Clear documentation, examples, optional migration |
156+
| Performance impact | Caching strategy, minimal additional overhead |
157+
158+
## Alternatives
159+
160+
**External Secret Operator**: More complex, adds external dependency
161+
**OpenStack Application Credentials**: Not universally supported across deployments
162+
**Namespace-scoped Identity**: Doesn't solve centralized management
163+
**ConfigMap-based References**: No validation, security concerns
164+
165+
## Example Usage
166+
167+
```yaml
168+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
169+
kind: OpenStackClusterIdentity
170+
metadata:
171+
name: production-openstack
172+
spec:
173+
secretRef:
174+
name: openstack-credentials
175+
namespace: capo-system
176+
allowedNamespaces: [team-a, team-b]
177+
178+
---
179+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
180+
kind: OpenStackClusterIdentity
181+
metadata:
182+
name: development-openstack
183+
spec:
184+
secretRef:
185+
name: dev-openstack-credentials
186+
namespace: capo-system
187+
namespaceSelector:
188+
matchLabels:
189+
environment: "development"
190+
```
191+
192+
### Use in OpenStackCluster
193+
```yaml
194+
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
195+
kind: OpenStackCluster
196+
metadata:
197+
name: my-cluster
198+
namespace: team-a
199+
spec:
200+
clusterIdentityRef:
201+
name: production-openstack
202+
identityRef: # Fallback for backward compatibility
203+
name: fallback-secret
204+
cloudName: openstack
205+
```
206+
207+
## Implementation Notes
208+
209+
**Controller Changes**: Modify `pkg/scope/provider.go` for dual-path resolution, update cluster controller for identity validation
210+
**API Generation**: Update CRD generation, generate deepcopy/clients/informers, update webhooks
211+
**Documentation**: API reference, migration guides, security best practices
212+
213+
This proposal provides centralized credential management while maintaining full backward compatibility and following established Kubernetes patterns.

0 commit comments

Comments
 (0)