Skip to content

Commit 3b1ea3c

Browse files
Merge pull request #8488 from Azure/release-2019-01-30
Push Release 2019 01 30 -> master
2 parents 56839c5 + 116c6cb commit 3b1ea3c

File tree

86 files changed

+488
-370
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+488
-370
lines changed

ChangeLog.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 1.2.1 - January 2019
2+
#### Az.Accounts
3+
* Release with correct version of Authentication
4+
5+
#### Az.AnalysisServices
6+
* Release with updated Authentication dependency
7+
8+
#### Az.RecoveryServices
9+
* Release with updated Authentication dependency
10+
111
## 1.2.0 - January 2019
212
#### Az.Accounts
313
* Add interactive and username/password authentication for Windows PowerShell 5.1 only

src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,24 @@ public override void ExecuteCmdlet()
229229
Path = "/oauth2/token"
230230
};
231231

232+
var envSecret = System.Environment.GetEnvironmentVariable(MSISecretVariable);
233+
232234
var msiSecret = this.IsBound(nameof(ManagedServiceSecret))
233235
? ManagedServiceSecret.ConvertToString()
234-
: System.Environment.GetEnvironmentVariable(MSISecretVariable);
236+
: envSecret;
237+
238+
var envUri = System.Environment.GetEnvironmentVariable(MSIEndpointVariable);
235239

236240
var suppliedUri = this.IsBound(nameof(ManagedServiceHostName))
237241
? builder.Uri.ToString()
238-
: System.Environment.GetEnvironmentVariable(MSIEndpointVariable);
242+
: envUri;
243+
244+
if (!this.IsBound(nameof(ManagedServiceHostName)) && !string.IsNullOrWhiteSpace(envUri)
245+
&& !this.IsBound(nameof(ManagedServiceSecret)) && !string.IsNullOrWhiteSpace(envSecret))
246+
{
247+
// set flag indicating this is AppService Managed Identity ad hoc mode
248+
azureAccount.SetProperty(AuthenticationFactory.AppServiceManagedIdentityFlag, "the value not used");
249+
}
239250

