Skip to content

Commit

Permalink
First iteration of a simple ManagedIdentity integration test (#33017)
Browse files Browse the repository at this point in the history
* First iteration of a simple ManagedIdentity integration test
  • Loading branch information
christothes authored Dec 13, 2022
1 parent a7a6b0b commit 141bae7
Show file tree
Hide file tree
Showing 18 changed files with 362 additions and 46 deletions.
1 change: 1 addition & 0 deletions eng/.docsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ omitted_paths:
- samples/*
- sdk/*/*.Management.*/*
- sdk/*/*/perf/*
- sdk/*/*/integration/*
- sdk/*/*/tests/Samples/*
- sdk/*/*/tests/samples/*
- sdk/*/*/samples/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Linq;
using Azure.Core;
using Azure.Identity;
using Azure.Storage.Blobs;
using Microsoft.AspNetCore.Mvc;

namespace WebApp.Controllers
{

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{

[HttpGet(Name = "GetTest")]
public IActionResult Get()
{
string resourceId = Environment.GetEnvironmentVariable("IDENTITY_WEBAPP_USER_DEFINED_IDENTITY")!;
string account1 = Environment.GetEnvironmentVariable("IDENTITY_STORAGE_NAME_1")!;
string account2 = Environment.GetEnvironmentVariable("IDENTITY_STORAGE_NAME_2")!;

var credential1 = new ManagedIdentityCredential();
var credential2 = new ManagedIdentityCredential(new ResourceIdentifier(resourceId));
var client1 = new BlobServiceClient(new Uri($"https://{account1}.blob.core.windows.net/"), credential1);
var client2 = new BlobServiceClient(new Uri($"https://{account2}.blob.core.windows.net/"), credential2);
try
{
var results = client1.GetBlobContainers().ToList();
results = client2.GetBlobContainers().ToList();
return Ok("Successfully acquired a token from ManagedIdentityCredential");
}
catch (Exception ex)
{
return BadRequest(ex.ToString());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Azure.Identity.csproj" />
</ItemGroup>

</Project>
21 changes: 21 additions & 0 deletions sdk/identity/Azure.Identity/integration/WebApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

var app = builder.Build();

// Configure the HTTP request pipeline.
app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
14 changes: 14 additions & 0 deletions sdk/identity/Azure.Identity/integration/nuget.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<!--
<add key="repositoryPath" value="./NugetInstall" />
<add key="globalPackagesFolder" value="./Nuget" />
-->
<add key="repositoryPath" value="%AGENT_WORKFOLDER%/NugetInstall" />
<add key="globalPackagesFolder" value="%AGENT_WORKFOLDER%/Nuget" />
</config>
<packageSources>
<add key="NuGet official package source" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Azure.Core;
using Azure.Core.TestFramework;
using Microsoft.Identity.Client;
using Moq;
using NUnit.Framework;

namespace Azure.Identity.Tests
Expand Down
10 changes: 5 additions & 5 deletions sdk/identity/Azure.Identity/tests/CredentialTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ public static TestFileSystemService CreateFileSystemForVisualStudioCode(Identity
{
var sb = new StringBuilder("{");

if (testEnvironment.TestTenantId != default)
if (testEnvironment.IdentityTenantId != default)
{
sb.AppendFormat("\"azure.tenant\": \"{0}\"", testEnvironment.TestTenantId);
sb.AppendFormat("\"azure.tenant\": \"{0}\"", testEnvironment.IdentityTenantId);
}

if (testEnvironment.TestTenantId != default && cloudName != default)
if (testEnvironment.IdentityTenantId != default && cloudName != default)
{
sb.Append(',');
}
Expand Down Expand Up @@ -117,7 +117,7 @@ public static async ValueTask<AuthenticationRecord> GetAuthenticationRecordAsync

var username = testEnvironment.Username;
var password = testEnvironment.Password;
var tenantId = testEnvironment.TestTenantId;
var tenantId = testEnvironment.IdentityTenantId;

var result = await PublicClientApplicationBuilder.Create(clientId)
.WithTenantId(tenantId)
Expand All @@ -138,7 +138,7 @@ public static async Task<string> GetRefreshTokenAsync(IdentityTestEnvironment te
var clientId = "aebc6443-996d-45c2-90f0-388ff96faa56";
var username = testEnvironment.Username;
var password = testEnvironment.Password;
var authorityUri = new Uri(new Uri(testEnvironment.AuthorityHostUrl), testEnvironment.TestTenantId).ToString();
var authorityUri = new Uri(new Uri(testEnvironment.AuthorityHostUrl), testEnvironment.IdentityTenantId).ToString();

var client = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authorityUri)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCredential()

[RecordedTest]
[RunOnlyOnPlatforms(Windows = true, OSX = true, ContainerNames = new[] { "ubuntu_netcore_keyring" })]
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/27263")]
public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()
{
var options = InstrumentClientOptions(new DefaultAzureCredentialOptions
Expand All @@ -73,7 +74,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()
ExcludeVisualStudioCredential = true,
ExcludeAzureCliCredential = true,
ExcludeVisualStudioCodeCredential = false,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
VisualStudioCodeTenantId = TestEnvironment.IdentityTenantId
});

var cloudName = Guid.NewGuid().ToString();
Expand Down Expand Up @@ -102,6 +103,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()

[RecordedTest]
[RunOnlyOnPlatforms(Windows = true, OSX = true, ContainerNames = new[] { "ubuntu_netcore_keyring" })]
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/27263")]
public async Task DefaultAzureCredential_UseVisualStudioCodeCredential_ParallelCalls()
{
var options = InstrumentClientOptions(new DefaultAzureCredentialOptions
Expand All @@ -112,7 +114,7 @@ public async Task DefaultAzureCredential_UseVisualStudioCodeCredential_ParallelC
ExcludeManagedIdentityCredential = true,
ExcludeAzureCliCredential = true,
ExcludeVisualStudioCodeCredential = false,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
VisualStudioCodeTenantId = TestEnvironment.IdentityTenantId
});

var cloudName = Guid.NewGuid().ToString();
Expand Down Expand Up @@ -149,7 +151,7 @@ public async Task DefaultAzureCredential_UseAzureCliCredential()
ExcludeSharedTokenCacheCredential = true,
ExcludeManagedIdentityCredential = true,
ExcludeVisualStudioCodeCredential = false,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
VisualStudioCodeTenantId = TestEnvironment.IdentityTenantId
});

var (expectedToken, expectedExpiresOn, processOutput) = CredentialTestHelpers.CreateTokenForAzureCli();
Expand Down Expand Up @@ -188,7 +190,7 @@ public async Task DefaultAzureCredential_UseAzureCliCredential_ParallelCalls()
ExcludeSharedTokenCacheCredential = true,
ExcludeManagedIdentityCredential = true,
ExcludeVisualStudioCodeCredential = false,
VisualStudioCodeTenantId = TestEnvironment.TestTenantId
VisualStudioCodeTenantId = TestEnvironment.IdentityTenantId
});

var (expectedToken, expectedExpiresOn, processOutput) = CredentialTestHelpers.CreateTokenForAzureCli();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class IdentityTestEnvironment : TestEnvironment
public string UserAssignedVault => GetRecordedOptionalVariable("IDENTITYTEST_IMDSTEST_USERASSIGNEDVAULT");

public string TestPassword => GetOptionalVariable("AZURE_IDENTITY_TEST_PASSWORD") ?? "SANITIZED";
public string TestTenantId => GetRecordedOptionalVariable("TENANT_ID") ?? GetRecordedVariable("AZURE_IDENTITY_TEST_TENANTID");
public string KeyvaultScope => GetRecordedOptionalVariable("AZURE_KEYVAULT_SCOPE") ?? "https://vault.azure.net/.default";

public string ServicePrincipalClientId => GetRecordedVariable("IDENTITY_SP_CLIENT_ID");
Expand All @@ -39,5 +38,6 @@ public class IdentityTestEnvironment : TestEnvironment
public string ServicePrincipalCertificatePfxPath => GetOptionalVariable("IDENTITY_SP_CERT_PFX") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pfx");
public string ServicePrincipalCertificatePemPath => GetOptionalVariable("IDENTITY_SP_CERT_PEM") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pem");
public string ServicePrincipalSniCertificatePath => GetOptionalVariable("IDENTITY_SP_CERT_SNI") ?? Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "cert.pfx");
public string IdentityTestWebName => GetRecordedVariable("IDENTITY_WEBAPP_NAME");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Net;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Pipeline;
using Azure.Core.TestFramework;
using NUnit.Framework;

namespace Azure.Identity.Tests
{
public class ManagedIdentityCredentialWebAppTests : IdentityRecordedTestBase
{
private HttpPipeline _pipeline;
private Uri _testEndpoint;

public ManagedIdentityCredentialWebAppTests(bool isAsync) : base(isAsync)
{
}

[SetUp]
public void Setup() {
var options = new TokenCredentialOptions();
_testEndpoint = new Uri($"https://{TestEnvironment.IdentityTestWebName}.azurewebsites.net/test");
_pipeline = HttpPipelineBuilder.Build(InstrumentClientOptions(options), Array.Empty<HttpPipelinePolicy>(), Array.Empty<HttpPipelinePolicy>(), new ResponseClassifier());
}

[RecordedTest]
[SyncOnly]
// This test leverages the test app found in Azure.Identity\integration\WebApp
// It validates that ManagedIdentityCredential can acquire a token in an actual Azure Web App environment
public async Task CallTestWebApp()
{
Request request = _pipeline.CreateRequest();
request.Uri.Reset(_testEndpoint);
Response response = await _pipeline.SendRequestAsync(request, default);

Assert.AreEqual((int)HttpStatusCode.OK, response.Status);
Assert.AreEqual("Successfully acquired a token from ManagedIdentityCredential", response.Content.ToString(), response.Content.ToString());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Azure.Identity.Tests
{
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/27020")]
public class VisualStudioCodeCredentialLiveTests : IdentityRecordedTestBase
{
private const string ExpectedServiceName = "VS Code Azure";
Expand All @@ -28,7 +29,7 @@ public async Task AuthenticateWithVscCredential()
var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment, cloudName);
using IDisposable fixture = await CredentialTestHelpers.CreateRefreshTokenFixtureAsync(TestEnvironment, Mode, ExpectedServiceName, cloudName);

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.IdentityTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystem, default));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
Expand All @@ -41,7 +42,7 @@ public async Task AuthenticateWithVscCredential_NoSettingsFile()
var fileSystemService = new TestFileSystemService { ReadAllHandler = s => throw new FileNotFoundException() };
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", refreshToken);

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.IdentityTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
Expand All @@ -54,7 +55,7 @@ public async Task AuthenticateWithVscCredential_BrokenSettingsFile()
var fileSystemService = new TestFileSystemService { ReadAllHandler = s => "{a,}" };
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", refreshToken);

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.IdentityTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));
AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
Assert.IsNotNull(token.Token);
Expand All @@ -67,7 +68,7 @@ public async Task AuthenticateWithVscCredential_EmptySettingsFile()
var fileSystemService = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment);
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", refreshToken);

var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.IdentityTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystemService, vscAdapter));

