From 00c8c4d9938391593cf4577477cf83d20d4195bd Mon Sep 17 00:00:00 2001 From: Bernard Kim Date: Mon, 18 Aug 2025 12:15:58 -0700 Subject: [PATCH 1/2] Support azure joining with VMSS --- lib/auth/join_azure.go | 12 +++++++++--- lib/auth/join_azure_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/auth/join_azure.go b/lib/auth/join_azure.go index 0f3b14dc9d8f1..1c6ffd5c88db4 100644 --- a/lib/auth/join_azure.go +++ b/lib/auth/join_azure.go @@ -54,6 +54,8 @@ const ( azureUserAgent = "teleport" // azureVirtualMachine specifies the Azure virtual machine resource type. azureVirtualMachine = "virtualMachines" + // azureVirtualMachineScaleSet specifies the Azure virtual machine scale set resource type. + azureVirtualMachineScaleSet = "virtualMachineScaleSets" ) // Structs for unmarshaling attested data. Schema can be found at @@ -348,10 +350,14 @@ func claimsToIdentifiers(tokenClaims *accessTokenClaims) (subscriptionID, resour if err != nil { return "", "", trace.Wrap(err, "failed to parse resource id from claims") } - if !slices.Contains(resourceID.ResourceType.Types, azureVirtualMachine) { - return "", "", trace.BadParameter("unexpected resource type: %q", resourceID.ResourceType.Type) + + supportedResourceTypes := []string{azureVirtualMachine, azureVirtualMachineScaleSet} + for _, resourceType := range resourceID.ResourceType.Types { + if slices.Contains(supportedResourceTypes, resourceType) { + return resourceID.SubscriptionID, resourceID.ResourceGroupName, nil + } } - return resourceID.SubscriptionID, resourceID.ResourceGroupName, nil + return "", "", trace.BadParameter("unexpected resource type: %q", resourceID.ResourceType.Type) } func checkAzureAllowRules(vmID string, attrs *workloadidentityv1pb.JoinAttrsAzure, token *types.ProvisionTokenV2) error { diff --git a/lib/auth/join_azure_test.go b/lib/auth/join_azure_test.go index 29b4d0e483db9..1214c7ac22074 100644 --- a/lib/auth/join_azure_test.go +++ b/lib/auth/join_azure_test.go @@ -103,6 +103,10 @@ func withChallengeAzure(challenge string) azureChallengeResponseOption { } } +func vmssResourceID(subscription, resourceGroup, name string) string { + return resourceID("Microsoft.Compute/virtualMachineScaleSets", subscription, resourceGroup, name) +} + func vmResourceID(subscription, resourceGroup, name string) string { return resourceID("Microsoft.Compute/virtualMachines", subscription, resourceGroup, name) } @@ -776,6 +780,28 @@ func TestAuth_RegisterUsingAzureClaims(t *testing.T) { certs: []*x509.Certificate{tlsConfig.Certificate}, assertError: isAccessDenied, }, + { + name: "vmss resource type", + requestTokenName: "test-token", + tokenSubscription: "token-subscription", + tokenVMID: defaultVMID, + tokenManagedIdentityResourceID: vmssResourceID("token-subscription", defaultResourceGroup, defaultVMName), + tokenSpec: types.ProvisionTokenSpecV2{ + Roles: []types.SystemRole{types.RoleNode}, + Azure: &types.ProvisionTokenSpecV2Azure{ + Allow: []*types.ProvisionTokenSpecV2Azure_Rule{ + { + Subscription: "token-subscription", + ResourceGroups: []string{defaultResourceGroup}, + }, + }, + }, + JoinMethod: types.JoinMethodAzure, + }, + verify: mockVerifyToken(nil), + certs: []*x509.Certificate{tlsConfig.Certificate}, + assertError: require.NoError, + }, } for _, tc := range tests { From e4548420ceccfcb3791bcaecbb1b48b65ada6680 Mon Sep 17 00:00:00 2001 From: Bernard Kim Date: Mon, 18 Aug 2025 14:52:14 -0700 Subject: [PATCH 2/2] Use switch statement --- lib/auth/join_azure.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/auth/join_azure.go b/lib/auth/join_azure.go index 1c6ffd5c88db4..c1d0da6be1c5f 100644 --- a/lib/auth/join_azure.go +++ b/lib/auth/join_azure.go @@ -351,9 +351,9 @@ func claimsToIdentifiers(tokenClaims *accessTokenClaims) (subscriptionID, resour return "", "", trace.Wrap(err, "failed to parse resource id from claims") } - supportedResourceTypes := []string{azureVirtualMachine, azureVirtualMachineScaleSet} for _, resourceType := range resourceID.ResourceType.Types { - if slices.Contains(supportedResourceTypes, resourceType) { + switch resourceType { + case azureVirtualMachine, azureVirtualMachineScaleSet: return resourceID.SubscriptionID, resourceID.ResourceGroupName, nil } }