Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Support for system-assigned and user-assigned managed identities - #330

Open
ulucinar wants to merge 6 commits into
crossplane-contrib:masterfrom
ulucinar:fix-164
Open

Support for system-assigned and user-assigned managed identities#330
ulucinar wants to merge 6 commits into
crossplane-contrib:masterfrom
ulucinar:fix-164

Conversation

@ulucinar

@ulucinar ulucinar commented Mar 23, 2022

Copy link
Copy Markdown
Collaborator

Description of your changes

Fixes #164, #292, #319

This PR adds support for system-assigned and user-assigned managed identities, formerly known as Managed Service Identities (MSIs) via the Azure Identity client module.

An example ProviderConfig that uses a system-assigned managed identity is as follows:

apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: example
spec:
  credentials:
    source: InjectedIdentity
  subscriptionID: <Azure subscription ID>

Another example using a user-assigned managed identity:

apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: example
spec:
  credentials:
    source: InjectedIdentity
  subscriptionID: <Azure subscription ID>
  clientID: <Client ID of the user-assigned managed kubelet identity>

I have:

  • Read and followed Crossplane's contribution process.
  • Run make reviewable test to ensure this PR is ready for review.

How has this code been tested

I have successfully provisioned a ResourceGroup and an AKSCluster using a system-assigned managed identity and also a user-assigned managed identity with the ProviderConfigs given above.

- Managed identities are formerly known as MSIs

Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
- If we are using an authentication scheme other than client secret
  returning a map of credentials secret data is no longer possible.
  Thus, we need a change in the function signature.
- azure.GetAuthInfo now returns subscription ID, which is used
  by the downstream ARM resource SDK clients.

Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
Comment thread pkg/clients/compute/aks.go Outdated
Comment on lines 79 to 80
// EnsureManagedCluster ensures the supplied AKS cluster exists, including
// ensuring any required service principals and role assignments exist.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to update this comment since we're no longer ensuring SP creation and its role assignments.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @ezgidemirel. Removed mentions of the service principals and role assignments as we are no longer dealing with them.

Comment thread pkg/clients/compute/aks.go Outdated
Comment on lines 90 to 91
// DeleteManagedCluster deletes the supplied AKS cluster, including its service
// principals and any role assignments.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, we're not deleting SP or its role assignments

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Count: &nodeCount,
VMSize: containerservice.VMSizeTypes(c.Spec.NodeVMSize),
VMSize: to.StringPtr(c.Spec.NodeVMSize),
Mode: containerservice.AgentPoolModeSystem,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though system mode is set in here, I got the following error when I tried to create an AKS cluster with a user-managed identity

Warning  CannotCreateExternalResource  96s (x25 over 3m21s)      managed/akscluster.compute.azure.crossplane.io  cannot create AKSCluster: containerservice.ManagedClustersClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="MustDefineAtLeastOneSystemPool" Message="Must define at least one system pool."

I used following manifest:

apiVersion: compute.azure.crossplane.io/v1alpha3
kind: AKSCluster
metadata:
  name: ezgi-akscluster
  labels:
    example: "true"
spec:
  resourceGroupName: ezgi
  vnetSubnetIDRef:
    name: ezgi-sub
  location: West US 2
  version: "1.21.7"
  nodeCount: 1
  nodeVMSize: Standard_B2s
  dnsNamePrefix: ezgi-aks
  disableRBAC: false
  identity:
    identityNames:
    - ezgiidentity
    type: UserAssigned
  providerConfigRef:
    name: example
  writeConnectionSecretToRef:
    namespace: crossplane-system
    name: ezgi-akscluster

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ezgidemirel,
Thank you for giving this a try. It looks like to be an issue specific to provisioning AKS clusters as you have mentioned below that provisioning some other resources were successful. Using SP credentials, I tried provisioning an AKS cluster with success using the example manifest from this PR. You are using the provider package ulucinar/provider-azure:build-3eacbce2, right?
I will also give it a try using a user-assigned managed identity in ProviderConfig and report back to you, although it should not be related.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello again,
Using the provider package ulucinar/provider-azure:build-3eacbce2, on an AKS cluster with a user-assigned managed kubelet identity, I tried to provision an AKS cluster using the following manifests successfully:

apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: example
spec:
  clientID: <client-id of the user-assigned managed kubelet identity>
  credentials:
    source: InjectedIdentity
  subscriptionID: <Azure subscription ID>

---

apiVersion: compute.azure.crossplane.io/v1alpha3
kind: AKSCluster
metadata:
  name: example-akscluster-alper2
  labels:
    example: "true"
spec:
  resourceGroupName: alper
  location: West US 2
  version: "1.21.7"
  nodeCount: 1
  nodeVMSize: Standard_B2s
  dnsNamePrefix: crossplane-aks
  disableRBAC: false
  identity:
    type: SystemAssigned
  providerConfigRef:
    name: example
  writeConnectionSecretToRef:
    namespace: crossplane-system
    name: example-akscluster

