From 7361efa914d3978e1298b2b1ab7075a969f92728 Mon Sep 17 00:00:00 2001 From: Hovsep Mkrtchyan Date: Thu, 10 Sep 2015 16:03:20 -0700 Subject: [PATCH 1/3] Work in progress --- .../Commands.ResourceManager.Common.csproj | 12 ++ .../Properties/Resources.Designer.cs | 72 ++++++++++ .../Properties/Resources.resx | 123 +++++++++++++++++ .../RMProfileClient.cs | 123 +++++++++++++++++ .../Commands.ResourceManager.Profile.csproj | 1 + .../LoginAzureRMAccount.cs | 130 ++++++++++++++++++ 6 files changed, 461 insertions(+) create mode 100644 src/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs create mode 100644 src/Common/Commands.ResourceManager.Common/Properties/Resources.resx create mode 100644 src/Common/Commands.ResourceManager.Common/RMProfileClient.cs create mode 100644 src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs diff --git a/src/Common/Commands.ResourceManager.Common/Commands.ResourceManager.Common.csproj b/src/Common/Commands.ResourceManager.Common/Commands.ResourceManager.Common.csproj index ff1ad1950375..62da2d902735 100644 --- a/src/Common/Commands.ResourceManager.Common/Commands.ResourceManager.Common.csproj +++ b/src/Common/Commands.ResourceManager.Common/Commands.ResourceManager.Common.csproj @@ -166,10 +166,22 @@ + + True + True + Resources.resx + + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + + diff --git a/src/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs b/src/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs new file mode 100644 index 000000000000..826b427af001 --- /dev/null +++ b/src/Common/Commands.ResourceManager.Common/Properties/Resources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Azure.Commands.ResourceManager.Common.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Commands.ResourceManager.Common.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Tenant '{0}' was not found. Please verify that your account has access to this tenant.. + /// + internal static string TenantNotFound { + get { + return ResourceManager.GetString("TenantNotFound", resourceCulture); + } + } + } +} diff --git a/src/Common/Commands.ResourceManager.Common/Properties/Resources.resx b/src/Common/Commands.ResourceManager.Common/Properties/Resources.resx new file mode 100644 index 000000000000..7e29fac28996 --- /dev/null +++ b/src/Common/Commands.ResourceManager.Common/Properties/Resources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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/Common/Commands.ResourceManager.Common/RMProfileClient.cs b/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs new file mode 100644 index 000000000000..4f37c55e56c4 --- /dev/null +++ b/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs @@ -0,0 +1,123 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Hyak.Common; +using Microsoft.Azure.Commands.ResourceManager.Common.Properties; +using Microsoft.Azure.Common.Authentication; +using Microsoft.Azure.Common.Authentication.Factories; +using Microsoft.Azure.Common.Authentication.Models; +using Microsoft.Azure.Subscriptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Commands.ResourceManager.Common +{ + public class RMProfileClient + { + private AzureRMProfile _profile; + + public RMProfileClient(AzureRMProfile profile) + { + _profile = profile; + } + + public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId) + { + var tenant = string.IsNullOrEmpty(tenantId) ? AuthenticationFactory.CommonAdTenant : tenantId; + + var commonTenantToken = AzureSession.AuthenticationFactory.Authenticate(account, environment, tenant, null, ShowDialog.Auto); + + using (SubscriptionClient SubscriptionClient = AzureSession.ClientFactory.CreateCustomClient( + new TokenCloudCredentials(commonTenantToken.AccessToken), + environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ServiceManagement))) + { + var tenantListResult = SubscriptionClient.Tenants.List(); + + if (!string.IsNullOrEmpty(tenantId) && !tenantListResult.TenantIds.Any(s => s.TenantId.Equals(tenantId, StringComparison.OrdinalIgnoreCase))) + { + throw new ArgumentException(string.Format(Resources.TenantNotFound, tenantId)); + } + + _profile. + //ListResourceManagerSubscriptions + + + //_profile.DefaultContext = new AzureContext(); + } + + return _profile; + } + + public IEnumerable GetTenantSubscriptions(AzureAccount account, AzureEnvironment environment, string tenantId, SecureString password) + { + try + { + var tenantAccount = new AzureAccount(); + CopyAccount(account, tenantAccount); + var tenantToken = AzureSession.AuthenticationFactory.Authenticate(tenantAccount, environment, tenantId, password, ShowDialog.Never); + if (string.Equals(tenantAccount.Id, account.Id, StringComparison.InvariantCultureIgnoreCase)) + { + tenantAccount = account; + } + + tenantAccount.SetOrAppendProperty(AzureAccount.Property.Tenants, new string[] { tenantId }); + + using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient( + new TokenCloudCredentials(tenantToken.AccessToken), + environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager))) + { + var subscriptionListResult = subscriptionClient.Subscriptions.List(); + + return subscriptionListResult.Subscriptions.Select(s => s.SubscriptionId); + } + + + } + catch (CloudException cEx) + { + WriteOrThrowAadExceptionMessage(cEx); + } + catch (AadAuthenticationException aadEx) + { + WriteOrThrowAadExceptionMessage(aadEx); + } + } + + private void CopyAccount(AzureAccount sourceAccount, AzureAccount targetAccount) + { + targetAccount.Id = sourceAccount.Id; + targetAccount.Type = sourceAccount.Type; + } + + private void WriteOrThrowAadExceptionMessage(AadAuthenticationException aadEx) + { + if (aadEx is AadAuthenticationFailedWithoutPopupException) + { + WriteDebugMessage(aadEx.Message); + } + else if (aadEx is AadAuthenticationCanceledException) + { + WriteWarningMessage(aadEx.Message); + } + else + { + throw aadEx; + } + } + } +} diff --git a/src/Common/Commands.ResourceManager.Profile/Commands.ResourceManager.Profile.csproj b/src/Common/Commands.ResourceManager.Profile/Commands.ResourceManager.Profile.csproj index c3b20d9827a2..5ff4ba4ddab5 100644 --- a/src/Common/Commands.ResourceManager.Profile/Commands.ResourceManager.Profile.csproj +++ b/src/Common/Commands.ResourceManager.Profile/Commands.ResourceManager.Profile.csproj @@ -132,6 +132,7 @@ + diff --git a/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs new file mode 100644 index 000000000000..56a6546d86ac --- /dev/null +++ b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs @@ -0,0 +1,130 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Commands.ResourceManager.Common; +using System.Management.Automation; +using Microsoft.Azure.Common.Authentication.Models; +using Microsoft.Azure.Common.Authentication; +using System.Security; + +namespace Microsoft.Azure.Commands.Profile +{ + /// + /// Cmdlet to log into an environment and download the subscriptions + /// + [Cmdlet("Login", "AzureRMAccount", DefaultParameterSetName = "User")] + [OutputType(typeof(AzureRMProfile))] + public class LoginAzureRMAccount : AzureRMCmdlet + { + [Parameter(Mandatory = false, HelpMessage = "Environment containing the account to log into")] + [ValidateNotNullOrEmpty] + public AzureEnvironment Environment { get; set; } + + [Parameter(ParameterSetName = "User", Mandatory = false, HelpMessage = "Optional credential")] + [Parameter(ParameterSetName = "ServicePrincipal", Mandatory = true, HelpMessage = "Credential")] + public PSCredential Credential { get; set; } + + [Parameter(ParameterSetName = "ServicePrincipal", Mandatory = true)] + public SwitchParameter ServicePrincipal { get; set; } + + [Parameter(ParameterSetName = "User", Mandatory = false, HelpMessage = "Optional tenant name or ID")] + [Parameter(ParameterSetName = "ServicePrincipal", Mandatory = true, HelpMessage = "Tenant name or ID")] + [Parameter(ParameterSetName = "AccessToken", Mandatory = false, HelpMessage = "Tenant name or ID")] + [ValidateNotNullOrEmpty] + public string Tenant { get; set; } + + [Parameter(ParameterSetName = "AccessToken", Mandatory = true, HelpMessage = "AccessToken")] + [ValidateNotNullOrEmpty] + public string AccessToken { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "Subscription")] + [ValidateNotNullOrEmpty] + public string SubscriptionId { get; set; } + + public LoginAzureRMAccount() + : base() + { + } + + protected override void BeginProcessing() + { + base.BeginProcessing(); + if (Environment == null) + { + Environment = DefaultContext.Environment; + } + } + + protected override void ProcessRecord() + { + AzureAccount azureAccount = new AzureAccount(); + + if (!string.IsNullOrEmpty(AccessToken)) + { + azureAccount.Type = AzureAccount.AccountType.AccessToken; + } + else if (ServicePrincipal.IsPresent) + { + azureAccount.Type = AzureAccount.AccountType.ServicePrincipal; + } + else + { + azureAccount.Type = AzureAccount.AccountType.User; + + } + + SecureString password = null; + if (Credential != null) + { + azureAccount.Id = Credential.UserName; + password = Credential.Password; + } + + if (!string.IsNullOrEmpty(Tenant)) + { + azureAccount.SetProperty(AzureAccount.Property.Tenants, new[] { Tenant }); + } + + var profileClient = new ProfileClient(); + var account = this.ProfileClient.AddAccountAndLoadSubscriptions(azureAccount, ProfileClient.GetEnvironmentOrDefault(Environment), password); + + if (account != null) + { + WriteVerbose(string.Format(Resources.AddAccountAdded, azureAccount.Id)); + if (ProfileClient.Profile.DefaultSubscription != null) + { + WriteVerbose(string.Format(Resources.AddAccountShowDefaultSubscription, + ProfileClient.Profile.DefaultSubscription.Name)); + } + WriteVerbose(Resources.AddAccountViewSubscriptions); + WriteVerbose(Resources.AddAccountChangeSubscription); + + string subscriptionsList = account.GetProperty(AzureAccount.Property.Subscriptions); + string tenantsList = account.GetProperty(AzureAccount.Property.Tenants); + + if (subscriptionsList == null) + { + WriteWarning(string.Format(Resources.NoSubscriptionAddedMessage, azureAccount.Id)); + } + + WriteObject(account.ToPSAzureAccount()); + } + } + } +} From 078fc60f3219093098f9d7a7e61938af4cac0eb0 Mon Sep 17 00:00:00 2001 From: Hovsep Mkrtchyan Date: Fri, 11 Sep 2015 16:41:47 -0700 Subject: [PATCH 2/3] Added AzureLogin cmdlets --- .../RMProfileClient.cs | 153 +++++++++++------- ...mmands.ResourceManager.Profile.Test.csproj | 1 + .../LoginCmdletTests.cs | 128 +++++++++++++++ .../LoginAzureRMAccount.cs | 48 ++---- src/ResourceManager.sln | 7 - 5 files changed, 241 insertions(+), 96 deletions(-) create mode 100644 src/Common/Commands.ResourceManager.Profile.Test/LoginCmdletTests.cs diff --git a/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs b/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs index 4f37c55e56c4..cd3908bafca1 100644 --- a/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs +++ b/src/Common/Commands.ResourceManager.Common/RMProfileClient.cs @@ -13,7 +13,6 @@ // ---------------------------------------------------------------------------------- using Hyak.Common; -using Microsoft.Azure.Commands.ResourceManager.Common.Properties; using Microsoft.Azure.Common.Authentication; using Microsoft.Azure.Common.Authentication.Factories; using Microsoft.Azure.Common.Authentication.Models; @@ -21,102 +20,144 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Management.Automation; using System.Security; -using System.Text; -using System.Threading.Tasks; namespace Microsoft.Azure.Commands.ResourceManager.Common { public class RMProfileClient { private AzureRMProfile _profile; + public Action WarningLog; public RMProfileClient(AzureRMProfile profile) { _profile = profile; } - public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId) + public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, SecureString password) { - var tenant = string.IsNullOrEmpty(tenantId) ? AuthenticationFactory.CommonAdTenant : tenantId; + AzureSubscription newSubscription = null; + AzureTenant newTenant = new AzureTenant(); - var commonTenantToken = AzureSession.AuthenticationFactory.Authenticate(account, environment, tenant, null, ShowDialog.Auto); - - using (SubscriptionClient SubscriptionClient = AzureSession.ClientFactory.CreateCustomClient( - new TokenCloudCredentials(commonTenantToken.AccessToken), - environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ServiceManagement))) + // (tenant and subscription are present) OR + // (tenant is present and subscription is not provided) + if (!string.IsNullOrEmpty(tenantId)) { - var tenantListResult = SubscriptionClient.Tenants.List(); - - if (!string.IsNullOrEmpty(tenantId) && !tenantListResult.TenantIds.Any(s => s.TenantId.Equals(tenantId, StringComparison.OrdinalIgnoreCase))) + newTenant.Id = new Guid(tenantId); + ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never; + TryGetTenantSubscription(account, environment, tenantId, subscriptionId, password, promptBehavior, out newSubscription); + } + // (tenant is not provided and subscription is present) OR + // (tenant is not provided and subscription is not provided) + else + { + foreach(var tenant in ListAccountTenants(account, environment, password)) { - throw new ArgumentException(string.Format(Resources.TenantNotFound, tenantId)); + if (TryGetTenantSubscription(account, environment, tenant, subscriptionId, password, ShowDialog.Auto, out newSubscription)) + { + newTenant.Id = new Guid(tenant); + break; + } } - _profile. - //ListResourceManagerSubscriptions - + } - //_profile.DefaultContext = new AzureContext(); + if (newSubscription == null) + { + throw new PSInvalidOperationException("Subscription was not found."); } + _profile.DefaultContext = new AzureContext(newSubscription, account, environment, newTenant); + return _profile; } - public IEnumerable GetTenantSubscriptions(AzureAccount account, AzureEnvironment environment, string tenantId, SecureString password) + private bool TryGetTenantSubscription( + AzureAccount account, + AzureEnvironment environment, + string tenantId, + string subscriptionId, + SecureString password, + ShowDialog promptBehavior, + out AzureSubscription subscription) { - try + var accessToken = AzureSession.AuthenticationFactory.Authenticate( + account, + environment, + tenantId, + password, + promptBehavior); + using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient( + new TokenCloudCredentials(accessToken.AccessToken), + environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager))) { - var tenantAccount = new AzureAccount(); - CopyAccount(account, tenantAccount); - var tenantToken = AzureSession.AuthenticationFactory.Authenticate(tenantAccount, environment, tenantId, password, ShowDialog.Never); - if (string.Equals(tenantAccount.Id, account.Id, StringComparison.InvariantCultureIgnoreCase)) + Subscriptions.Models.Subscription subscriptionFromServer = null; + + try { - tenantAccount = account; + if (subscriptionId != null) + { + subscriptionFromServer = subscriptionClient.Subscriptions.Get(subscriptionId).Subscription; + } + else + { + var subscriptions = subscriptionClient.Subscriptions.List().Subscriptions; + if (subscriptions != null) + { + if (subscriptions.Count > 1) + { + WriteWarningMessage(string.Format( + "Tenant '{0}' contains more than one subscription. First one will be selected for further use.", + tenantId)); + } + subscriptionFromServer = subscriptions.First(); + } + } } - - tenantAccount.SetOrAppendProperty(AzureAccount.Property.Tenants, new string[] { tenantId }); - - using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient( - new TokenCloudCredentials(tenantToken.AccessToken), - environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager))) + catch (CloudException ex) { - var subscriptionListResult = subscriptionClient.Subscriptions.List(); - - return subscriptionListResult.Subscriptions.Select(s => s.SubscriptionId); + WriteWarningMessage(ex.Message); } + if (subscriptionFromServer != null) + { + subscription = new AzureSubscription + { + Id = new Guid(subscriptionFromServer.SubscriptionId), + Account = accessToken.UserId, + Environment = environment.Name, + Name = subscriptionFromServer.DisplayName, + Properties = new Dictionary { { AzureSubscription.Property.Tenants, accessToken.TenantId } } + }; + return true; + } - } - catch (CloudException cEx) - { - WriteOrThrowAadExceptionMessage(cEx); - } - catch (AadAuthenticationException aadEx) - { - WriteOrThrowAadExceptionMessage(aadEx); + subscription = null; + return false; } } - private void CopyAccount(AzureAccount sourceAccount, AzureAccount targetAccount) + private string[] ListAccountTenants(AzureAccount account, AzureEnvironment environment, SecureString password) { - targetAccount.Id = sourceAccount.Id; - targetAccount.Type = sourceAccount.Type; - } + ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never; - private void WriteOrThrowAadExceptionMessage(AadAuthenticationException aadEx) - { - if (aadEx is AadAuthenticationFailedWithoutPopupException) - { - WriteDebugMessage(aadEx.Message); - } - else if (aadEx is AadAuthenticationCanceledException) + var commonTenantToken = AzureSession.AuthenticationFactory.Authenticate(account, environment, + AuthenticationFactory.CommonAdTenant, password, promptBehavior); + + using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient( + new TokenCloudCredentials(commonTenantToken.AccessToken), + environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager))) { - WriteWarningMessage(aadEx.Message); + return subscriptionClient.Tenants.List().TenantIds.Select(ti => ti.TenantId).ToArray(); } - else + } + + private void WriteWarningMessage(string message) + { + if (WarningLog != null) { - throw aadEx; + WarningLog(message); } } } diff --git a/src/Common/Commands.ResourceManager.Profile.Test/Commands.ResourceManager.Profile.Test.csproj b/src/Common/Commands.ResourceManager.Profile.Test/Commands.ResourceManager.Profile.Test.csproj index a2007b8519c7..b7b9311fa65c 100644 --- a/src/Common/Commands.ResourceManager.Profile.Test/Commands.ResourceManager.Profile.Test.csproj +++ b/src/Common/Commands.ResourceManager.Profile.Test/Commands.ResourceManager.Profile.Test.csproj @@ -178,6 +178,7 @@ + diff --git a/src/Common/Commands.ResourceManager.Profile.Test/LoginCmdletTests.cs b/src/Common/Commands.ResourceManager.Profile.Test/LoginCmdletTests.cs new file mode 100644 index 000000000000..a881481c0e88 --- /dev/null +++ b/src/Common/Commands.ResourceManager.Profile.Test/LoginCmdletTests.cs @@ -0,0 +1,128 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Microsoft.WindowsAzure.Commands.Utilities.Common; +using Microsoft.Azure.Commands.Profile; +using Microsoft.Azure.Commands.ResourceManager.Common; +using Microsoft.Azure.Common.Authentication; +using Microsoft.Azure.Common.Authentication.Models; +using Microsoft.WindowsAzure.Commands.Common.Test.Mocks; +using Microsoft.WindowsAzure.Commands.ScenarioTest; +using System.Linq; +using Xunit; +using System; +using Microsoft.WindowsAzure.Commands.Test.Utilities.Common; +using Hyak.Common; +using System.Management.Automation; + +namespace Microsoft.Azure.Commands.Profile.Test +{ + public class LoginCmdletTests + { + private MemoryDataStore dataStore; + private MockCommandRuntime commandRuntimeMock; + + public LoginCmdletTests() + { + dataStore = new MemoryDataStore(); + AzureSession.DataStore = dataStore; + commandRuntimeMock = new MockCommandRuntime(); + AzureRMCmdlet.DefaultProfile = new AzureRMProfile(); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithSubscriptionAndTenant() + { + var cmdlt = new LoginAzureRMAccount(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a6"; + cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47"; + + // Act + cmdlt.InvokeBeginProcessing(); + cmdlt.ExecuteCmdlet(); + cmdlt.InvokeEndProcessing(); + + Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithInvalidSubscriptionAndTenantThrowsCloudException() + { + var cmdlt = new LoginAzureRMAccount(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a5"; + cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47"; + + // Act + cmdlt.InvokeBeginProcessing(); + Assert.Throws(() => cmdlt.ExecuteCmdlet()); + cmdlt.InvokeEndProcessing(); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithSubscriptionAndNoTenant() + { + var cmdlt = new LoginAzureRMAccount(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a6"; + + // Act + cmdlt.InvokeBeginProcessing(); + cmdlt.ExecuteCmdlet(); + cmdlt.InvokeEndProcessing(); + + Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithNoSubscriptionAndNoTenant() + { + var cmdlt = new LoginAzureRMAccount(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + + // Act + cmdlt.InvokeBeginProcessing(); + cmdlt.ExecuteCmdlet(); + cmdlt.InvokeEndProcessing(); + + Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.LiveOnly)] + public void LoginWithNoSubscriptionAndTenant() + { + var cmdlt = new LoginAzureRMAccount(); + // Setup + cmdlt.CommandRuntime = commandRuntimeMock; + cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47"; + + // Act + cmdlt.InvokeBeginProcessing(); + cmdlt.ExecuteCmdlet(); + cmdlt.InvokeEndProcessing(); + + Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext); + } + } +} diff --git a/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs index 56a6546d86ac..cadf1f4068a7 100644 --- a/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs +++ b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs @@ -12,16 +12,11 @@ // limitations under the License. // ---------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.Azure.Commands.ResourceManager.Common; using System.Management.Automation; using Microsoft.Azure.Common.Authentication.Models; -using Microsoft.Azure.Common.Authentication; using System.Security; +using Microsoft.WindowsAzure.Commands.Utilities.Common; namespace Microsoft.Azure.Commands.Profile { @@ -30,7 +25,7 @@ namespace Microsoft.Azure.Commands.Profile /// [Cmdlet("Login", "AzureRMAccount", DefaultParameterSetName = "User")] [OutputType(typeof(AzureRMProfile))] - public class LoginAzureRMAccount : AzureRMCmdlet + public class LoginAzureRMAccount : AzurePSCmdlet { [Parameter(Mandatory = false, HelpMessage = "Environment containing the account to log into")] [ValidateNotNullOrEmpty] @@ -57,6 +52,14 @@ public class LoginAzureRMAccount : AzureRMCmdlet [ValidateNotNullOrEmpty] public string SubscriptionId { get; set; } + protected override AzureContext DefaultContext + { + get + { + return null; + } + } + public LoginAzureRMAccount() : base() { @@ -67,7 +70,7 @@ protected override void BeginProcessing() base.BeginProcessing(); if (Environment == null) { - Environment = DefaultContext.Environment; + Environment = AzureEnvironment.PublicEnvironments[EnvironmentName.AzureCloud]; } } @@ -100,31 +103,10 @@ protected override void ProcessRecord() { azureAccount.SetProperty(AzureAccount.Property.Tenants, new[] { Tenant }); } - - var profileClient = new ProfileClient(); - var account = this.ProfileClient.AddAccountAndLoadSubscriptions(azureAccount, ProfileClient.GetEnvironmentOrDefault(Environment), password); - - if (account != null) - { - WriteVerbose(string.Format(Resources.AddAccountAdded, azureAccount.Id)); - if (ProfileClient.Profile.DefaultSubscription != null) - { - WriteVerbose(string.Format(Resources.AddAccountShowDefaultSubscription, - ProfileClient.Profile.DefaultSubscription.Name)); - } - WriteVerbose(Resources.AddAccountViewSubscriptions); - WriteVerbose(Resources.AddAccountChangeSubscription); - - string subscriptionsList = account.GetProperty(AzureAccount.Property.Subscriptions); - string tenantsList = account.GetProperty(AzureAccount.Property.Tenants); - - if (subscriptionsList == null) - { - WriteWarning(string.Format(Resources.NoSubscriptionAddedMessage, azureAccount.Id)); - } - - WriteObject(account.ToPSAzureAccount()); - } + + var profileClient = new RMProfileClient(AzureRMCmdlet.DefaultProfile); + + WriteObject(profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, password)); } } } diff --git a/src/ResourceManager.sln b/src/ResourceManager.sln index b793d8fdf990..eae93fd6ef08 100644 --- a/src/ResourceManager.sln +++ b/src/ResourceManager.sln @@ -121,8 +121,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Websites.Test", "R EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Common", "Common\Commands.Common\Commands.Common.csproj", "{5EE72C53-1720-4309-B54B-5FB79703195F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Profile", "Common\Commands.Profile\Commands.Profile.csproj", "{C60342B1-47D3-4A0E-8081-9B97CE60B7AF}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -349,10 +347,6 @@ Global {5EE72C53-1720-4309-B54B-5FB79703195F}.Debug|Any CPU.Build.0 = Debug|Any CPU {5EE72C53-1720-4309-B54B-5FB79703195F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5EE72C53-1720-4309-B54B-5FB79703195F}.Release|Any CPU.Build.0 = Release|Any CPU - {C60342B1-47D3-4A0E-8081-9B97CE60B7AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C60342B1-47D3-4A0E-8081-9B97CE60B7AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C60342B1-47D3-4A0E-8081-9B97CE60B7AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C60342B1-47D3-4A0E-8081-9B97CE60B7AF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -382,6 +376,5 @@ Global {152D78F0-A642-4D0E-B3A8-2FC64FFA9714} = {95C16AED-FD57-42A0-86C3-2CF4300A4817} {F220C306-29A3-4511-8518-A58A55C60D07} = {95C16AED-FD57-42A0-86C3-2CF4300A4817} {13E031E4-8A43-4B87-9D72-D70180C31C11} = {95C16AED-FD57-42A0-86C3-2CF4300A4817} - {C60342B1-47D3-4A0E-8081-9B97CE60B7AF} = {95C16AED-FD57-42A0-86C3-2CF4300A4817} EndGlobalSection EndGlobal From ecf227b2de9803c5aa3c3914c7892ae19a927e52 Mon Sep 17 00:00:00 2001 From: Hovsep Mkrtchyan Date: Fri, 11 Sep 2015 16:54:10 -0700 Subject: [PATCH 3/3] Fixed Login-AzureRMAccount --- .../LoginAzureRMAccount.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs index cadf1f4068a7..3d8f5d85bf7f 100644 --- a/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs +++ b/src/Common/Commands.ResourceManager.Profile/LoginAzureRMAccount.cs @@ -103,7 +103,12 @@ protected override void ProcessRecord() { azureAccount.SetProperty(AzureAccount.Property.Tenants, new[] { Tenant }); } - + + if( AzureRMCmdlet.DefaultProfile == null) + { + AzureRMCmdlet.DefaultProfile = new AzureRMProfile(); + } + var profileClient = new RMProfileClient(AzureRMCmdlet.DefaultProfile); WriteObject(profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, password));