Skip to content

Add MSI eMSI support #5771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ public static class Property
/// <summary>
/// Login Uri for Managed Service Login
/// </summary>
MSILoginUri = "MSILoginUri";
MSILoginUri = "MSILoginUri",

/// <summary>
/// Backup login Uri for MSI
/// </summary>
MSILoginUriBackup = "MSILoginBackup";


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using Microsoft.Azure.Commands.Common.Authentication.Test;
using Microsoft.WindowsAzure.Commands.Utilities.Common;
using Xunit.Abstractions;
using Microsoft.Rest.Azure;

namespace Common.Authentication.Test
{
Expand Down Expand Up @@ -162,14 +163,14 @@ public void CanAuthenticateUsingMSIDefault()
};
var environment = AzureEnvironment.PublicEnvironments["AzureCloud"];
var expectedResource = environment.ActiveDirectoryServiceEndpointResourceId;
var builder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
builder.Query = string.Format("resource={0}", Uri.EscapeDataString(environment.ActiveDirectoryServiceEndpointResourceId));
var builder = new UriBuilder(AuthenticationFactory.DefaultBackupMSILoginUri);
builder.Query = $"resource={Uri.EscapeDataString(environment.ActiveDirectoryServiceEndpointResourceId)}&api-version=2018-02-01";
var defaultUri = builder.Uri.ToString();