I have also verified accessing the provisioned AKS cluster using the credentials (kubeconfig) stored in the connection secret.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AKS cluster I tried to provision has UserAssigned managed identity. I believe that's the reason why my attempt is failing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ezgidemirel,
The following also succeeded in my cluster:

apiVersion: compute.azure.crossplane.io/v1alpha3
kind: AKSCluster
metadata:
  name: example-akscluster-alper2
  labels:
    example: "true"
spec:
  resourceGroupName: alper
  location: West US 2
  version: "1.21.7"
  nodeCount: 1
  nodeVMSize: Standard_B2s
  dnsNamePrefix: crossplane-aks
  disableRBAC: false
  identity:
    type: UserAssigned
    identityNames:
    - control-plane-identity-alper
  providerConfigRef:
    name: example
  writeConnectionSecretToRef:
    namespace: crossplane-system
    name: example-akscluster

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating resource manifests to use the same location didn't work. However, removing vnetSubnetIDRef from the spec did the trick. I could successfully provision an AKS cluster.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that we are not setting the default node pool's mode to System iff a subnet is specified :)
Fixed the bug and successfully provisioned an AKS cluster by specifying a subnet for its node pool.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much @ezgidemirel for finding this issue and helping me in fixing it. Very much appreciated!

Comment thread pkg/clients/compute/aks.go Outdated
Comment on lines +149 to +152
for _, n := range c.Spec.Identity.IdentityNames {
resourceID := fmt.Sprintf(fmtUserAssignedManagedIdentityID, subscriptionID, c.Spec.ResourceGroupName, n)
p.Identity.UserAssignedIdentities[resourceID] = &containerservice.ManagedClusterIdentityUserAssignedIdentitiesValue{}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still wonder what is the use case of having multiple user identities here :) I'll dive in later.

@ezgidemirel

Copy link
Copy Markdown

I tested the PR with user-assigned managed identity with following steps:

  • Created an identitiy
az identity create --name ezgiidentity --resource-group ezgi --location westeurope
  • Assigned Managed Identity Operator and Contributor roles to it. Seeing these role assignments' effects took some time.
  • Created an AKS cluster and set its identity and its kubelet's identity to the managed one above
 az aks create --resource-group ezgi --name ezgi-cluster --enable-managed-identity --assign-identity $ID --location westeurope
  • Installed crossplane
up uxp installed -n crossplane-system
  • Installed provider built from this branch
kc install provider ulucinar/provider-azure:build-3eacbce2
  • Created a provider config with user-managed identity ID
apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: example
spec:
  credentials:
    source: InjectedIdentity
  subscriptionID: <sub-id>
  clientID: <client-id>
  • Successfully created a resourcegroup with example manifest
  • Successfully created subnet, virtual network with example manifets
  • Failed to create an AKS cluster with following error
Warning  CannotCreateExternalResource  3m16s (x340 over 28m)   managed/akscluster.compute.azure.crossplane.io  cannot create AKSCluster: containerservice.ManagedClustersClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="MustDefineAtLeastOneSystemPool" Message="Must define at least one system pool."

While preparing a cluster with user-managed identity, I noticed that kubelet's identity should also be set. Following curl command helped me to troubleshoot. I created a pod with curl binary in the cluster and executed it inside it:

curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s

Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
…d identities

instead of the plain identity names

Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
@ulucinar
ulucinar requested review from ezgidemirel and turkenh April 28, 2022 20:28

@ezgidemirel ezgidemirel left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a ton @ulucinar for adding managed identity support, fixing an existing bug and, cleaning up some SP generation code for AKS clusters. I learned a lot while reviewing/testing it. Amazing work from an amazing mentor :)

@turkenh turkenh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@ghost

ghost commented May 27, 2022

Copy link
Copy Markdown

@turkenh I have a client who would like to use Manage Identities. I would be happy to try and help fix whatever CodeCov is saying is wrong but I do not have access to see what the problem is. Can you let us know what it is or help to get it addressed so that we can all start using these amazingly helpful changes from @ulucinar?

@carct

carct commented Aug 31, 2022

Copy link
Copy Markdown

any estimate on this feature delivery? it would be really useful

@marianheinsen

Copy link
Copy Markdown

I would also love to see this PR merged because it would simplify our current setup using Crossplane with Service Principals a lot!

@ahilmathew

Copy link
Copy Markdown

Any chance we can get this merged?

@ghost

ghost commented Jul 26, 2023

Copy link
Copy Markdown

Any ETA here? Hoping this helps me automate giving the role "DNS Zone Contributor" to my AKS clusters so external-dns will work.

@mazilu88

Copy link
Copy Markdown

I'm looking at implementing this provider. The feature you've introduced aligns perfectly with our current needs. Thank you for your valuable work @ulucinar !

I see this was approved on May 9, 2022 but is still not merged because of codegov check.

@turkenh / @ezgidemirel if possible, could you revisit this matter for a second evaluation? The report is no longer available, and a previous user mentioned that external users don't have access to it. Your assistance in this matter would be greatly appreciated.

@undefinedhuman

Copy link
Copy Markdown

Any updates? Would love to see this feature implemented

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(feat): Azure MSI authentication

8 participants