240251
if (!string.IsNullOrWhiteSpace(msiSecret))
241252
{

src/Accounts/Accounts/Az.Accounts.psd1

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# RootModule = ''
1313

1414
# Version number of this module.
15-
ModuleVersion = '1.2.0'
15+
ModuleVersion = '1.2.1'
1616

1717
# Supported PSEditions
1818
CompatiblePSEditions = 'Core', 'Desktop'
@@ -141,9 +141,7 @@ PrivateData = @{
141141
# IconUri = ''
142142

143143
# ReleaseNotes of this module
144-
ReleaseNotes = '* Add interactive and username/password authentication for Windows PowerShell 5.1 only
145-
* Update incorrect online help URLs
146-
* Add warning message in PS Core for Uninstall-AzureRm'
144+
ReleaseNotes = '* Release with correct version of Authentication'
147145

148146
# Prerelease string of this module
149147
# Prerelease = ''

src/Accounts/Accounts/ChangeLog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
## Upcoming Release
2121
* Update to latest version of ClientRuntime
2222

23+
## Version 1.2.1
24+
* Release with correct version of Authentication
25+
* Enable MSI Authentication in Azure Functions and WebApps
26+
2327
## Version 1.2.0
2428
* Add interactive and username/password authentication for Windows PowerShell 5.1 only
2529
* Update incorrect online help URLs

src/Accounts/Accounts/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
// You can specify all the values or you can default the Build and Revision Numbers
4444
// by using the '*' as shown below:
4545

46-
[assembly: AssemblyVersion("1.2.0")]
47-
[assembly: AssemblyFileVersion("1.2.0")]
46+
[assembly: AssemblyVersion("1.2.1")]
47+
[assembly: AssemblyFileVersion("1.2.1")]
4848
#if SIGN
4949
[assembly: InternalsVisibleTo("Microsoft.Azure.PowerShell.Cmdlets.Accounts.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
5050
[assembly: InternalsVisibleTo("Microsoft.WindowsAzure.Commands.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]

src/Accounts/Authentication.Test/AuthenticationFactoryTests.cs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
using Microsoft.Azure.Commands.Common.Authentication;
1616
using Microsoft.Azure.Commands.Common.Authentication.Factories;
17-
using Microsoft.Azure.Commands.Common.Authentication.Models;
1817
using Microsoft.WindowsAzure.Commands.Test.Utilities.Common;
1918
using System;
2019
using System.Collections.Generic;
@@ -25,8 +24,6 @@
2524
using Microsoft.Azure.Commands.Common.Authentication.Test;
2625
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2726
using Xunit.Abstractions;
28-
using Microsoft.Rest.Azure;
29-
using Microsoft.Azure.Commands.ResourceManager.Common;
3027

3128
namespace Common.Authentication.Test
3229
{
@@ -180,7 +177,7 @@ public void CanAuthenticateUsingMSIDefault()
180177
IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null);
181178
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
182179
Assert.Equal(expectedAccessToken, token.AccessToken);
183-
Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds));
180+
Assert.Equal(3600, Math.Round(token.ExpiresOn.Subtract(DateTimeOffset.Now).TotalSeconds));
184181
var account2 = new AzureAccount
185182
{
186183
Id = userId,
@@ -230,7 +227,7 @@ public void CanAuthenticateUsingMSIResourceId()
230227
IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null);
231228
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
232229
Assert.Equal(expectedAccessToken, token.AccessToken);
233-
Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds));
230+
Assert.Equal(3600, Math.Round(token.ExpiresOn.Subtract(DateTimeOffset.Now).TotalSeconds));
234231
var account2 = new AzureAccount
235232
{
236233
Id = userId,
@@ -279,7 +276,7 @@ public void CanAuthenticateUsingMSIClientId()
279276
IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null);
280277
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
281278
Assert.Equal(expectedAccessToken, token.AccessToken);
282-
Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds));
279+
Assert.Equal(3600, Math.Round(token.ExpiresOn.Subtract(DateTimeOffset.Now).TotalSeconds));
283280
var account2 = new AzureAccount
284281
{
285282
Id = userId,
@@ -328,7 +325,7 @@ public void CanAuthenticateUsingMSIObjectId()
328325
IRenewableToken token = (IRenewableToken) authFactory.Authenticate(account, environment, tenant, null, null, null);
329326
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
330327
Assert.Equal(expectedAccessToken, token.AccessToken);
331-
Assert.Equal(3600, Math.Round(token.ExpiresOn.DateTime.Subtract(DateTime.UtcNow).TotalSeconds));
328+
Assert.Equal(3600, Math.Round(token.ExpiresOn.Subtract(DateTimeOffset.Now).TotalSeconds));
332329
var account2 = new AzureAccount
333330
{
334331
Id = userId,
@@ -351,7 +348,6 @@ void ResponseRedactionWorks()
351348

352349
void VerifyToken(IAccessToken checkToken, string expectedAccessToken, string expectedUserId, string expectedTenant)
353350
{
354-
355351
Assert.True(checkToken is RawAccessToken);
356352
Assert.Equal(expectedAccessToken, checkToken.AccessToken);
357353
Assert.Equal(expectedUserId, checkToken.UserId);
@@ -363,5 +359,45 @@ void VerifyToken(IAccessToken checkToken, string expectedAccessToken, string exp
363359
});
364360
}
365361

362+
[Fact]
363+
[Trait(Category.AcceptanceType, Category.CheckIn)]
364+
public void AppServiceManagedIdentity()
365+
{
366+
AzureSessionInitializer.InitializeAzureSession();
367+
var tenant = Guid.NewGuid().ToString();
368+
var userId = Guid.NewGuid().ToString();
369+
var environment = AzureEnvironment.PublicEnvironments["AzureCloud"];
370+
var account = new AzureAccount
371+
{
372+
Id = userId,
373+
Type = AzureAccount.AccountType.ManagedService
374+
};
375+
const string resource = @"https://management.azure.com/";
376+
const string endpoint = @"http://127.0.0.1:41217/MSI/token/";
377+
var expectedUri = $"{endpoint}?resource={resource}&api-version=2017-09-01";
378+
account.SetProperty(AzureAccount.Property.MSILoginUri , endpoint);
379+
account.SetProperty(AzureAccount.Property.MSILoginSecret , @"bar");
380+
const string expectedAccessToken = "foo";
381+
var expectedExpiresOn = DateTimeOffset.Parse("1/23/2019 7:15:42 AM +00:00");
382+
var responses = new Dictionary<string, ManagedServiceAppServiceTokenInfo>(StringComparer.OrdinalIgnoreCase)
383+
{
384+
{
385+
expectedUri,
386+
new ManagedServiceAppServiceTokenInfo()
387+
{
388+
AccessToken = expectedAccessToken,
389+
ExpiresOn = expectedExpiresOn,
390+
Resource = resource,
391+
TokenType = "Bearer",
392+
}
393+
}
394+
};
395+
AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true);
396+
var msat = new ManagedServiceAppServiceAccessToken(account, environment, tenant);
397+
Assert.Equal(expectedUri, msat.RequestUris.Peek());
398+
var accessToken = msat.AccessToken;
399+
Assert.Equal(expectedAccessToken, accessToken);
400+
Assert.Equal(expectedExpiresOn, msat.ExpiresOn);
401+
}
366402
}
367403
}