var responses = new Dictionary<string, ManagedServiceTokenInfo>(StringComparer.OrdinalIgnoreCase)
{
{defaultUri, new ManagedServiceTokenInfo { AccessToken = expectedAccessToken, ExpiresIn = 3600, Resource=expectedResource}},
{"http://myfunkyurl:10432/oauth2/token?resource=foo", new ManagedServiceTokenInfo { AccessToken = expectedToken2, ExpiresIn = 3600, Resource="foo"} }
{"http://myfunkyurl:10432/oauth2/token?resource=foo&api-version=2018-02-01", new ManagedServiceTokenInfo { AccessToken = expectedToken2, ExpiresIn = 3600, Resource="foo"} }
};
AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true);
var authFactory = new AuthenticationFactory();
Expand All @@ -189,6 +190,150 @@ public void CanAuthenticateUsingMSIDefault()
Assert.Throws<InvalidOperationException>(() => token3.AccessToken);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void CanAuthenticateUsingMSIResourceId()
{
AzureSessionInitializer.InitializeAzureSession();
string expectedAccessToken = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for ARM URI: {0}", expectedAccessToken);
string expectedToken2 = Guid.NewGuid().ToString();
string tenant = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for graph URI: {0}", expectedToken2);
string userId = "/foo/bar/baz";
var account = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var environment = AzureEnvironment.PublicEnvironments["AzureCloud"];
var expectedResource = environment.ActiveDirectoryServiceEndpointResourceId;
var builder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
builder.Query = $"resource={Uri.EscapeDataString(environment.ActiveDirectoryServiceEndpointResourceId)}&msi_res_id={Uri.EscapeDataString(userId)}&api-version=2018-02-01";
var defaultUri = builder.Uri.ToString();

var customBuilder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
customBuilder.Query = $"resource={Uri.EscapeDataString(environment.GraphEndpointResourceId)}&msi_res_id={Uri.EscapeDataString(userId)}&api-version=2018-02-01";
var customUri = customBuilder.Uri.ToString();

var responses = new Dictionary<string, ManagedServiceTokenInfo>(StringComparer.OrdinalIgnoreCase)
{
{defaultUri, new ManagedServiceTokenInfo { AccessToken = expectedAccessToken, ExpiresIn = 3600, Resource=expectedResource}},
{customUri, new ManagedServiceTokenInfo { AccessToken = expectedToken2, ExpiresIn = 3600, Resource=environment.GraphEndpointResourceId} }
};
AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true);
var authFactory = new AuthenticationFactory();
var token = authFactory.Authenticate(account, environment, tenant, null, null, null);
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
Assert.Equal(expectedAccessToken, token.AccessToken);
var account2 = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var token2 = authFactory.Authenticate(account2, environment, tenant, null, null, null, AzureEnvironment.Endpoint.GraphEndpointResourceId);
_output.WriteLine($"Received access token for custom Uri ${token2.AccessToken}");
Assert.Equal(expectedToken2, token2.AccessToken);
var token3 = authFactory.Authenticate(account, environment, tenant, null, null, null, "bar");
Assert.Throws<InvalidOperationException>(() => token3.AccessToken);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void CanAuthenticateUsingMSIClientId()
{
AzureSessionInitializer.InitializeAzureSession();
string expectedAccessToken = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for ARM URI: {0}", expectedAccessToken);
string expectedToken2 = Guid.NewGuid().ToString();
string tenant = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for graph URI: {0}", expectedToken2);
string userId = Guid.NewGuid().ToString();
var account = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var environment = AzureEnvironment.PublicEnvironments["AzureCloud"];
var expectedResource = environment.ActiveDirectoryServiceEndpointResourceId;
var builder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
builder.Query = $"resource={Uri.EscapeDataString(environment.ActiveDirectoryServiceEndpointResourceId)}&client_id={userId}&api-version=2018-02-01";
var defaultUri = builder.Uri.ToString();

var customBuilder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
customBuilder.Query = $"resource={Uri.EscapeDataString(environment.GraphEndpointResourceId)}&client_id={userId}&api-version=2018-02-01";
var customUri = customBuilder.Uri.ToString();

var responses = new Dictionary<string, ManagedServiceTokenInfo>(StringComparer.OrdinalIgnoreCase)
{
{defaultUri, new ManagedServiceTokenInfo { AccessToken = expectedAccessToken, ExpiresIn = 3600, Resource=expectedResource}},
{customUri, new ManagedServiceTokenInfo { AccessToken = expectedToken2, ExpiresIn = 3600, Resource=environment.GraphEndpointResourceId} }
};
AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true);
var authFactory = new AuthenticationFactory();
var token = authFactory.Authenticate(account, environment, tenant, null, null, null);
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
Assert.Equal(expectedAccessToken, token.AccessToken);
var account2 = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var token2 = authFactory.Authenticate(account2, environment, tenant, null, null, null, AzureEnvironment.Endpoint.GraphEndpointResourceId);
_output.WriteLine($"Received access token for custom Uri ${token2.AccessToken}");
Assert.Equal(expectedToken2, token2.AccessToken);
var token3 = authFactory.Authenticate(account, environment, tenant, null, null, null, "bar");
Assert.Throws<InvalidOperationException>(() => token3.AccessToken);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void CanAuthenticateUsingMSIObjectId()
{
AzureSessionInitializer.InitializeAzureSession();
string expectedAccessToken = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for ARM URI: {0}", expectedAccessToken);
string expectedToken2 = Guid.NewGuid().ToString();
string tenant = Guid.NewGuid().ToString();
_output.WriteLine("Expected access token for graph URI: {0}", expectedToken2);
string userId = Guid.NewGuid().ToString();
var account = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var environment = AzureEnvironment.PublicEnvironments["AzureCloud"];
var expectedResource = environment.ActiveDirectoryServiceEndpointResourceId;
var builder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
builder.Query = $"resource={Uri.EscapeDataString(environment.ActiveDirectoryServiceEndpointResourceId)}&object_id={userId}&api-version=2018-02-01";
var defaultUri = builder.Uri.ToString();

var customBuilder = new UriBuilder(AuthenticationFactory.DefaultMSILoginUri);
customBuilder.Query = $"resource={Uri.EscapeDataString(environment.GraphEndpointResourceId)}&object_id={userId}&api-version=2018-02-01";
var customUri = customBuilder.Uri.ToString();

var responses = new Dictionary<string, ManagedServiceTokenInfo>(StringComparer.OrdinalIgnoreCase)
{
{defaultUri, new ManagedServiceTokenInfo { AccessToken = expectedAccessToken, ExpiresIn = 3600, Resource=expectedResource}},
{customUri, new ManagedServiceTokenInfo { AccessToken = expectedToken2, ExpiresIn = 3600, Resource=environment.GraphEndpointResourceId} }
};
AzureSession.Instance.RegisterComponent(HttpClientOperationsFactory.Name, () => TestHttpOperationsFactory.Create(responses, _output), true);
var authFactory = new AuthenticationFactory();
var token = authFactory.Authenticate(account, environment, tenant, null, null, null);
_output.WriteLine($"Received access token for default Uri ${token.AccessToken}");
Assert.Equal(expectedAccessToken, token.AccessToken);
var account2 = new AzureAccount
{
Id = userId,
Type = AzureAccount.AccountType.ManagedService
};
var token2 = authFactory.Authenticate(account2, environment, tenant, null, null, null, AzureEnvironment.Endpoint.GraphEndpointResourceId);
_output.WriteLine($"Received access token for custom Uri ${token2.AccessToken}");
Assert.Equal(expectedToken2, token2.AccessToken);
var token3 = authFactory.Authenticate(account, environment, tenant, null, null, null, "bar");
Assert.Throws<InvalidOperationException>(() => token3.AccessToken);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
void ResponseRedactionWorks()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using Microsoft.Rest.Azure;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
Expand All @@ -31,7 +32,13 @@ private TestHttpOperationsFactory()
}

IDictionary<string, object> _responses = new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase);
public IHttpOperations<T> GetHttpOperations<T>()
public IHttpOperations<T> GetHttpOperations<T>() where T : class, ICacheable
{
var result = new TestHttpOperations<T>(_responses, _output);
return result;
}

public IHttpOperations<T> GetHttpOperations<T>(bool useCaching) where T : class, ICacheable
{
var result = new TestHttpOperations<T>(_responses, _output);
return result;
Expand Down Expand Up @@ -83,7 +90,7 @@ public Task<T> GetAsync(string requestUri, CancellationToken token)
{
if (!_responses.ContainsKey(requestUri))
{
throw new InvalidOperationException(string.Format("Unexpected request Uri '{0}'", requestUri));
throw new CloudException(string.Format("Unexpected request Uri '{0}'", requestUri));
}

var output = _responses[requestUri];
Expand Down
Loading