Skip to content

Commit

Permalink
Set aso secret annotation in aso.go
Browse files Browse the repository at this point in the history
  • Loading branch information
adriananeci committed Jul 13, 2023
1 parent 32cde27 commit dab4d64
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 15 deletions.
2 changes: 1 addition & 1 deletion azure/scope/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (c *AzureClients) setCredentialsWithProvider(ctx context.Context, subscript
}
c.Values[auth.ClientSecret] = strings.TrimSuffix(clientSecret, "\n")

c.Authorizer, err = credentialsProvider.GetAuthorizer(ctx, c.ResourceManagerEndpoint, c.Environment.ActiveDirectoryEndpoint, c.Environment.TokenAudience)
c.Authorizer, err = credentialsProvider.GetAuthorizer(ctx, c.ResourceManagerEndpoint, c.Environment.ActiveDirectoryEndpoint, c.Environment.TokenAudience, c.SubscriptionID())
return err
}

Expand Down
13 changes: 13 additions & 0 deletions azure/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,19 @@ func (s *ClusterScope) ClusterName() string {
return s.Cluster.Name
}

// AzureClusterIdentityName returns the azure cluster identity name.
func (s *ClusterScope) AzureClusterIdentityName() string {
if s.AzureCluster.Spec.IdentityRef == nil {
return ""
}
return s.AzureCluster.Spec.IdentityRef.Name
}

// SubscriptionID returns the Azure client Subscription ID.
func (s *ClusterScope) SubscriptionID() string {
return s.AzureClients.SubscriptionID()
}

// Namespace returns the cluster namespace.
func (s *ClusterScope) Namespace() string {
return s.Cluster.Namespace
Expand Down
23 changes: 15 additions & 8 deletions azure/scope/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const azureSecretKey = "clientSecret"

// CredentialsProvider defines the behavior for azure identity based credential providers.
type CredentialsProvider interface {
GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience string) (autorest.Authorizer, error)
GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID string) (autorest.Authorizer, error)
GetClientID() string
GetClientSecret(ctx context.Context) (string, error)
GetTenantID() string
Expand Down Expand Up @@ -104,12 +104,12 @@ func NewAzureClusterCredentialsProvider(ctx context.Context, kubeClient client.C
}

