Skip to content

Commit 2c05a35

Browse files
committed
ARO-24514 - make AROControlPlane.spec.identityRef optional
1 parent 6066418 commit 2c05a35

File tree

12 files changed

+681
-218
lines changed

12 files changed

+681
-218
lines changed

azure/scope/arocontrolplane.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,18 @@ func NewAROControlPlaneScope(ctx context.Context, params AROControlPlaneScopePar
8181
return nil, errors.New("failed to generate new scope from nil AROControlPlane")
8282
}
8383

84-
// Initialize Azure SDK credentials in the following cases:
85-
// 1. Field-based mode (len(Resources) == 0): Always initialize credentials
86-
// 2. Resources mode with IdentityRef set: Initialize CAPZ credentials for hybrid scenarios
87-
// 3. Resources mode without IdentityRef: Skip credential initialization, ASO handles authentication
84+
// Initialize Azure SDK credentials only when IdentityRef is set.
85+
// With identityRef: Initialize CAPZ credentials for Key Vault operations
86+
// Without identityRef: Skip credential initialization, ASO handles authentication
87+
//
88+
// When identityRef is not set, CAPZ cannot perform Key Vault operations:
89+
// - Cannot check for encryption key existence
90+
// - Cannot create encryption keys
91+
// - Cannot auto-propagate key versions to HcpOpenShiftCluster
92+
// Customers must manually create the vault and key via ASO and specify the key version in HcpOpenShiftCluster.
93+
//
94+
// Note: The check for empty Resources is defensive - the webhook now requires Resources mode,
95+
// so Resources cannot be empty in practice.
8896
shouldInitCredentials := len(params.ControlPlane.Spec.Resources) == 0 || params.ControlPlane.Spec.IdentityRef != nil
8997

