Skip to content
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
9 changes: 4 additions & 5 deletions eng/pipelines/steps/compound-build-csproj-step.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
# See the LICENSE file in the project root for more information. #
#################################################################################

# Generic build step for csproj-based Extension packages (Logging, Abstractions, Azure). Each
# project uses a build.proj target that runs Build only and produces assemblies within
# $(BUILD_OUTPUT). Downstream ESRP DLL signing must locate the assemblies within $(BUILD_OUTPUT)
# for all target frameworks that the csproj targets. NuGet packaging is done separately via
# compound-pack-csproj-step.yml after DLL signing.
# Generic build step for csproj-based packages. Each project uses a build.proj target that runs
# Build only and produces assemblies within $(BUILD_OUTPUT). Downstream ESRP DLL signing must
# locate the assemblies within $(BUILD_OUTPUT) for all target frameworks that the csproj targets.
# NuGet packaging is done separately via compound-pack-csproj-step.yml after DLL signing.

parameters:
# The MSBuild build target in build.proj (e.g. BuildLogging, BuildAbstractions,
Expand Down
17 changes: 17 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
<!-- Respect environment variable for the .NET install directory if set; otherwise, use the current default location -->
<BuildSimulator Condition="'$(BuildSimulator)' != 'true'">false</BuildSimulator>
</PropertyGroup>

<!-- Add user-supplied define constants. -->
<PropertyGroup Condition="'$(UserDefinedConstants)' != ''">
<DefineConstants>$(DefineConstants);$(UserDefinedConstants)</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(BuildSimulator)' == 'true'">
<DefineConstants>$(DefineConstants);ENCLAVE_SIMULATOR</DefineConstants>
</PropertyGroup>
Expand Down Expand Up @@ -109,6 +115,17 @@
<!-- <WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors> -->
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>

<!-- We also define a constant used for conditional compilation. -->
<DefineConstants>$(DefineConstants);STRONG_NAME_SIGNING</DefineConstants>
</PropertyGroup>

<!-- Packaging for source link-->
<PropertyGroup>
<DebugType>portable</DebugType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<InternalsVisibleTo Include="$(AssemblyName).Test" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<InternalsVisibleTo Include="$(AssemblyName).Test" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<InternalsVisibleTo Include="$(AssemblyName).Test" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,9 @@
</PropertyGroup>

<!-- Trim/AOT Support ================================================ -->
<PropertyGroup>
<IsTrimmable Condition="'$(TargetFramework)' != 'net462'">true</IsTrimmable>
<IsAotCompatible Condition="'$(TargetFramework)' != 'net462'">true</IsAotCompatible>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
<PropertyGroup Condition="'$(TargetFramework)' != 'net462'">
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<!-- References ====================================================== -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
<Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>

<!-- CLS Compliance attribute -->
<ItemGroup>
<AssemblyAttribute Include="System.CLSCompliantAttribute">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<InternalsVisibleTo Include="UnitTests" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@
<Configurations>Debug;Release</Configurations>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>

<!-- CLS Compliance -->
<ItemGroup>
<AssemblyAttribute Include="System.CLSCompliantAttribute">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>UnitTests</_Parameter1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@
</AssemblyAttribute>
</ItemGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>

<!-- References ====================================================== -->
<!-- Reference to Abstractions -->
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,7 @@
</AssemblyAttribute>
</ItemGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>
<!-- Otherwise, we're not signing, so we are permitted to expose our internals to tests. -->
<!-- When we're not signing, we are permitted to expose our internals to tests. -->
<ItemGroup Condition="'$(SigningKeyPath)' == ''">
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>UnitTests</_Parameter1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ internal sealed class SqlAuthenticationProviderManager
private const string ActiveDirectoryDefault = "active directory default";
private const string ActiveDirectoryWorkloadIdentity = "active directory workload identity";

