diff --git a/src/ResourceManager/Automation/Commands.Automation.Test/packages.config b/src/ResourceManager/Automation/Commands.Automation.Test/packages.config index 8b5713e969f3..222b03afb390 100644 --- a/src/ResourceManager/Automation/Commands.Automation.Test/packages.config +++ b/src/ResourceManager/Automation/Commands.Automation.Test/packages.config @@ -16,7 +16,6 @@ - diff --git a/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs b/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs index 900a6a82fe96..8d2426d80988 100644 --- a/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs +++ b/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs @@ -135,6 +135,24 @@ public static string NoSubscriptionFound { } } + /// + /// Looks up a localized string similar to The provided account {0} does not have access to subscription ID "{1}". Please try logging in with different credentials not a different subscription ID.. + /// + public static string SubscriptionIdNotFound { + get { + return ResourceManager.GetString("SubscriptionIdNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SubscriptionIdNotFound The provided account {0} does not have access to subscription name "{1}". Please try logging in with different credentials not a different subscription name.. + /// + public static string SubscriptionNameNotFound { + get { + return ResourceManager.GetString("SubscriptionNameNotFound", resourceCulture); + } + } + /// /// Looks up a localized string similar to Tenant '{0}' was not found. Please verify that your account has access to this tenant.. /// diff --git a/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.resx b/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.resx index 617f62d27d76..93b591600071 100644 --- a/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.resx +++ b/src/ResourceManager/Common/Commands.ResourceManager.Common/Properties/Resources.resx @@ -151,7 +151,13 @@ Select Y to enable data collection [Y/N]: The provided account {0} does not have access to any subscriptions. Please try logging in with different credentials. + + The provided account {0} does not have access to subscription ID "{1}". Please try logging in with different credentials not a different subscription ID. + + + The provided account {0} does not have access to subscription name "{1}". Please try logging in with different credentials not a different subscription name. + Tenant '{0}' was not found. Please verify that your account has access to this tenant. - \ No newline at end of file + diff --git a/src/ResourceManager/Common/Commands.ResourceManager.Common/RMProfileClient.cs b/src/ResourceManager/Common/Commands.ResourceManager.Common/RMProfileClient.cs index 32272bac79fb..74ac2fa22943 100644 --- a/src/ResourceManager/Common/Commands.ResourceManager.Common/RMProfileClient.cs +++ b/src/ResourceManager/Common/Commands.ResourceManager.Common/RMProfileClient.cs @@ -44,7 +44,7 @@ public RMProfileClient(AzureRMProfile profile) } } - public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, SecureString password) + public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, string subscriptionName, SecureString password) { AzureSubscription newSubscription = null; AzureTenant newTenant = null; @@ -55,7 +55,7 @@ public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, if (!string.IsNullOrEmpty(tenantId)) { var token = AcquireAccessToken(account, environment, tenantId, password, promptBehavior); - TryGetTenantSubscription(token, account, environment, tenantId, subscriptionId, out newSubscription, out newTenant); + TryGetTenantSubscription(token, account, environment, tenantId, subscriptionId, subscriptionName, out newSubscription, out newTenant); } // (tenant is not provided and subscription is present) OR // (tenant is not provided and subscription is not provided) @@ -67,7 +67,7 @@ public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, AzureSubscription tempSubscription; var token = AcquireAccessToken(account, environment, tenant.Id.ToString(), password, ShowDialog.Auto); - if (newTenant == null && TryGetTenantSubscription(token, account, environment, tenant.Id.ToString(), subscriptionId, out tempSubscription, out tempTenant) && + if (newTenant == null && TryGetTenantSubscription(token, account, environment, tenant.Id.ToString(), subscriptionId, subscriptionName, out tempSubscription, out tempTenant) && newTenant == null) { newTenant = tempTenant; @@ -78,7 +78,18 @@ public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, if (newSubscription == null) { - throw new PSInvalidOperationException(String.Format(Properties.Resources.NoSubscriptionFound, account.Id)); + if (subscriptionId != null) + { + throw new PSInvalidOperationException(String.Format(Properties.Resources.SubscriptionIdNotFound, account.Id, subscriptionId)); + } + else if (subscriptionName != null) + { + throw new PSInvalidOperationException(String.Format(Properties.Resources.SubscriptionNameNotFound, account.Id, subscriptionId)); + } + else + { + throw new PSInvalidOperationException(String.Format(Properties.Resources.NoSubscriptionFound, account.Id)); + } } _profile.Context = new AzureContext(newSubscription, account, environment, newTenant); @@ -155,7 +166,7 @@ public bool TryGetSubscription(string tenantId, string subscriptionId, out Azure var token = AcquireAccessToken(_profile.Context.Account, _profile.Context.Environment, tenantId, null, ShowDialog.Never); return TryGetTenantSubscription(token, _profile.Context.Account, _profile.Context.Environment, - tenantId, subscriptionId, out subscription, out tenant); + tenantId, subscriptionId, null, out subscription, out tenant); } public bool TryGetSubscriptionByName(string tenantId, string subscriptionName, out AzureSubscription subscription) @@ -283,10 +294,10 @@ private bool TryGetTenantSubscription(IAccessToken accessToken, AzureEnvironment environment, string tenantId, string subscriptionId, + string subscriptionName, out AzureSubscription subscription, out AzureTenant tenant) { - using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient( new TokenCloudCredentials(accessToken.AccessToken), environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager))) @@ -304,14 +315,21 @@ private bool TryGetTenantSubscription(IAccessToken accessToken, var subscriptions = subscriptionClient.Subscriptions.List().Subscriptions; if (subscriptions != null && subscriptions.Any()) { - if (subscriptions.Count > 1) + if (subscriptionName != null) + { + subscriptionFromServer = subscriptions.FirstOrDefault(s => s.DisplayName.Equals(subscriptionName, StringComparison.OrdinalIgnoreCase)); + } + else { - WriteWarningMessage(string.Format( - "Tenant '{0}' contains more than one subscription. First one will be selected for further use. " + - "To select another subscription, use Set-AzureRmContext.", - tenantId)); + if (subscriptions.Count > 1) + { + WriteWarningMessage(string.Format( + "Tenant '{0}' contains more than one subscription. First one will be selected for further use. " + + "To select another subscription, use Set-AzureRmContext.", + tenantId)); + } + subscriptionFromServer = subscriptions.First(); } - subscriptionFromServer = subscriptions.First(); } } } diff --git a/src/ResourceManager/Profile/Commands.Profile.Test/LoginCmdletTests.cs b/src/ResourceManager/Profile/Commands.Profile.Test/LoginCmdletTests.cs index dd4a70057b74..48a8b8ca779a 100644 --- a/src/ResourceManager/Profile/Commands.Profile.Test/LoginCmdletTests.cs +++ b/src/ResourceManager/Profile/Commands.Profile.Test/LoginCmdletTests.cs @@ -128,5 +128,41 @@ public void LoginWithNoSubscriptionAndTenant() Assert.NotNull(AzureRMCmdlet.DefaultProfile.Context); Assert.Equal("microsoft.com", AzureRMCmdlet.DefaultProfile.Context.Tenant.Domain); } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithSubscriptionname() + { + var cmdlt = new AddAzureRMAccountCommand(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47"; + cmdlt.SubscriptionName = "Node CLI Test"; + + // Act + cmdlt.InvokeBeginProcessing(); + cmdlt.ExecuteCmdlet(); + cmdlt.InvokeEndProcessing(); + + Assert.NotNull(AzureRMCmdlet.DefaultProfile.Context); + Assert.Equal("microsoft.com", AzureRMCmdlet.DefaultProfile.Context.Tenant.Domain); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithBothSubscriptionIdAndNameThrowsCloudException() + { + var cmdlt = new AddAzureRMAccountCommand(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47"; + cmdlt.SubscriptionName = "Node CLI Test"; + cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a6"; + + // Act + cmdlt.InvokeBeginProcessing(); + Assert.Throws(() => cmdlt.ExecuteCmdlet()); + cmdlt.InvokeEndProcessing(); + } } } diff --git a/src/ResourceManager/Profile/Commands.Profile/Account/AddAzureRmAccount.cs b/src/ResourceManager/Profile/Commands.Profile/Account/AddAzureRmAccount.cs index 735a695eaff8..158103085ca1 100644 --- a/src/ResourceManager/Profile/Commands.Profile/Account/AddAzureRmAccount.cs +++ b/src/ResourceManager/Profile/Commands.Profile/Account/AddAzureRmAccount.cs @@ -20,6 +20,8 @@ using Microsoft.Azure.Commands.Profile.Models; using Microsoft.Azure.Commands.ResourceManager.Common; using Microsoft.Azure.Common.Authentication; +using System; +using Microsoft.Azure.Commands.Profile.Properties; namespace Microsoft.Azure.Commands.Profile { @@ -56,6 +58,10 @@ public class AddAzureRMAccountCommand : AzureRMCmdlet , IModuleAssemblyInitializ [ValidateNotNullOrEmpty] public string SubscriptionId { get; set; } + [Parameter(Mandatory = false, HelpMessage = "Subscription")] + [ValidateNotNullOrEmpty] + public string SubscriptionName { get; set; } + protected override AzureContext DefaultContext { get @@ -75,6 +81,17 @@ protected override void BeginProcessing() protected override void ProcessRecord() { + if (SubscriptionId != null && SubscriptionName != null) + { + throw new PSInvalidOperationException(Resources.BothSubscriptionIdAndNameProvided); + } + + Guid subscrptionIdGuid; + if (SubscriptionId != null && !Guid.TryParse(SubscriptionId, out subscrptionIdGuid)) + { + throw new PSInvalidOperationException(Resources.InvalidSubscriptionId); + } + AzureAccount azureAccount = new AzureAccount(); if (!string.IsNullOrEmpty(AccessToken)) @@ -109,7 +126,7 @@ protected override void ProcessRecord() var profileClient = new RMProfileClient(AzureRMCmdlet.DefaultProfile); - WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, password)); + WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, SubscriptionName, password)); } /// diff --git a/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs b/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs index ac0eae9ab4c0..4d0ead958c30 100644 --- a/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs +++ b/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs @@ -69,6 +69,15 @@ internal static string AzureProfileMustNotBeNull { } } + /// + /// Looks up a localized string similar to Please provide either a subscription ID or a subscription name.. + /// + internal static string BothSubscriptionIdAndNameProvided { + get { + return ResourceManager.GetString("BothSubscriptionIdAndNameProvided", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not authenticate your user account {0} with the common tenant. Please login again using Login-AzureRmAccount.. /// @@ -78,6 +87,15 @@ internal static string CommonTenantAuthFailed { } } + /// + /// Looks up a localized string similar to The provided subscription ID "{0}" is not a valid Guid.. + /// + internal static string InvalidSubscriptionId { + get { + return ResourceManager.GetString("InvalidSubscriptionId", resourceCulture); + } + } + /// /// Looks up a localized string similar to (no account provided). /// diff --git a/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx b/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx index ea1af986447d..0e92efc9cc35 100644 --- a/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx +++ b/src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx @@ -120,9 +120,15 @@ Selected profile must not be null. + + Please provide either a subscription ID or a subscription name. + Could not authenticate your user account {0} with the common tenant. Please login again using Login-AzureRmAccount. + + The provided subscription ID "{0}" is not a valid Guid. + (no account provided)