Skip to content

Commit

Permalink
Automate Managed Identity manual tests - Azure Functions (Azure#38393)
Browse files Browse the repository at this point in the history
  • Loading branch information
christothes authored and jsquire committed Sep 6, 2023
1 parent a8b0f64 commit f657914
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 41 deletions.
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "net",
"TagPrefix": "net/identity/Azure.Identity",
"Tag": "net/identity/Azure.Identity_7f050cb3f3"
"Tag": "net/identity/Azure.Identity_f0e02fe424"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Azure.Identity.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Core;

namespace Integration.Identity.Common;

public static class ManagedIdentityTests
{
public static void AuthToStorage()
{
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);
client1.GetBlobContainers().ToList();
client2.GetBlobContainers().ToList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Integration.Identity.Common;

namespace Integration.Identity.Func
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");

try
{
ManagedIdentityTests.AuthToStorage();
return new OkObjectResult("Successfully acquired a token from ManagedIdentityCredential");
}
catch (Exception ex)
{
return new BadRequestObjectResult(ex.ToString());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Integration.Identity.Common\Integration.Identity.Common.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"appInsights1": {
"type": "appInsights"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"appInsights1": {
"type": "appInsights.sdk"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": "2.0",
"logging": {
"fileLoggingMode": "always",
"logLevel": {
"Function.MyFunction": "Information",
"default": "None"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Azure.Identity;
using Azure.Storage.Blobs;
using Microsoft.AspNetCore.Mvc;
using Integration.Identity.Common;

namespace WebApp.Controllers
{
Expand All @@ -16,18 +17,9 @@ 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();
ManagedIdentityTests.AuthToStorage();
return Ok("Successfully acquired a token from ManagedIdentityCredential");
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<PackageReference Include="Azure.Storage.Blobs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Azure.Identity.csproj" />
<ProjectReference Include="..\Integration.Identity.Common\Integration.Identity.Common.csproj" />
</ItemGroup>

</Project>
14 changes: 0 additions & 14 deletions sdk/identity/Azure.Identity/integration/nuget.config

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ public class IdentityTestEnvironment : TestEnvironment
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");
public string IdentityTestAzFuncName => GetRecordedVariable("IDENTITY_FUNCTION_NAME");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,44 @@

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

public ManagedIdentityCredentialWebAppTests(bool isAsync) : base(isAsync)
public ManagedIdentityCredentialIntegrationTests(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()
public async Task CallIntegrationTestWebApp()
{
var testEndpoint = new Uri($"https://{TestEnvironment.IdentityTestWebName}.azurewebsites.net/test");
Request request = _pipeline.CreateRequest();
request.Uri.Reset(_testEndpoint);
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());
}

[RecordedTest]
[SyncOnly]
// This test leverages the test app found in Azure.Identity\integration\Integration.Identity.Func
// It validates that ManagedIdentityCredential can acquire a token in an actual Azure Web App environment
public async Task CallIntegrationTestAzFunction()
{
var testEndpoint = new Uri($"https://{TestEnvironment.IdentityTestAzFuncName}.azurewebsites.net/api/function1");
Request request = _pipeline.CreateRequest();
request.Uri.Reset(testEndpoint);
Response response = await _pipeline.SendRequestAsync(request, default);

Assert.AreEqual((int)HttpStatusCode.OK, response.Status);
Expand Down
16 changes: 13 additions & 3 deletions sdk/identity/test-resources-post.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ if ($null -ne $Env:AGENT_WORKFOLDER) {
}
az login --service-principal -u $DeploymentOutputs['IDENTITY_CLIENT_ID'] -p $DeploymentOutputs['IDENTITY_CLIENT_SECRET'] --tenant $DeploymentOutputs['IDENTITY_TENANT_ID']
az account set --subscription $DeploymentOutputs['IDENTITY_SUBSCRIPTION_ID']

# Deploy the webapp
dotnet publish "$webappRoot/WebApp/Integration.Identity.WebApp.csproj" -o "$workingFolder/Pub" /p:EnableSourceLink=false
Compress-Archive -Path "$workingFolder/Pub/*" -DestinationPath "$workingFolder/Pub/package.zip" -Force
az webapp deploy --resource-group $DeploymentOutputs['IDENTITY_RESOURCE_GROUP'] --name $DeploymentOutputs['IDENTITY_WEBAPP_NAME'] --src-path "$workingFolder/Pub/package.zip"

# clean up
Remove-Item -Force -Recurse "$workingFolder/Pub"
if ($null -eq $Env:AGENT_WORKFOLDER) {
Remove-Item -Force -Recurse "$webappRoot/%AGENT_WORKFOLDER%"
}

# Deploy the function app
dotnet publish "$webappRoot/Integration.Identity.Func/Integration.Identity.Func.csproj" -o "$workingFolder/Pub" /p:EnableSourceLink=false
Compress-Archive -Path "$workingFolder/Pub/*" -DestinationPath "$workingFolder/Pub/package.zip" -Force
az functionapp deployment source config-zip -g $DeploymentOutputs['IDENTITY_RESOURCE_GROUP'] -n $DeploymentOutputs['IDENTITY_FUNCTION_NAME'] --src "$workingFolder/Pub/package.zip"

# clean up
Remove-Item -Force -Recurse "$workingFolder/Pub"

az logout
Loading

0 comments on commit f657914

Please sign in to comment.