// GetAuthorizer returns an Azure authorizer based on the provided azure identity. It delegates to AzureCredentialsProvider with AzureCluster metadata.
func (p *AzureClusterCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience string) (autorest.Authorizer, error) {
if err := reconcileASOSecret(ctx, p.AzureCredentialsProvider.Identity, p.Client, p.AzureCluster.Spec.SubscriptionID); err != nil {
func (p *AzureClusterCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID string) (autorest.Authorizer, error) {
if err := reconcileASOSecret(ctx, p.AzureCredentialsProvider.Identity, p.Client, subscriptionID); err != nil {
return nil, errors.Errorf("failed to reconcile ASO secret related to AzureClusterIdentity %q/%q: %v", p.Identity.Namespace, p.Identity.Name, err)
}
p.ASOSecret = identity.GetASOSecretName(p.AzureCluster.Spec.SubscriptionID, p.AzureCredentialsProvider.Identity.Name)
return p.AzureCredentialsProvider.GetAuthorizer(ctx, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, p.AzureCluster.ObjectMeta)
return p.AzureCredentialsProvider.GetAuthorizer(ctx, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID, p.AzureCluster.ObjectMeta)
}

// NewManagedControlPlaneCredentialsProvider creates a new ManagedControlPlaneCredentialsProvider from the supplied inputs.
Expand Down Expand Up @@ -140,19 +140,26 @@ func NewManagedControlPlaneCredentialsProvider(ctx context.Context, kubeClient c
}

// GetAuthorizer returns an Azure authorizer based on the provided azure identity. It delegates to AzureCredentialsProvider with AzureManagedControlPlane metadata.
func (p *ManagedControlPlaneCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience string) (autorest.Authorizer, error) {
if err := reconcileASOSecret(ctx, p.AzureCredentialsProvider.Identity, p.Client, p.AzureManagedControlPlane.Spec.SubscriptionID); err != nil {
func (p *ManagedControlPlaneCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID string) (autorest.Authorizer, error) {
if err := reconcileASOSecret(ctx, p.AzureCredentialsProvider.Identity, p.Client, subscriptionID); err != nil {
return nil, errors.Errorf("failed to reconcile ASO secret related to AzureClusterIdentity %q/%q: %v", p.Identity.Namespace, p.Identity.Name, err)
}
p.ASOSecret = identity.GetASOSecretName(p.AzureManagedControlPlane.Spec.SubscriptionID, p.AzureCredentialsProvider.Identity.Name)

return p.AzureCredentialsProvider.GetAuthorizer(ctx, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, p.AzureManagedControlPlane.ObjectMeta)
return p.AzureCredentialsProvider.GetAuthorizer(ctx, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID, p.AzureManagedControlPlane.ObjectMeta)
}

// GetAuthorizer returns an Azure authorizer based on the provided azure identity and cluster metadata.
func (p *AzureCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience string, clusterMeta metav1.ObjectMeta) (autorest.Authorizer, error) {
func (p *AzureCredentialsProvider) GetAuthorizer(ctx context.Context, resourceManagerEndpoint, activeDirectoryEndpoint, tokenAudience, subscriptionID string, clusterMeta metav1.ObjectMeta) (autorest.Authorizer, error) {
var authErr error
var cred azcore.TokenCredential

// reconcile ASO secret first
if err := reconcileASOSecret(ctx, p.Identity, p.Client, subscriptionID); err != nil {
return nil, errors.Errorf("failed to reconcile ASO secret related to AzureClusterIdentity %q/%q: %v", p.Identity.Namespace, p.Identity.Name, err)
}
p.ASOSecret = identity.GetASOSecretName(subscriptionID, p.Identity.Name)

switch p.Identity.Spec.Type {
case infrav1.WorkloadIdentity:
azwiCredOptions, err := NewWorkloadIdentityCredentialOptions().
Expand Down
10 changes: 9 additions & 1 deletion azure/scope/managedcontrolplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,19 @@ func (s *ManagedControlPlaneScope) NodeResourceGroup() string {
return s.ControlPlane.Spec.NodeResourceGroupName
}

// ClusterName returns the managed control plane's name.
// ClusterName returns the cluster name.
func (s *ManagedControlPlaneScope) ClusterName() string {
return s.Cluster.Name
}

// AzureClusterIdentityName returns the azure cluster identity name.
func (s *ManagedControlPlaneScope) AzureClusterIdentityName() string {
if s.ControlPlane == nil || s.ControlPlane.Spec.IdentityRef == nil {
return ""
}
return s.ControlPlane.Spec.IdentityRef.Name
}

// Location returns the managed control plane's Azure location, or an empty string.
func (s *ManagedControlPlaneScope) Location() string {
if s.ControlPlane == nil {
Expand Down
22 changes: 18 additions & 4 deletions azure/services/aso/aso.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package aso
import (
"context"
"fmt"
"sigs.k8s.io/cluster-api-provider-azure/util/identity"
"time"

"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
Expand Down Expand Up @@ -47,21 +48,27 @@ const (

createOrUpdateFutureType = "ASOCreateOrUpdate"
deleteFutureType = "ASODelete"

SecretNameAnnotation = "serviceoperator.azure.com/credential-from"
)

// Service is an implementation of the Reconciler interface. It handles creation
// and deletion of resources using ASO.
type Service struct {
client.Client

clusterName string
clusterName string
azureClusterIdentityName string
subscriptionID string
}

// New creates a new ASO service.
func New(ctrlClient client.Client, clusterName string) *Service {
func New(ctrlClient client.Client, clusterName, azureClusterIdentityName, subscriptionID string) *Service {
return &Service{
Client: ctrlClient,
clusterName: clusterName,
Client: ctrlClient,
clusterName: clusterName,
azureClusterIdentityName: azureClusterIdentityName,
subscriptionID: subscriptionID,
}
}

Expand Down Expand Up @@ -163,13 +170,20 @@ func (s *Service) CreateOrUpdateResource(ctx context.Context, spec azure.ASOReso
// Azure and the ASO resource will be adopted by changing this
// annotation to "manage".
annotations[ReconcilePolicyAnnotation] = ReconcilePolicySkip

} else {
adopt = adopt || spec.WasManaged(existing)
}
if adopt {
annotations[ReconcilePolicyAnnotation] = ReconcilePolicyManage
}

// Set the secret name annotation if AzureClusterIdentity name is not empty in order to leverage the ASO resource credential
//scope as defined in https://azure.github.io/azure-service-operator/guide/authentication/credential-scope/#resource-scope.
if s.azureClusterIdentityName != "" {
annotations[SecretNameAnnotation] = identity.GetASOSecretName(s.azureClusterIdentityName, s.subscriptionID)
}

if len(labels) > 0 {
parameters.SetLabels(maps.Merge(parameters.GetLabels(), labels))
}
Expand Down
4 changes: 3 additions & 1 deletion azure/services/asogroups/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ type GroupScope interface {
ASOGroupSpec() azure.ASOResourceSpecGetter
GetClient() client.Client
ClusterName() string
AzureClusterIdentityName() string
SubscriptionID() string
}

// New creates a new service.
func New(scope GroupScope) *Service {
return &Service{
Scope: scope,
Reconciler: aso.New(scope.GetClient(), scope.ClusterName()),
Reconciler: aso.New(scope.GetClient(), scope.ClusterName(), scope.AzureClusterIdentityName(), scope.SubscriptionID()),
}
}

Expand Down
28 changes: 28 additions & 0 deletions azure/services/asogroups/mock_asogroups/groups_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions util/identity/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ func GetAzureIdentityName(clusterName, clusterNamespace, identityName string) st

// GetASOSecretName formats the name of the ASO Secret created by the capz controller.
func GetASOSecretName(subscriptionID, clusterIdentitySecret string) string {
if subscriptionID == "" {
return clusterIdentitySecret
}
return fmt.Sprintf("%s-%s", clusterIdentitySecret, subscriptionID)
}

0 comments on commit dab4d64

Please sign in to comment.