Skip to content

Commit 078fc60

Browse files
author
Hovsep Mkrtchyan
committed
Added AzureLogin cmdlets
1 parent b62fa7d commit 078fc60

File tree

5 files changed

+241
-96
lines changed

5 files changed

+241
-96
lines changed

src/Common/Commands.ResourceManager.Common/RMProfileClient.cs

Lines changed: 97 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,110 +13,151 @@
1313
// ----------------------------------------------------------------------------------
1414

1515
using Hyak.Common;
16-
using Microsoft.Azure.Commands.ResourceManager.Common.Properties;
1716
using Microsoft.Azure.Common.Authentication;
1817
using Microsoft.Azure.Common.Authentication.Factories;
1918
using Microsoft.Azure.Common.Authentication.Models;
2019
using Microsoft.Azure.Subscriptions;
2120
using System;
2221
using System.Collections.Generic;
2322
using System.Linq;
23+
using System.Management.Automation;
2424
using System.Security;
25-
using System.Text;
26-
using System.Threading.Tasks;
2725

2826
namespace Microsoft.Azure.Commands.ResourceManager.Common
2927
{
3028
public class RMProfileClient
3129
{
3230
private AzureRMProfile _profile;
31+
public Action<string> WarningLog;
3332

3433
public RMProfileClient(AzureRMProfile profile)
3534
{
3635
_profile = profile;
3736
}
3837

39-
public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId)
38+
public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, SecureString password)
4039
{
41-
var tenant = string.IsNullOrEmpty(tenantId) ? AuthenticationFactory.CommonAdTenant : tenantId;
40+
AzureSubscription newSubscription = null;
41+
AzureTenant newTenant = new AzureTenant();
4242

43-
var commonTenantToken = AzureSession.AuthenticationFactory.Authenticate(account, environment, tenant, null, ShowDialog.Auto);
44-
45-
using (SubscriptionClient SubscriptionClient = AzureSession.ClientFactory.CreateCustomClient<SubscriptionClient>(
46-
new TokenCloudCredentials(commonTenantToken.AccessToken),
47-
environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ServiceManagement)))
43+
// (tenant and subscription are present) OR
44+
// (tenant is present and subscription is not provided)
45+
if (!string.IsNullOrEmpty(tenantId))
4846
{
49-
var tenantListResult = SubscriptionClient.Tenants.List();
50-
51-
if (!string.IsNullOrEmpty(tenantId) && !tenantListResult.TenantIds.Any(s => s.TenantId.Equals(tenantId, StringComparison.OrdinalIgnoreCase)))
47+
newTenant.Id = new Guid(tenantId);
48+
ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never;
49+
TryGetTenantSubscription(account, environment, tenantId, subscriptionId, password, promptBehavior, out newSubscription);
50+
}
51+
// (tenant is not provided and subscription is present) OR
52+
// (tenant is not provided and subscription is not provided)
53+
else
54+
{
55+
foreach(var tenant in ListAccountTenants(account, environment, password))
5256
{
53-
throw new ArgumentException(string.Format(Resources.TenantNotFound, tenantId));
57+
if (TryGetTenantSubscription(account, environment, tenant, subscriptionId, password, ShowDialog.Auto, out newSubscription))
58+
{
59+
newTenant.Id = new Guid(tenant);
60+
break;
61+
}
5462
}
5563

56-
_profile.
57-
//ListResourceManagerSubscriptions
58-
64+
}
5965

60-
//_profile.DefaultContext = new AzureContext();
66+
if (newSubscription == null)
67+
{
68+
throw new PSInvalidOperationException("Subscription was not found.");
6169
}
6270

71+
_profile.DefaultContext = new AzureContext(newSubscription, account, environment, newTenant);
72+
6373
return _profile;
6474
}
6575

