/// <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);
        }
Beispiel #2
0
        /// <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));
        }
Beispiel #3
0
        /// <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));
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #11
0
        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 { }
                }
            }
        }
Beispiel #12
0
        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 { }
                }
            }
        }