AccessToken token = await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None);
Expand Down Expand Up @@ -97,7 +98,7 @@ public void AuthenticateWithVscCredential_NoVscInstalled()
var cloudName = Guid.NewGuid().ToString();

var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment, cloudName);
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.TestTenantId });
var options = InstrumentClientOptions(new VisualStudioCodeCredentialOptions { TenantId = TestEnvironment.IdentityTenantId });
VisualStudioCodeCredential credential = InstrumentClient(new VisualStudioCodeCredential(options, default, default, fileSystem, default));

Assert.CatchAsync<AuthenticationFailedException>(async () => await credential.GetTokenAsync(new TokenRequestContext(new[] {TestEnvironment.KeyvaultScope}), CancellationToken.None));
Expand All @@ -106,7 +107,7 @@ public void AuthenticateWithVscCredential_NoVscInstalled()
[Test]
public void AuthenticateWithVscCredential_NoRefreshToken()
{
var tenantId = TestEnvironment.TestTenantId;
var tenantId = TestEnvironment.IdentityTenantId;
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", null);
var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment);

Expand All @@ -119,7 +120,7 @@ public void AuthenticateWithVscCredential_NoRefreshToken()
[Test]
public void AuthenticateWithVscCredential_AuthenticationCodeInsteadOfRefreshToken()
{
var tenantId = TestEnvironment.TestTenantId;
var tenantId = TestEnvironment.IdentityTenantId;
var fileSystemService = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment);
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", "{}");

Expand All @@ -132,7 +133,7 @@ public void AuthenticateWithVscCredential_AuthenticationCodeInsteadOfRefreshToke
[Test]
public void AuthenticateWithVscCredential_InvalidRefreshToken()
{
var tenantId = TestEnvironment.TestTenantId;
var tenantId = TestEnvironment.IdentityTenantId;
var fileSystemService = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment);
var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", Guid.NewGuid().ToString());

Expand Down
Loading

0 comments on commit 141bae7

Please sign in to comment.