Skip to content
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

First iteration of a simple ManagedIdentity integration test #33017

Merged
merged 5 commits into from
Dec 13, 2022
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
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