66-
public IEnumerable<string> GetTenantSubscriptions(AzureAccount account, AzureEnvironment environment, string tenantId, SecureString password)
76+
private bool TryGetTenantSubscription(
77+
AzureAccount account,
78+
AzureEnvironment environment,
79+
string tenantId,
80+
string subscriptionId,
81+
SecureString password,
82+
ShowDialog promptBehavior,
83+
out AzureSubscription subscription)
6784
{
68-
try
85+
var accessToken = AzureSession.AuthenticationFactory.Authenticate(
86+
account,
87+
environment,
88+
tenantId,
89+
password,
90+
promptBehavior);
91+
using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient<SubscriptionClient>(
92+
new TokenCloudCredentials(accessToken.AccessToken),
93+
environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager)))
6994
{
70-
var tenantAccount = new AzureAccount();
71-
CopyAccount(account, tenantAccount);
72-
var tenantToken = AzureSession.AuthenticationFactory.Authenticate(tenantAccount, environment, tenantId, password, ShowDialog.Never);
73-
if (string.Equals(tenantAccount.Id, account.Id, StringComparison.InvariantCultureIgnoreCase))
95+
Subscriptions.Models.Subscription subscriptionFromServer = null;
96+
97+
try
7498
{
75-
tenantAccount = account;
99+
if (subscriptionId != null)
100+
{
101+
subscriptionFromServer = subscriptionClient.Subscriptions.Get(subscriptionId).Subscription;
102+
}
103+
else
104+
{
105+
var subscriptions = subscriptionClient.Subscriptions.List().Subscriptions;
106+
if (subscriptions != null)
107+
{
108+
if (subscriptions.Count > 1)
109+
{
110+
WriteWarningMessage(string.Format(
111+
"Tenant '{0}' contains more than one subscription. First one will be selected for further use.",
112+
tenantId));
113+
}
114+
subscriptionFromServer = subscriptions.First();
115+
}
116+
}
76117
}
77-
78-
tenantAccount.SetOrAppendProperty(AzureAccount.Property.Tenants, new string[] { tenantId });
79-
80-
using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient<SubscriptionClient>(
81-
new TokenCloudCredentials(tenantToken.AccessToken),
82-
environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager)))
118+
catch (CloudException ex)
83119
{
84-
var subscriptionListResult = subscriptionClient.Subscriptions.List();
85-
86-
return subscriptionListResult.Subscriptions.Select(s => s.SubscriptionId);
120+
WriteWarningMessage(ex.Message);
87121
}
88122

123+
if (subscriptionFromServer != null)
124+
{
125+
subscription = new AzureSubscription
126+
{
127+
Id = new Guid(subscriptionFromServer.SubscriptionId),
128+
Account = accessToken.UserId,
129+
Environment = environment.Name,
130+
Name = subscriptionFromServer.DisplayName,
131+
Properties = new Dictionary<AzureSubscription.Property, string> { { AzureSubscription.Property.Tenants, accessToken.TenantId } }
132+
};
133+
return true;
134+
}
89135

90-
}
91-
catch (CloudException cEx)
92-
{
93-
WriteOrThrowAadExceptionMessage(cEx);
94-
}
95-
catch (AadAuthenticationException aadEx)
96-
{
97-
WriteOrThrowAadExceptionMessage(aadEx);
136+
subscription = null;
137+
return false;
98138
}
99139
}
100140

101-
private void CopyAccount(AzureAccount sourceAccount, AzureAccount targetAccount)
141+
private string[] ListAccountTenants(AzureAccount account, AzureEnvironment environment, SecureString password)
102142
{
103-
targetAccount.Id = sourceAccount.Id;
104-
targetAccount.Type = sourceAccount.Type;
105-
}
143+
ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never;
106144

107-
private void WriteOrThrowAadExceptionMessage(AadAuthenticationException aadEx)
108-
{
109-
if (aadEx is AadAuthenticationFailedWithoutPopupException)
110-
{
111-
WriteDebugMessage(aadEx.Message);
112-
}
113-
else if (aadEx is AadAuthenticationCanceledException)
145+
var commonTenantToken = AzureSession.AuthenticationFactory.Authenticate(account, environment,
146+
AuthenticationFactory.CommonAdTenant, password, promptBehavior);
147+
148+
using (var subscriptionClient = AzureSession.ClientFactory.CreateCustomClient<SubscriptionClient>(
149+
new TokenCloudCredentials(commonTenantToken.AccessToken),
150+
environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager)))
114151
{
115-
WriteWarningMessage(aadEx.Message);
152+
return subscriptionClient.Tenants.List().TenantIds.Select(ti => ti.TenantId).ToArray();
116153
}
117-
else
154+
}
155+
156+
private void WriteWarningMessage(string message)
157+
{
158+
if (WarningLog != null)
118159
{
119-
throw aadEx;
160+
WarningLog(message);
120161
}
121162
}
122163
}