src/Accounts/Authentication/Authentication/ManagedServiceAccessToken.cs

Lines changed: 5 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -13,204 +13,24 @@
1313
// ----------------------------------------------------------------------------------
1414

1515
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
16-
using Microsoft.Azure.Commands.Common.Authentication.Properties;
17-
using Microsoft.Rest.Azure;
1816
using System;
19-
using System.Collections.Generic;
20-
using System.Net.Http;
21-
using System.Text;
22-
using System.Threading;
2317

2418
namespace Microsoft.Azure.Commands.Common.Authentication
2519
{
26-
public class ManagedServiceAccessToken : IRenewableToken
20+
public class ManagedServiceAccessToken : ManagedServiceAccessTokenBase<ManagedServiceTokenInfo>
2721
{
28-
IAzureAccount _account;
29-
string _tenant;
30-
string _resourceId;
31-
IHttpOperations<ManagedServiceTokenInfo> _tokenGetter;
32-
DateTime _expiration = DateTime.UtcNow;
33-
string _accessToken;
34-
3522
public ManagedServiceAccessToken(IAzureAccount account, IAzureEnvironment environment, string resourceId, string tenant = "Common")
23+
: base(account, environment, resourceId, tenant)
3624
{
37-
if (account == null || string.IsNullOrEmpty(account.Id) || !account.IsPropertySet(AzureAccount.Property.MSILoginUri))
38-
{
39-
throw new ArgumentNullException(nameof(account));
40-
}
41-
42-
if (string.IsNullOrWhiteSpace(tenant))
43-
{
44-
throw new ArgumentNullException(nameof(tenant));
45-
}
46-
47-
if (environment == null)
48-
{
49-
throw new ArgumentNullException(nameof(environment));
50-
}
51-
52-
_account = account;
53-
_resourceId = GetResource(resourceId, environment);
54-
var idType = GetIdentityType(account);
55-
foreach (var uri in BuildTokenUri(_account.GetProperty(AzureAccount.Property.MSILoginUri), account, idType, _resourceId))
56-
{
57-
RequestUris.Enqueue(uri);
58-
}
59-
60-
if (account.IsPropertySet(AzureAccount.Property.MSILoginUriBackup))
61-
{
62-
foreach (var uri in BuildTokenUri(_account.GetProperty(AzureAccount.Property.MSILoginUriBackup), account, idType, _resourceId))
63-
{
64-
RequestUris.Enqueue(uri);
65-
}
66-
}
67-
68-
_tenant = tenant;
69-
IHttpOperationsFactory factory;
70-
if (!AzureSession.Instance.TryGetComponent(HttpClientOperationsFactory.Name, out factory))
71-
{
72-
factory = HttpClientOperationsFactory.Create();
73-
}
74-
75-
_tokenGetter = factory.GetHttpOperations<ManagedServiceTokenInfo>(true).WithHeader("Metadata", new[] { "true" });
76-
if (account.IsPropertySet(AzureAccount.Property.MSILoginSecret))
77-
{
78-
_tokenGetter = _tokenGetter.WithHeader("Secret", new[] { account.GetProperty(AzureAccount.Property.MSILoginSecret) });
79-
}
80-
}
81-
82-
public string AccessToken
83-
{
84-
get
85-
{
86-
try
87-
{
88-
GetOrRenewAuthentication();
89-
}
90-
catch (CloudException httpException)
91-
{
92-
throw new InvalidOperationException(string.Format(Resources.MSITokenRequestFailed, _resourceId, httpException?.Request?.RequestUri?.ToString()), httpException);
93-
}
94-
95-
return _accessToken;
96-
}
97-
}
98-
99-
public Queue<string> RequestUris { get; } = new Queue<string>();
100-
101-
public string LoginType => "ManagedService";
102-
103-
public string TenantId => _tenant;
104-
105-
public string UserId => _account.Id;
106-
107-
public DateTimeOffset ExpiresOn
108-
{
109-
get
110-
{
111-
return _expiration;
112-
}
113-
}
114-
115-
public void AuthorizeRequest(Action<string, string> authTokenSetter)
116-
{
117-
authTokenSetter("Bearer", AccessToken);
118-
}
119-
120-
void GetOrRenewAuthentication()
121-
{
122-
if (_expiration - DateTime.UtcNow < ManagedServiceTokenInfo.TimeoutThreshold)
123-
{
124-
ManagedServiceTokenInfo info = null;
125-
while (info == null && RequestUris.Count > 0)
126-
{
127-
var currentRequestUri = RequestUris.Dequeue();
128-
try
129-
{
130-
info = _tokenGetter.GetAsync(currentRequestUri, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
131-
// if a request was succesful, we should not check any other Uris
132-
RequestUris.Clear();
133-
RequestUris.Enqueue(currentRequestUri);
134-
}
135-
catch (Exception e) when ( (e is CloudException || e is HttpRequestException) && RequestUris.Count > 0)
136-
{
137-
// skip to the next uri
138-
}
139-
}
140-
141-
SetToken(info);
142-
}
14325
}
14426

145-
void SetToken(ManagedServiceTokenInfo info)
27+
protected override void SetToken(ManagedServiceTokenInfo info)
14628
{
14729
if (info != null)
14830
{
149-
_expiration = DateTime.UtcNow + TimeSpan.FromSeconds(info.ExpiresIn);
150-
_accessToken = info.AccessToken;
151-
}
152-
}
153-
154-
static IdentityType GetIdentityType(IAzureAccount account)
155-
{
156-
if (account == null || string.IsNullOrWhiteSpace(account.Id) || account.Id.Contains("@"))
157-
{
158-
return IdentityType.SystemAssigned;
159-
}
160-
161-
if (account.Id.Contains("/"))
162-
{
163-
return IdentityType.Resource;
164-
}
165-
166-
return IdentityType.ClientId;
167-
}
168-
169-
static string GetResource(string endpointOrResource, IAzureEnvironment environment)
170-
{
171-
return environment.GetEndpoint(endpointOrResource) ?? endpointOrResource;
172-
}
173-
174-
static IEnumerable<string> BuildTokenUri(string baseUri, IAzureAccount account, IdentityType identityType, string resourceId)
175-
{
176-
UriBuilder builder = new UriBuilder(baseUri);
177-
builder.Query = BuildTokenQuery(account, identityType, resourceId);
178-
yield return builder.Uri.ToString();
179-
180-
if (identityType == IdentityType.ClientId)
181-
{
182-
builder = new UriBuilder(baseUri);
183-
builder.Query = BuildTokenQuery(account, IdentityType.ObjectId, resourceId);
184-
yield return builder.Uri.ToString();
31+
Expiration = DateTimeOffset.Now + TimeSpan.FromSeconds(info.ExpiresIn);
32+
accessToken = info.AccessToken;
18533
}
18634
}
187-
188-
static string BuildTokenQuery(IAzureAccount account, IdentityType idType, string resource)
189-
{
190-
StringBuilder query = new StringBuilder($"resource={Uri.EscapeDataString(resource)}");
191-
switch (idType)
192-
{
193-
case IdentityType.Resource:
194-
query.Append($"&msi_res_id={Uri.EscapeDataString(account.Id)}");
195-
break;
196-
case IdentityType.ClientId:
197-
query.Append($"&client_id={Uri.EscapeDataString(account.Id)}");
198-
break;
199-
case IdentityType.ObjectId:
200-
query.Append($"&object_id={Uri.EscapeDataString(account.Id)}");
201-
break;
202-
}
203-
204-
query.Append("&api-version=2018-02-01");
205-
return query.ToString();
206-
}
207-
208-
enum IdentityType
209-
{
210-
Resource,
211-
ClientId,
212-
ObjectId,
213-
SystemAssigned
214-
}
21535
}
21636
}

0 commit comments

Comments
 (0)