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

[release/9.0] Automatic authentication for runtime downloads when building internal branches #15187

Open
wants to merge 4 commits into
base: release/9.0
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
<!-- external -->
<ItemGroup>
<PackageVersion Include="Azure.Core" Version="1.41.0" />
<PackageVersion Include="Azure.Identity" Version="1.12.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.19.1" />
<PackageVersion Include="Azure.Identity" Version="1.13.0-beta.1" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.21.2" />
<PackageVersion Include="CommandLineParser" Version="2.5.0" />
<PackageVersion Include="coverlet.collector" Version="1.0.1" />
<PackageVersion Include="FluentAssertions" Version="5.10.3" />
Expand All @@ -84,7 +84,7 @@
<PackageVersion Include="Microsoft.Data.OData" Version="5.8.4" />
<PackageVersion Include="Microsoft.DataServices.Client" Version="$(MicrosoftDataServicesClientVersion)" />
<PackageVersion Include="Microsoft.Diagnostics.Runtime" Version="1.0.5" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.61.3" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.62.0" />
<PackageVersion Include="Microsoft.OpenApi" Version="1.3.2" />
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.3.2" />
<PackageVersion Include="Microsoft.Signed.Wix" Version="$(MicrosoftSignedWixVersion)" />
Expand Down
64 changes: 64 additions & 0 deletions src/Common/Microsoft.Arcade.Common/AuthenticationHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if !DOTNET_BUILD_SOURCE_ONLY
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using Azure.Identity;
using System;

namespace Microsoft.Arcade.Common
{
public static class AuthenticationHelpers
{
public static string GenerateDelegationSas(string uri)
{
// Parse the URI to get the storage account name and container name
var parsedUri = new Uri(uri);
string storageAccountName = parsedUri.Host.Split('.')[0];
if (parsedUri.Segments.Length < 2)
{
throw new Exception("Expected that the uri be in the form https://{storageAccountName}.blob.core.windows.net/{container} or https://{storageAccountName}.azureedge.net/{container}");
}
string containerName = parsedUri.Segments[1].Trim('/');

// Create a BlobServiceClient using the default Azure credentials
var blobServiceClient = new BlobServiceClient(new Uri($"https://{storageAccountName}.blob.core.windows.net"), new DefaultAzureCredential());

var start = DateTimeOffset.UtcNow;
var expiry = DateTimeOffset.UtcNow.AddHours(1);
// Get the user delegation key
var userDelegationKey = blobServiceClient.GetUserDelegationKey(start, expiry);

// Create a BlobSasBuilder
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = containerName,
Resource = "c",
StartsOn = start,
ExpiresOn = expiry
};

// Set permissions
sasBuilder.SetPermissions(BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);

// Generate the SAS token
string sasToken = sasBuilder.ToSasQueryParameters(userDelegationKey, storageAccountName).ToString();

return sasToken;
}
}
}
#else
namespace Microsoft.Arcade.Common
{
public static class AuthenticationHelpers
{
public static string GenerateDelegationSas(string uri)
{
throw NotImplementedException("Not supported in source-only modes");
}
}
}
#endif
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>

<PropertyGroup Condition="'$(DotNetBuildSourceOnly)' == 'true'">
<DefineConstants>$(DefineConstants);DOTNET_BUILD_SOURCE_ONLY</DefineConstants>
</PropertyGroup>

<ItemGroup Condition="'$(DotNetBuildSourceOnly)' != 'true'">
<PackageReference Include="Azure.Storage.Blobs" />
<PackageReference Include="Azure.Identity" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<Compile Include="..\Internal\AssemblyResolver.cs" />

Expand Down
22 changes: 20 additions & 2 deletions src/Microsoft.DotNet.Arcade.Sdk/src/InstallDotNetCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Arcade.Common;
using NuGet.Versioning;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -56,6 +57,23 @@ public override bool Execute()
var jsonContent = File.ReadAllText(GlobalJsonPath);
var bytes = Encoding.UTF8.GetBytes(jsonContent);

string feedKey = "";
if (!string.IsNullOrWhiteSpace(RuntimeSourceFeed) && !string.IsNullOrWhiteSpace(RuntimeSourceFeedKey))
{
// If the key is "az", the user wants automatic authentication.
if (RuntimeSourceFeedKey.Equals("az", StringComparison.OrdinalIgnoreCase))
{
Log.LogMessage(MessageImportance.Low, $"Attempting to generate SAS token for current user.");
string sasToken = AuthenticationHelpers.GenerateDelegationSas(RuntimeSourceFeed);
Log.LogMessage(MessageImportance.High, $"Got sasToken {sasToken}");
feedKey = Convert.ToBase64String(Encoding.ASCII.GetBytes(sasToken));
}
else
{
feedKey = RuntimeSourceFeedKey;
}
}

using (JsonDocument jsonDocument = JsonDocument.Parse(bytes))
{
if (jsonDocument.RootElement.TryGetProperty("tools", out JsonElement toolsElement))
Expand Down Expand Up @@ -137,9 +155,9 @@ public override bool Execute()
}

// The default RuntimeSourceFeed doesn't need a key
if (!string.IsNullOrWhiteSpace(RuntimeSourceFeed) && !string.IsNullOrWhiteSpace(RuntimeSourceFeedKey))
if (!string.IsNullOrWhiteSpace(feedKey))
{
arguments += $" -runtimeSourceFeedKey {RuntimeSourceFeedKey}";
arguments += $" -runtimeSourceFeedKey {feedKey}";
}

Log.LogMessage(MessageImportance.Low, $"Executing: {DotNetInstallScript} {arguments}");
Expand Down
Loading