// The name of our Azure extension assembly.
private const string azureAssemblyName = "Microsoft.Data.SqlClient.Extensions.Azure";

// The public key token of our Azure extension assembly, used to avoid loading imposter
// assemblies.
private static readonly byte[] azurePublicKeyToken = [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ];

static SqlAuthenticationProviderManager()
{
SqlAuthenticationProviderConfigurationSection? configurationSection = null;
Expand All @@ -48,30 +55,77 @@ static SqlAuthenticationProviderManager()

Instance = new SqlAuthenticationProviderManager(configurationSection);

// If our Azure extensions package is present, use its
// authentication provider as our default.
const string assemblyName = "Microsoft.Data.SqlClient.Extensions.Azure";

// If our Azure extensions package is present, use its authentication provider as our
// default.
try
{
// Try to load our Azure extension.
var assembly = Assembly.Load(assemblyName);
#if STRONG_NAME_SIGNING

// When strong-name signing is enabled, build a fully-qualified AssemblyName
// that includes the expected public key token.

SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Attempting to load Azure extension assembly={azureAssemblyName} with " +
"expected public key token=" +
BitConverter.ToString(azurePublicKeyToken).Replace("-", ""));

var qualifiedName = new AssemblyName(azureAssemblyName);
qualifiedName.SetPublicKeyToken(azurePublicKeyToken);

// The .NET Framework runtime will enforce the token during binding, causing Load()
// to throw. This prevents an untrusted assembly from being loaded and having its
// module initializers run. This will throw if the public key token doesn't match.
//
// The .NET runtime ignores the public key token and will happily load any assembly
// with the same simple name.
//
var assembly = Assembly.Load(qualifiedName);

#if NET
// For the .NET runtime, we will check the public key token ourselves.
//
// Note that a null assembly is handled below.
if (assembly is not null)
{
byte[]? actualToken = assembly.GetName().GetPublicKeyToken();

if (actualToken is null || !actualToken.AsSpan().SequenceEqual(azurePublicKeyToken))
{
SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Azure extension assembly={assembly.GetName()} has an " +
"unexpected public key token; " +
"no default Active Directory provider installed");
return;
}
}
#endif

#else

SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Attempting to load Azure extension assembly={azureAssemblyName} without " +
"strong name verification; ensure this assembly is from a trusted source");

var assembly = Assembly.Load(azureAssemblyName);

#endif

if (assembly is null)
{
SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Azure extension assembly={assemblyName} not found; " +
$": Azure extension assembly={azureAssemblyName} not found; " +
"no default Active Directory provider installed");
return;
}

// TODO(https://sqlclientdrivers.visualstudio.com/ADO.Net/_workitems/edit/39845):
// Verify the assembly is signed by us?

SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Azure extension assembly={assemblyName} found; " +
$": Azure extension assembly={assembly.GetName()} found; " +
"attempting to set as default provider for all Active " +
"Directory authentication methods");

Expand Down Expand Up @@ -147,7 +201,7 @@ ex is TargetInvocationException ||
{
SqlClientEventSource.Log.TryTraceEvent(
nameof(SqlAuthenticationProviderManager) +
$": Azure extension assembly={assemblyName} not found or " +
$": Azure extension assembly={azureAssemblyName} not found or " +
"not usable; no default provider installed; " +
$"{ex.GetType().Name}: {ex.Message}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,6 @@ Microsoft.SqlServer.Server.Format</Description>
<None Include="PackageReadme.md" Pack="true" PackagePath="README.md" />
</ItemGroup>

<!-- Strong name signing ============================================= -->

<!-- When a signing key is specified, we will perform strong name assembly signing. -->
<PropertyGroup Condition="'$(SigningKeyPath)' != ''">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>$(SigningKeyPath)</AssemblyOriginatorKeyFile>
</PropertyGroup>

<ItemGroup>
<None Remove=".AssemblyAttributes" />
</ItemGroup>
Expand Down
Loading