src/Common/Commands.ResourceManager.Profile.Test/Commands.ResourceManager.Profile.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
</Reference>
179179
</ItemGroup>
180180
<ItemGroup>
181+
<Compile Include="LoginCmdletTests.cs" />
181182
<Compile Include="ProfileCmdletTests.cs" />
182183
<Compile Include="Properties\AssemblyInfo.cs" />
183184
</ItemGroup>
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
16+
using Microsoft.Azure.Commands.Profile;
17+
using Microsoft.Azure.Commands.ResourceManager.Common;
18+
using Microsoft.Azure.Common.Authentication;
19+
using Microsoft.Azure.Common.Authentication.Models;
20+
using Microsoft.WindowsAzure.Commands.Common.Test.Mocks;
21+
using Microsoft.WindowsAzure.Commands.ScenarioTest;
22+
using System.Linq;
23+
using Xunit;
24+
using System;
25+
using Microsoft.WindowsAzure.Commands.Test.Utilities.Common;
26+
using Hyak.Common;
27+
using System.Management.Automation;
28+
29+
namespace Microsoft.Azure.Commands.Profile.Test
30+
{
31+
public class LoginCmdletTests
32+
{
33+
private MemoryDataStore dataStore;
34+
private MockCommandRuntime commandRuntimeMock;
35+
36+
public LoginCmdletTests()
37+
{
38+
dataStore = new MemoryDataStore();
39+
AzureSession.DataStore = dataStore;
40+
commandRuntimeMock = new MockCommandRuntime();
41+
AzureRMCmdlet.DefaultProfile = new AzureRMProfile();
42+
}
43+
44+
[Fact]
45+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
46+
public void LoginWithSubscriptionAndTenant()
47+
{
48+
var cmdlt = new LoginAzureRMAccount();
49+
// Setup
50+
cmdlt.CommandRuntime = commandRuntimeMock;
51+
cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a6";
52+
cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47";
53+
54+
// Act
55+
cmdlt.InvokeBeginProcessing();
56+
cmdlt.ExecuteCmdlet();
57+
cmdlt.InvokeEndProcessing();
58+
59+
Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext);
60+
}
61+
62+
[Fact]
63+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
64+
public void LoginWithInvalidSubscriptionAndTenantThrowsCloudException()
65+
{
66+
var cmdlt = new LoginAzureRMAccount();
67+
// Setup
68+
cmdlt.CommandRuntime = commandRuntimeMock;
69+
cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a5";
70+
cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47";
71+
72+
// Act
73+
cmdlt.InvokeBeginProcessing();
74+
Assert.Throws<PSInvalidOperationException>(() => cmdlt.ExecuteCmdlet());
75+
cmdlt.InvokeEndProcessing();
76+
}
77+
78+
[Fact]
79+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
80+
public void LoginWithSubscriptionAndNoTenant()
81+
{
82+
var cmdlt = new LoginAzureRMAccount();
83+
// Setup
84+
cmdlt.CommandRuntime = commandRuntimeMock;
85+
cmdlt.SubscriptionId = "2c224e7e-3ef5-431d-a57b-e71f4662e3a6";
86+
87+
// Act
88+
cmdlt.InvokeBeginProcessing();
89+
cmdlt.ExecuteCmdlet();
90+
cmdlt.InvokeEndProcessing();
91+
92+
Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext);
93+
}
94+
95+
[Fact]
96+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
97+
public void LoginWithNoSubscriptionAndNoTenant()
98+
{
99+
var cmdlt = new LoginAzureRMAccount();
100+
// Setup
101+
cmdlt.CommandRuntime = commandRuntimeMock;
102+
103+
// Act
104+
cmdlt.InvokeBeginProcessing();
105+
cmdlt.ExecuteCmdlet();
106+
cmdlt.InvokeEndProcessing();
107+
108+
Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext);
109+
}
110+
111+
[Fact]
112+
[Trait(Category.AcceptanceType, Category.LiveOnly)]
113+
public void LoginWithNoSubscriptionAndTenant()
114+
{
115+
var cmdlt = new LoginAzureRMAccount();
116+
// Setup
117+
cmdlt.CommandRuntime = commandRuntimeMock;
118+
cmdlt.Tenant = "72f988bf-86f1-41af-91ab-2d7cd011db47";
119+
120+
// Act
121+
cmdlt.InvokeBeginProcessing();
122+
cmdlt.ExecuteCmdlet();
123+
cmdlt.InvokeEndProcessing();
124+
125+
Assert.NotNull(AzureRMCmdlet.DefaultProfile.DefaultContext);
126+
}
127+
}
128+
}

0 commit comments

Comments
 (0)