/// <summary> /// Retrieves the encryption extension status from the extension instance view. /// An error observable will be returned if /// 1. extension is not installed /// 2. extension is not provisioned successfully /// 2. extension status could be retrieved (either not found or empty). /// </summary> /// <param name="statusEmptyErrorMessage">The error message to emit if unable to locate the status.</param> /// <return>An observable that emits status message.</return> ///GENMHASH:5D5D4450A8A3676D4AB254F68D0D6E6F:FD676570747D9407B4E5BA65CEA5012A private async Task <string> RetrieveEncryptionExtensionStatusStringAsync(string statusEmptyErrorMessage, CancellationToken cancellationToken = default(CancellationToken)) { IVirtualMachineExtension encryptionExtension = await GetEncryptionExtensionInstalledInVMAsync(cancellationToken); if (encryptionExtension == null) { throw new Exception(ERROR_ENCRYPTION_EXTENSION_NOT_FOUND); } if (!encryptionExtension.ProvisioningState.Equals("Succeeded", StringComparison.OrdinalIgnoreCase)) { throw new Exception(string.Format(ERROR_NON_SUCCESS_PROVISIONING_STATE, encryptionExtension.ProvisioningState)); } VirtualMachineExtensionInstanceView instanceView = await encryptionExtension.GetInstanceViewAsync(cancellationToken); if (instanceView == null || instanceView.Statuses == null || instanceView.Statuses.Count == 0) { throw new Exception(ERROR_EXPECTED_ENCRYPTION_EXTENSION_STATUS_NOT_FOUND); } string extensionStatus = instanceView.Statuses[0].Message; if (string.IsNullOrEmpty(extensionStatus)) { throw new Exception(statusEmptyErrorMessage); } return(extensionStatus); }
/// <summary> /// Disables encryption on the given disk volume. /// </summary> /// <param name="volumeType">The disk volume.</param> /// <return>An observable that emits the decryption status.</return> ///GENMHASH:B980B0A762D67885E3B127392FD42890:A65E5C07D8DA37A2AB5EC199276933B9 internal async Task <Microsoft.Azure.Management.Compute.Fluent.IDiskVolumeEncryptionMonitor> DisableEncryptionAsync(DiskVolumeType volumeType, CancellationToken cancellationToken = default(CancellationToken)) { var encryptConfig = EncryptionSettings.CreateDisable(volumeType); await ValidateBeforeDecryptAsync(volumeType, cancellationToken); // Update the encryption extension if already installed // IVirtualMachineExtension extension = await GetEncryptionExtensionInstalledInVMAsync(cancellationToken); IVirtualMachine virtualMachine = await UpdateEncryptionExtensionAsync(encryptConfig, extension, cancellationToken); bool isNoAAD = EncryptionExtensionIdentifier.IsNoAADVersion(osType, extension.VersionName); if (virtualMachine != null && !isNoAAD) { // Validate and retrieve the encryption extension status // string status = await RetrieveEncryptionExtensionStatusStringAsync(ERROR_ENCRYPTION_EXTENSION_STATUS_IS_EMPTY, cancellationToken); // Update the VM's OS profile by marking encryption disabled // virtualMachine = await UpdateVMStorageProfileAsync(encryptConfig, cancellationToken); } // Gets the encryption status // return(await GetDiskVolumeEncryptDecryptStatusAsync(virtualMachine, isNoAAD, cancellationToken)); }
/// <summary> /// Enables encryption. /// </summary> /// <param name="encryptionSettings">The settings to be used for encryption extension.</param> /// <param name="">The Windows or Linux encryption settings.</param> /// <return>An observable that emits the encryption status.</return> ///GENMHASH:FB7DBA27A41CC76685F21AB0A9729C82:D88D73A86520940C4EA57E9CEEA1516F internal async Task <IDiskVolumeEncryptionMonitor> EnableEncryptionAsync <T>(VirtualMachineEncryptionConfiguration <T> encryptionSettings, CancellationToken cancellationToken = default(CancellationToken)) where T : VirtualMachineEncryptionConfiguration <T> { var encryptConfig = EncryptionSettings.CreateEnable <T>(encryptionSettings); // Update the encryption extension if already installed // IVirtualMachineExtension extension = await GetEncryptionExtensionInstalledInVMAsync(cancellationToken); IVirtualMachine virtualMachine = await UpdateEncryptionExtensionAsync(encryptConfig, extension, cancellationToken); if (virtualMachine == null) { // If encryption extension is not installed then install it // virtualMachine = await InstallEncryptionExtensionAsync(encryptConfig, cancellationToken); } if (encryptConfig.RequestedForLegacyEncryptExtension) { // Retrieve the encryption key URL after extension install or update // string keyVaultSecretUrl = await RetrieveEncryptionExtensionStatusStringAsync(ERROR_EXPECTED_KEY_VAULT_URL_NOT_FOUND, cancellationToken); // Update the VM's OS Disk (in storage profile) with the encryption metadata // virtualMachine = await UpdateVMStorageProfileAsync(encryptConfig, keyVaultSecretUrl, cancellationToken); // Gets the encryption status // } return(await GetDiskVolumeEncryptDecryptStatusAsync(virtualMachine, encryptConfig.RequestedForNoAADEncryptExtension, cancellationToken)); }
private static void InstallNetworkWatcherExtension(IVirtualMachine vm, TraceWriter log = null) { IVirtualMachineExtension extension = null; IReadOnlyDictionary <string, IVirtualMachineExtension> extensionList = vm.ListExtensions(); if (extensionList.Count > 0) { extension = extensionList.First(x => x.Value.PublisherName == "Microsoft.Azure.NetworkWatcher").Value; } if (extension == null) { log.Info($"VM doesn't have Network Watcher Extension... Installing"); vm.Update() .DefineNewExtension("packetcapture") .WithPublisher("Microsoft.Azure.NetworkWatcher") .WithType("NetworkWatcherAgentWindows") // TODO: determine OS family, can be NetworkWatcherAgentLinux .WithVersion("1.4") .Attach(); log?.Info("Installed Extension on " + vm.Name); } else { log.Info($"VM already has Network Watcher Extension: proceeding..."); } }
/// <summary> /// Retrieves encryption extension installed in the virtual machine, if the extension is /// not installed then return an empty observable. /// </summary> /// <return>An observable that emits the encryption extension installed in the virtual machine.</return> ///GENMHASH:9E0CF934F182F50D2FE7A72E02617F94:324B026FB14C16BEDA7B060212E59DE0 private async Task <Microsoft.Azure.Management.Compute.Fluent.IVirtualMachineExtension> GetEncryptionExtensionInstalledInVMAsync(CancellationToken cancellationToken = default(CancellationToken)) { var extensions = await virtualMachine.ListExtensionsAsync(cancellationToken); IVirtualMachineExtension encryptionExtension = extensions .FirstOrDefault(e => e.PublisherName.Equals(encryptionExtensionPublisher, StringComparison.OrdinalIgnoreCase) && e.TypeName.Equals(EncryptionExtensionType(), StringComparison.OrdinalIgnoreCase)); return(encryptionExtension); }
/// <summary> /// Updates the encryption extension in the virtual machine using provided configuration. /// If extension is not installed then this method return null else the updated vm. /// </summary> /// <param name="encryptConfig">The volume encryption configuration.</param> /// <return>Tasks that emits updated virtual machine.</return> ///GENMHASH:99CCEB2CE75C64E72E8D4CB8CFDA73B5:B2EAD454D0D489C6F6AC659E4EB949F0 private async Task <Microsoft.Azure.Management.Compute.Fluent.IVirtualMachine> UpdateEncryptionExtensionAsync(EnableDisableEncryptConfig encryptConfig, CancellationToken cancellationToken = default(CancellationToken)) { IVirtualMachineExtension extension = await GetEncryptionExtensionInstalledInVMAsync(cancellationToken); if (extension == null) { return(await Task.FromResult <IVirtualMachine>(null)); } return(await virtualMachine.Update() .UpdateExtension(extension.Name) .WithPublicSettings(encryptConfig.ExtensionPublicSettings()) .WithProtectedSettings(encryptConfig.ExtensionProtectedSettings()) .Parent() .ApplyAsync(cancellationToken)); }
private static void InstallNetworkWatcherExtension(IVirtualMachine vm, TraceWriter log = null) { IVirtualMachineExtension extension = vm.ListExtensions().First(x => x.Value.PublisherName == "Microsoft.Azure.NetworkWatcher").Value; if (extension == null) { vm.Update() .DefineNewExtension("packetcapture") .WithPublisher("Microsoft.Azure.NetworkWatcher") .WithType("NetworkWatcherAgentWindows") // TODO: determine OS family, can be NetworkWatcherAgentLinux .WithVersion("1.4") .Attach(); log?.Info("Installed Extension on " + vm.Name); } }
public void CanSetMSIOnNewOrExistingVMWithoutRoleAssignment() { using (var context = FluentMockContext.Start(GetType().FullName)) { var groupName = TestUtilities.GenerateName("rgmsi"); var region = Region.USSouthCentral; var vmName = "javavm"; IAzure azure = null; try { azure = TestHelper.CreateRollupClient(); // Create a virtual machine with just MSI enabled without role and scope. // IVirtualMachine virtualMachine = azure.VirtualMachines .Define(vmName) .WithRegion(region) .WithNewResourceGroup(groupName) .WithNewPrimaryNetwork("10.0.0.0/28") .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer16_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("abc!@#F0orL") .WithSize(VirtualMachineSizeTypes.StandardDS2V2) .WithOSDiskCaching(CachingTypes.ReadWrite) .WithSystemAssignedManagedServiceIdentity() .Create(); Assert.NotNull(virtualMachine); Assert.NotNull(virtualMachine.Inner); Assert.True(virtualMachine.IsManagedServiceIdentityEnabled); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityTenantId); // Ensure the MSI extension is set // var extensions = virtualMachine.ListExtensions(); IVirtualMachineExtension msiExtension = null; foreach (var extension in extensions.Values) { if (extension.PublisherName.Equals("Microsoft.ManagedIdentity", StringComparison.OrdinalIgnoreCase) && extension.TypeName.Equals("ManagedIdentityExtensionForLinux", StringComparison.OrdinalIgnoreCase)) { msiExtension = extension; break; } } Assert.NotNull(msiExtension); // Check the default token port // var publicSettings = msiExtension.PublicSettings; Assert.NotNull(publicSettings); Assert.True(publicSettings.ContainsKey("port")); Object portObj = publicSettings["port"]; Assert.NotNull(portObj); int?port = ObjectToInteger(portObj); Assert.True(port.HasValue); Assert.NotNull(port); Assert.Equal(50342, port); var authenticatedClient = TestHelper.CreateAuthenticatedClient(); // Ensure NO role assigned for resource group // var resourceGroup = azure.ResourceGroups.GetByName(virtualMachine.ResourceGroupName); var rgRoleAssignments1 = authenticatedClient.RoleAssignments.ListByScope(resourceGroup.Id); Assert.NotNull(rgRoleAssignments1); bool found = false; foreach (var roleAssignment in rgRoleAssignments1) { if (roleAssignment.PrincipalId != null && roleAssignment.PrincipalId.Equals(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId, StringComparison.OrdinalIgnoreCase)) { found = true; break; } } Assert.False(found, "Resource group should not have a role assignment with virtual machine MSI principal"); virtualMachine = virtualMachine.Update() .WithSystemAssignedManagedServiceIdentity(50343) .Apply(); Assert.NotNull(virtualMachine); Assert.NotNull(virtualMachine.Inner); Assert.True(virtualMachine.IsManagedServiceIdentityEnabled); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityTenantId); extensions = virtualMachine.ListExtensions(); msiExtension = null; foreach (var extension in extensions.Values) { if (extension.PublisherName.Equals("Microsoft.ManagedIdentity", StringComparison.OrdinalIgnoreCase) && extension.TypeName.Equals("ManagedIdentityExtensionForLinux", StringComparison.OrdinalIgnoreCase)) { msiExtension = extension; break; } } Assert.NotNull(msiExtension); // Check the default token port // publicSettings = msiExtension.PublicSettings; Assert.NotNull(publicSettings); Assert.True(publicSettings.ContainsKey("port")); portObj = publicSettings["port"]; Assert.NotNull(portObj); port = ObjectToInteger(portObj); Assert.True(port.HasValue); Assert.NotNull(port); Assert.Equal(50343, port); rgRoleAssignments1 = authenticatedClient.RoleAssignments.ListByScope(resourceGroup.Id); Assert.NotNull(rgRoleAssignments1); found = false; foreach (var roleAssignment in rgRoleAssignments1) { if (roleAssignment.PrincipalId != null && roleAssignment.PrincipalId.Equals(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId, StringComparison.OrdinalIgnoreCase)) { found = true; break; } } Assert.False(found, "Resource group should not have a role assignment with virtual machine MSI principal"); } finally { try { if (azure != null) { azure.ResourceGroups.BeginDeleteByName(groupName); } } catch { } } } }
public void CanHandleExtensionReference() { using (var context = FluentMockContext.Start(GetType().FullName)) { string rgName = TestUtilities.GenerateName("vmexttest"); string location = "eastus"; string vmName = "javavm"; var azure = TestHelper.CreateRollupClient(); // Create a Linux VM // try { var vm = azure.VirtualMachines .Define(vmName) .WithRegion(location) .WithNewResourceGroup(rgName) .WithNewPrimaryNetwork("10.0.0.0/28") .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer14_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("BaR@12abc!") .WithSize(VirtualMachineSizeTypes.Parse("Standard_D2a_v4")) .DefineNewExtension("VMAccessForLinux") .WithPublisher("Microsoft.OSTCExtensions") .WithType("VMAccessForLinux") .WithVersion("1.4") .WithProtectedSetting("username", "Foo12") .WithProtectedSetting("password", "B12a6@12xyz!") .WithProtectedSetting("reset_ssh", "true") .Attach() .Create(); Assert.True(vm.ListExtensions().Count() > 0); // Get the created virtual machine via VM List not by VM GET var virtualMachines = azure.VirtualMachines .ListByResourceGroup(rgName); IVirtualMachine vmWithExtensionReference = null; foreach (var virtualMachine in virtualMachines) { if (virtualMachine.Name.Equals(vmName, StringComparison.OrdinalIgnoreCase)) { vmWithExtensionReference = virtualMachine; break; } } // The VM retrieved from the list will contain extensions as reference (i.e. with only id) Assert.NotNull(vmWithExtensionReference); // Update the extension var vmWithExtensionUpdated = vmWithExtensionReference.Update() .UpdateExtension("VMAccessForLinux") .WithProtectedSetting("username", "Foo12") .WithProtectedSetting("password", "muy!234OR") .WithProtectedSetting("reset_ssh", "true") .Parent() .Apply(); // Again getting VM with extension reference virtualMachines = azure.VirtualMachines .ListByResourceGroup(rgName); vmWithExtensionReference = null; foreach (var virtualMachine in virtualMachines) { vmWithExtensionReference = virtualMachine; } Assert.NotNull(vmWithExtensionReference); IVirtualMachineExtension accessExtension = null; foreach (var extension in vmWithExtensionReference.ListExtensions().Values) { if (extension.Name.Equals("VMAccessForLinux", StringComparison.OrdinalIgnoreCase)) { accessExtension = extension; break; } } // Even though VM's inner contain just extension reference VirtualMachine::extensions() // should resolve the reference and get full extension. Assert.NotNull(accessExtension); Assert.NotNull(accessExtension.PublisherName); Assert.NotNull(accessExtension.TypeName); Assert.NotNull(accessExtension.VersionName); } finally { try { azure.ResourceGroups.DeleteByName(rgName); } catch { } } } }
/// <summary> /// Update the Managed Service Identity extension installed in the virtual machine. /// </summary> /// <param name="virtualMachine">The virtual machine.</param> /// <param name="extension">The Managed Service Identity extension.</param> /// <param name="typeName">The Managed Service Identity extension type name.</param> /// <return>Task that produces true if extension is updated, false otherwise</return> private async Task <bool> UpdateMSIExtensionAsync(IVirtualMachine virtualMachine, IVirtualMachineExtension extension, string typeName, CancellationToken cancellationToken = default(CancellationToken)) { int?currentTokenPort = ComputeUtils.ObjectToInteger(extension.PublicSettings["port"]); int?tokenPortToUse; if (this.tokenPort != null) { // User specified a port tokenPortToUse = this.tokenPort; } else if (currentTokenPort == null) { // User didn't specify a port and port is not already set tokenPortToUse = this.DEFAULT_TOKEN_PORT; } else { // User didn't specify a port and port is already set in the extension // No need to do a PUT on extension // return(false); } var publicSettings = new Dictionary <string, object> { { "port", tokenPortToUse } }; extension.Inner.Settings = publicSettings; await virtualMachine.Manager.Inner.VirtualMachineExtensions.CreateOrUpdateAsync(virtualMachine.ResourceGroupName, virtualMachine.Name, typeName, extension.Inner, cancellationToken); return(true); }
public void CanUpdateEMSIAndLMSI() { using (var context = FluentMockContext.Start(GetType().FullName)) { var region = Region.USSouthCentral; var vmName = "javavm"; var groupName = TestUtilities.GenerateName("rgmsi"); String identityName1 = TestUtilities.GenerateName("msi-id"); String identityName2 = TestUtilities.GenerateName("msi-id"); IAzure azure = null; try { azure = TestHelper.CreateRollupClient(); // Create a virtual machine with no EMSI & LMSI // var virtualMachine = azure.VirtualMachines .Define(vmName) .WithRegion(region) .WithNewResourceGroup(groupName) .WithNewPrimaryNetwork("10.0.0.0/28") .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer16_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("abc!@#F0orL") .Create(); // Prepare a definition for yet-to-be-created "User Assigned (External) MSI" with contributor access to the resource group // it resides // var creatableIdentity = azure.Identities .Define(identityName1) .WithRegion(region) .WithExistingResourceGroup(virtualMachine.ResourceGroupName) .WithAccessToCurrentResourceGroup(BuiltInRole.Contributor); // Update virtual machine so that it depends on the EMSI // virtualMachine = virtualMachine.Update() .WithNewUserAssignedManagedServiceIdentity(creatableIdentity) .Apply(); // Ensure the MSI extension is set // var extensions = virtualMachine.ListExtensions(); IVirtualMachineExtension msiExtension = extensions .Select(e => e.Value) .FirstOrDefault(l => l.PublisherName.Equals("Microsoft.ManagedIdentity", StringComparison.OrdinalIgnoreCase) && l.TypeName.Equals("ManagedIdentityExtensionForLinux", StringComparison.OrdinalIgnoreCase)); Assert.NotNull(msiExtension); // Ensure the "User Assigned (External) MSI" id can be retrieved from the virtual machine // ISet <string> emsiIds = virtualMachine.UserAssignedManagedServiceIdentityIds; Assert.NotNull(emsiIds); Assert.Equal(1, emsiIds.Count); var identity = azure.Identities.GetById(emsiIds.First()); Assert.NotNull(identity); Assert.Equal(identity.Name, identityName1, ignoreCase: true); var createdIdentity = azure.Identities .Define(identityName2) .WithRegion(region) .WithExistingResourceGroup(virtualMachine.ResourceGroupName) .WithAccessToCurrentResourceGroup(BuiltInRole.Contributor) .Create(); // Update the virtual machine by removing the an EMSI and adding existing EMSI // virtualMachine = virtualMachine.Update() .WithoutUserAssignedManagedServiceIdentity(identity.Id) .WithExistingUserAssignedManagedServiceIdentity(createdIdentity) .Apply(); // Ensure the "User Assigned (External) MSI" id can be retrieved from the virtual machine // emsiIds = virtualMachine.UserAssignedManagedServiceIdentityIds; Assert.NotNull(emsiIds); Assert.Single(emsiIds); identity = azure.Identities.GetById(emsiIds.First()); Assert.NotNull(identity); Assert.Equal(identity.Name, identityName2, ignoreCase: true); // Update the virtual machine by enabling "LMSI" virtualMachine .Update() .WithSystemAssignedManagedServiceIdentity() .Apply(); Assert.NotNull(virtualMachine); Assert.NotNull(virtualMachine.Inner); Assert.True(virtualMachine.IsManagedServiceIdentityEnabled); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId); Assert.NotNull(virtualMachine.SystemAssignedManagedServiceIdentityTenantId); } finally { try { if (azure != null) { azure.ResourceGroups.BeginDeleteByName(groupName); } } catch { } } } }
public void CanCreateWithEMSI() { using (var context = FluentMockContext.Start(GetType().FullName)) { var region = Region.USSouthCentral; var vmName = "javavm"; var groupName = TestUtilities.GenerateName("rgmsi"); String identityName1 = TestUtilities.GenerateName("msi-id"); String identityName2 = TestUtilities.GenerateName("msi-id"); String networkName = TestUtilities.GenerateName("nw"); IAzure azure = null; try { azure = TestHelper.CreateRollupClient(); // Prepare a definition for yet-to-be-created resource group // var creatableRG = azure.ResourceGroups .Define(groupName) .WithRegion(region); // Create a virtual network residing in the above RG // var network = azure.Networks .Define(networkName) .WithRegion(region) .WithNewResourceGroup(creatableRG) .Create(); // Create an "User Assigned (External) MSI" residing in the above RG and assign reader access to the virtual network // var createdIdentity = azure.Identities .Define(identityName1) .WithRegion(region) .WithNewResourceGroup(creatableRG) .WithAccessTo(network, BuiltInRole.Reader) .Create(); // Prepare a definition for yet-to-be-created "User Assigned (External) MSI" with contributor access to the resource group // it resides // var creatableIdentity = azure.Identities .Define(identityName2) .WithRegion(region) .WithNewResourceGroup(creatableRG) .WithAccessToCurrentResourceGroup(BuiltInRole.Contributor); // Create a virtual machine and associate it with existing and yet-t-be-created identities // var virtualMachine = azure.VirtualMachines .Define(vmName) .WithRegion(region) .WithNewResourceGroup(groupName) .WithNewPrimaryNetwork("10.0.0.0/28") .WithPrimaryPrivateIPAddressDynamic() .WithoutPrimaryPublicIPAddress() .WithPopularLinuxImage(KnownLinuxVirtualMachineImage.UbuntuServer16_04_Lts) .WithRootUsername("Foo12") .WithRootPassword("abc!@#F0orL") .WithExistingUserAssignedManagedServiceIdentity(createdIdentity) .WithNewUserAssignedManagedServiceIdentity(creatableIdentity) .Create(); Assert.NotNull(virtualMachine); Assert.NotNull(virtualMachine.Inner); Assert.True(virtualMachine.IsManagedServiceIdentityEnabled); Assert.Null(virtualMachine.SystemAssignedManagedServiceIdentityPrincipalId); // No Local MSI enabled Assert.Null(virtualMachine.SystemAssignedManagedServiceIdentityTenantId); // No Local MSI enabled // Ensure the MSI extension is set // var extensions = virtualMachine.ListExtensions(); IVirtualMachineExtension msiExtension = extensions .Select(e => e.Value) .FirstOrDefault(l => l.PublisherName.Equals("Microsoft.ManagedIdentity", StringComparison.OrdinalIgnoreCase) && l.TypeName.Equals("ManagedIdentityExtensionForLinux", StringComparison.OrdinalIgnoreCase)); Assert.NotNull(msiExtension); // Ensure the "User Assigned (External) MSI" id can be retrieved from the virtual machine // var emsiIds = virtualMachine.UserAssignedManagedServiceIdentityIds; Assert.NotNull(emsiIds); Assert.Equal(2, emsiIds.Count); // Ensure the "User Assigned (External) MSI"s matches with the those provided as part of VM create // IIdentity implicitlyCreatedIdentity = null; foreach (var emsiId in emsiIds) { var identity = azure.Identities.GetById(emsiId); Assert.NotNull(identity); Assert.True(identity.Name.Equals(identityName1, StringComparison.OrdinalIgnoreCase) || identity.Name.Equals(identityName2, StringComparison.OrdinalIgnoreCase)); Assert.NotNull(identity.PrincipalId); if (identity.Name.Equals(identityName2, StringComparison.OrdinalIgnoreCase)) { implicitlyCreatedIdentity = identity; } } Assert.NotNull(implicitlyCreatedIdentity); // Ensure expected role assignment exists for explicitly created EMSI // var roleAssignmentsForNetwork = azure .AccessManagement .RoleAssignments .ListByScope(network.Id); bool found = roleAssignmentsForNetwork.Any(r => r.PrincipalId != null && r.PrincipalId.Equals(createdIdentity.PrincipalId, StringComparison.OrdinalIgnoreCase)); Assert.True(found, $"Expected role assignment not found for the virtual network for identity {createdIdentity.Name}"); var assignment = LookupRoleAssignmentUsingScopeAndRole(network.Id, BuiltInRole.Reader, createdIdentity.PrincipalId, azure); Assert.False(assignment == null, "Expected role assignment with ROLE not found for the virtual network for identity"); // Ensure expected role assignment exists for explicitly created EMSI // var resourceGroup = azure.ResourceGroups.GetByName(virtualMachine.ResourceGroupName); Assert.NotNull(resourceGroup); var roleAssignmentsForResourceGroup = azure .AccessManagement .RoleAssignments .ListByScope(resourceGroup.Id); found = roleAssignmentsForResourceGroup.Any(r => r.PrincipalId != null && r.PrincipalId.Equals(implicitlyCreatedIdentity.PrincipalId, StringComparison.OrdinalIgnoreCase)); Assert.True(found, $"Expected role assignment not found for the resource group for identity{implicitlyCreatedIdentity.Name}"); assignment = LookupRoleAssignmentUsingScopeAndRole(resourceGroup.Id, BuiltInRole.Contributor, implicitlyCreatedIdentity.PrincipalId, azure); Assert.False(assignment == null, "Expected role assignment with ROLE not found for the resource group for identity"); } finally { try { if (azure != null) { azure.ResourceGroups.BeginDeleteByName(groupName); } } catch { } } } }