9098
if shouldInitCredentials {

azure/scope/aromachinepool.go

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,36 +41,28 @@ import (
4141

4242
// AROMachinePoolScopeParams defines the input parameters used to create a new Scope.
4343
type AROMachinePoolScopeParams struct {
44-
AzureClients
45-
Client client.Client
46-
Cluster *clusterv1.Cluster
47-
MachinePool *clusterv1.MachinePool
48-
ControlPlane *cplane.AROControlPlane
49-
AROMachinePool *v1beta2.AROMachinePool
50-
Cache *AROMachinePoolCache
51-
Timeouts azure.AsyncReconciler
52-
CredentialCache azure.CredentialCache
53-
AROControlPlaneScope *AROControlPlaneScope
44+
Client client.Client
45+
Cluster *clusterv1.Cluster
46+
MachinePool *clusterv1.MachinePool
47+
ControlPlane *cplane.AROControlPlane
48+
AROMachinePool *v1beta2.AROMachinePool
49+
Cache *AROMachinePoolCache
50+
Timeouts azure.AsyncReconciler
5451
}
5552

5653
// NewAROMachinePoolScope creates a new Scope from the supplied parameters.
5754
// This is meant to be called for each reconcile iteration.
5855
func NewAROMachinePoolScope(ctx context.Context, params AROMachinePoolScopeParams) (*AROMachinePoolScope, error) {
59-
ctx, _, done := tele.StartSpanWithLogger(ctx, "azure.aroMachinePoolScope.NewAROMachinePoolScope")
56+
_, _, done := tele.StartSpanWithLogger(ctx, "azure.aroMachinePoolScope.NewAROMachinePoolScope")
6057
defer done()
6158

6259
if params.AROMachinePool == nil {
6360
return nil, errors.New("failed to generate new scope from nil AROMachinePool")
6461
}
6562

66-
credentialsProvider, err := NewAzureCredentialsProvider(ctx, params.CredentialCache, params.Client, params.ControlPlane.Spec.IdentityRef, params.AROMachinePool.Namespace)
67-
if err != nil {
68-
return nil, errors.Wrap(err, "failed to init credentials provider")
69-
}
70-
err = params.AzureClients.setCredentialsWithProvider(ctx, params.ControlPlane.Spec.SubscriptionID, params.ControlPlane.Spec.AzureEnvironment, credentialsProvider)
71-
if err != nil {
72-
return nil, errors.Wrap(err, "failed to configure azure settings and credentials for Identity")
73-
}
63+
// AROMachinePool no longer requires Azure credentials
64+
// ProviderIDList is populated from workload cluster nodes instead of Azure VM API
65+
// ASO handles all Azure operations via its own authentication (serviceoperator.azure.com/credential-from annotations)
7466

7567
if params.Cache == nil {
7668
params.Cache = &AROMachinePoolCache{}
@@ -89,7 +81,6 @@ func NewAROMachinePoolScope(ctx context.Context, params AROMachinePoolScopeParam
8981
Client: params.Client,
9082
patchHelper: helper,
9183
cache: params.Cache,
92-
AzureClients: params.AzureClients,
9384
Cluster: params.Cluster,
9485
MachinePool: params.MachinePool,
9586
ControlPlane: params.ControlPlane,
@@ -106,7 +97,6 @@ type AROMachinePoolScope struct {
10697
capiMachinePoolPatchHelper *patch.Helper
10798
cache *AROMachinePoolCache
10899

109-
AzureClients
110100
Cluster *clusterv1.Cluster
111101
ControlPlane *cplane.AROControlPlane
112102
MachinePool *clusterv1.MachinePool
@@ -218,11 +208,6 @@ func (s *AROMachinePoolScope) UpdatePatchStatus(condition clusterv1.ConditionTyp
218208
type AROMachinePoolCache struct {
219209
}
220210

221-
// BaseURI returns the Azure ResourceManagerEndpoint.
222-
func (s *AROMachinePoolScope) BaseURI() string {
223-
return s.ResourceManagerEndpoint
224-
}
225-
226211
// GetClient returns the controller-runtime client.
227212
func (s *AROMachinePoolScope) GetClient() client.Client {
228213
return s.Client

azure/services/keyvaults/keyvault.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ func (s *Service) Reconcile(ctx context.Context) error {
8585
// Get all KeyVault specs
8686
keyVaultSpecs := s.Scope.KeyVaultSpecs()
8787

88-
// In resources mode (e.g., ARO HCP), KeyVault vault resources are managed by ASO,
88+
// For ARO HCP (resources mode), KeyVault vault resources are managed by ASO,
8989
// so KeyVaultSpecs may be empty. However, we still need to ensure encryption keys exist.
90+
// For legacy non-ARO clusters, KeyVaultSpecs contains vault definitions to reconcile.
9091
if len(keyVaultSpecs) > 0 {
91-
// Process each KeyVault spec (field-based mode)
92+
// Process each KeyVault spec (legacy path - not used by ARO HCP)
9293
for _, keyVaultSpec := range keyVaultSpecs {
9394
log.V(2).Info("reconciling KeyVault", "keyvault", keyVaultSpec.ResourceName())
9495

@@ -100,8 +101,9 @@ func (s *Service) Reconcile(ctx context.Context) error {
100101
}
101102
}
102103

103-
// Ensure the ETCD encryption key exists (works in both field-based and resources modes)
104-
// In resources mode, the vault is managed by ASO but keys must be managed via Azure SDK
104+
// Ensure the ETCD encryption key exists
105+
// For ARO HCP (resources mode): vault is managed by ASO, keys managed via Azure SDK
106+
// For legacy clusters: both vault and keys managed via Azure SDK
105107
if err := s.EnsureETCDEncryptionKey(ctx, s.Scope); err != nil {
106108
return errors.Wrap(err, "failed to ensure ETCD encryption key exists")
107109
}

config/crd/bases/controlplane.cluster.x-k8s.io_arocontrolplanes.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,12 @@ spec:
7979
identityRef:
8080
description: |-
8181
IdentityRef is a reference to an identity to be used when reconciling the aro control plane.
82-
If no identity is specified, the default identity for this controller will be used.
82+
This field is optional. When set, CAPZ will initialize Azure SDK credentials and perform
83+
Key Vault operations (check existence, create encryption keys, propagate key versions).
84+
85+
When NOT set (ASO credential-based mode), ASO handles authentication via
86+
serviceoperator.azure.com/credential-from annotations, and customers must manually
87+
create the vault and encryption key via ASO and specify the keyVersion in HcpOpenShiftCluster spec.
8388
properties:
8489
apiVersion:
8590
description: API version of the referent.

0 commit comments

Comments
 (0)