Skip to content

Commit

Permalink
depend more heavily on Microsoft libraries for auth, split auth types…
Browse files Browse the repository at this point in the history
… to separate packages
  • Loading branch information
TimHess committed Jun 3, 2024
1 parent 939e5ab commit cf5d7ec
Show file tree
Hide file tree
Showing 166 changed files with 1,872 additions and 7,059 deletions.
8 changes: 6 additions & 2 deletions shared-package.props
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,18 @@
</Target>

<ItemGroup
Condition="$(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Management')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Logging')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Discovery')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Security.DataProtection'))">
Condition="$(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) Or
$(MSBuildProjectName.StartsWith('Steeltoe.Discovery')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Logging')) Or $(MSBuildProjectName.StartsWith('Steeltoe.Management')) Or
$(MSBuildProjectName.StartsWith('Steeltoe.Security'))">

<!-- Widen the condition above as we're completing more public API reviews -->
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="$(PublicApiAnalyzersVersion)" PrivateAssets="All" />
</ItemGroup>

<PropertyGroup
Condition="!$(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Management')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Logging')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Discovery')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Security.DataProtection'))">
Condition="!$(MSBuildProjectName.StartsWith('Steeltoe.Configuration')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Management')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Connectors')) And
!$(MSBuildProjectName.StartsWith('Steeltoe.Logging')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Bootstrap')) And !$(MSBuildProjectName.StartsWith('Steeltoe.Discovery')) And
!$(MSBuildProjectName.StartsWith('Steeltoe.Security'))">

<!-- Narrow the condition above as we're completing more public API reviews -->
<NoWarn>$(NoWarn);SA1401;S1168;S2360;S3900;S3956;S4004;S4023</NoWarn>
Expand Down
14 changes: 6 additions & 8 deletions src/Bootstrap/src/AutoConfiguration/BootstrapScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Steeltoe.Common;
using Steeltoe.Common.DynamicTypeAccess;
using Steeltoe.Common.Hosting;
using Steeltoe.Common.Logging;
using Steeltoe.Common.Security;
using Steeltoe.Configuration.CloudFoundry;
using Steeltoe.Configuration.ConfigServer;
using Steeltoe.Configuration.Placeholder;
Expand Down Expand Up @@ -36,7 +36,6 @@
using Steeltoe.Management.Tracing;
using Steeltoe.Management.Wavefront;
using Steeltoe.Management.Wavefront.Exporters;
using Steeltoe.Security.Authentication.CloudFoundry;

namespace Steeltoe.Bootstrap.AutoConfiguration;

Expand Down Expand Up @@ -82,7 +81,7 @@ public void ConfigureSteeltoe()
WireIfLoaded(WirePrometheus, SteeltoeAssemblyNames.ManagementPrometheus);
WireIfLoaded(WireWavefrontMetrics, SteeltoeAssemblyNames.ManagementWavefront);
WireIfLoaded(WireDistributedTracing, SteeltoeAssemblyNames.ManagementTracing);
WireIfLoaded(WireCloudFoundryContainerIdentity, SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
WireIfLoaded(WireContainerIdentity, SteeltoeAssemblyNames.CommonSecurity);
}

private void WireConfigServer()
Expand Down Expand Up @@ -257,13 +256,12 @@ private void WireDistributedTracing()
_logger.LogInformation("Configured distributed tracing");
}

private void WireCloudFoundryContainerIdentity()
private void WireContainerIdentity()
{
_wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddCloudFoundryContainerIdentity());
_wrapper.ConfigureAppConfiguration(configurationBuilder => configurationBuilder.AddContainerIdentityCertificate());
_wrapper.ConfigureServices((host, services) => services.ConfigureCertificateOptions(host.Configuration));

_wrapper.ConfigureServices((host, services) => services.AddCloudFoundryCertificateAuth(host.Configuration));

_logger.LogInformation("Configured Cloud Foundry mTLS security");
_logger.LogInformation("Configured container identity certificate");
}

private bool WireIfLoaded(Action wireAction, string assemblyName)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#nullable enable
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.CommonSecurity = "Steeltoe.Common.Security" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationCloudFoundry = "Steeltoe.Configuration.CloudFoundry" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationConfigServer = "Steeltoe.Configuration.ConfigServer" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ConfigurationPlaceholder = "Steeltoe.Configuration.Placeholder" -> string!
Expand All @@ -12,7 +13,6 @@ const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementEndpo
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementPrometheus = "Steeltoe.Management.Prometheus" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementTracing = "Steeltoe.Management.Tracing" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.ManagementWavefront = "Steeltoe.Management.Wavefront" -> string!
const Steeltoe.Bootstrap.AutoConfiguration.SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry = "Steeltoe.Security.Authentication.CloudFoundry" -> string!
static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder) -> Microsoft.Extensions.Hosting.IHostBuilder!
static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.Extensions.Hosting.IHostBuilder!
static Steeltoe.Bootstrap.AutoConfiguration.HostBuilderExtensions.AddSteeltoe(this Microsoft.Extensions.Hosting.IHostBuilder! builder, System.Collections.Generic.IReadOnlySet<string!>! assemblyNamesToExclude) -> Microsoft.Extensions.Hosting.IHostBuilder!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\Common\src\Common.Hosting\Steeltoe.Common.Hosting.csproj" />
<ProjectReference Include="..\..\..\Common\src\Common\Steeltoe.Common.csproj" />
<ProjectReference Include="..\..\..\Common\src\Common.Hosting\Steeltoe.Common.Hosting.csproj" />
<ProjectReference Include="..\..\..\Common\src\Common.Security\Steeltoe.Common.Security.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Configuration\src\CloudFoundry\Steeltoe.Configuration.CloudFoundry.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Configuration\src\ConfigServer\Steeltoe.Configuration.ConfigServer.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Configuration\src\RandomValue\Steeltoe.Configuration.RandomValue.csproj" PrivateAssets="All" />
Expand All @@ -30,10 +31,7 @@
<ProjectReference Include="..\..\..\Management\src\Task\Steeltoe.Management.Task.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Management\src\Tracing\Steeltoe.Management.Tracing.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Management\src\Wavefront\Steeltoe.Management.Wavefront.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Security\src\Authentication.CloudFoundry\Steeltoe.Security.Authentication.CloudFoundry.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Security\src\Authentication.Mtls\Steeltoe.Security.Authentication.Mtls.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Security\src\DataProtection.Redis\Steeltoe.Security.DataProtection.Redis.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Connectors\src\CloudFoundry\Steeltoe.Connectors.CloudFoundry.csproj" PrivateAssets="All" />
<ProjectReference Include="..\..\..\Logging\src\DynamicLogger\Steeltoe.Logging.DynamicLogger.csproj" PrivateAssets="All" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Steeltoe.Bootstrap.AutoConfiguration;
/// </summary>
public static class SteeltoeAssemblyNames
{
public const string CommonSecurity = "Steeltoe.Common.Security";
public const string ConfigurationCloudFoundry = "Steeltoe.Configuration.CloudFoundry";
public const string ConfigurationConfigServer = "Steeltoe.Configuration.ConfigServer";
public const string ConfigurationRandomValue = "Steeltoe.Configuration.RandomValue";
Expand All @@ -24,7 +25,6 @@ public static class SteeltoeAssemblyNames
public const string ManagementPrometheus = "Steeltoe.Management.Prometheus";
public const string ManagementTracing = "Steeltoe.Management.Tracing";
public const string ManagementWavefront = "Steeltoe.Management.Wavefront";
public const string SecurityAuthenticationCloudFoundry = "Steeltoe.Security.Authentication.CloudFoundry";

internal static readonly IReadOnlySet<string> All = typeof(SteeltoeAssemblyNames).GetFields().Where(field => field.FieldType == typeof(string))
.Select(field => field.GetValue(null)).Cast<string>().ToHashSet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,14 @@ public void Tracing_IsAutowired()
[Fact]
public void CloudFoundryContainerSecurity_IsAutowired()
{
using IHost host = GetHostForOnly(SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
using IHost host = GetHostForOnly(SteeltoeAssemblyNames.CommonSecurity);
var configuration = host.Services.GetRequiredService<IConfiguration>();

configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:CertificateFilePath"].Should().NotBeNull();
configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:PrivateKeyFilePath"].Should().NotBeNull();

host.Services.GetService<IOptions<CertificateOptions>>().Should().NotBeNull();
host.Services.GetService<IOptionsChangeTokenSource<CertificateOptions>>().Should().NotBeNull();
host.Services.GetService<IAuthorizationHandler>().Should().NotBeNull();
}

private static IHost GetHostForOnly(string assemblyNameToInclude)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
<Import Project="..\..\..\..\shared.props" />

<ItemGroup>
<ProjectReference Include="..\..\..\Common\src\Common.Security\Steeltoe.Common.Security.csproj" />
<ProjectReference Include="..\..\..\Configuration\src\ConfigServer\Steeltoe.Configuration.ConfigServer.csproj" />
<ProjectReference Include="..\..\..\Configuration\src\RandomValue\Steeltoe.Configuration.RandomValue.csproj" />
<ProjectReference Include="..\..\..\Connectors\src\Connectors\Steeltoe.Connectors.csproj" />
<ProjectReference Include="..\..\..\Discovery\src\Configuration\Steeltoe.Discovery.Configuration.csproj" />
<ProjectReference Include="..\..\..\Discovery\src\Consul\Steeltoe.Discovery.Consul.csproj" />
<ProjectReference Include="..\..\..\Discovery\src\Eureka\Steeltoe.Discovery.Eureka.csproj" />
<ProjectReference Include="..\..\..\Logging\src\DynamicSerilog\Steeltoe.Logging.DynamicSerilog.csproj" />
<ProjectReference Include="..\..\..\Management\src\Endpoint\Steeltoe.Management.Endpoint.csproj" />
<ProjectReference Include="..\..\..\Management\src\Tracing\Steeltoe.Management.Tracing.csproj" />
<ProjectReference Include="..\..\..\Security\src\Authentication.CloudFoundry\Steeltoe.Security.Authentication.CloudFoundry.csproj" />
<ProjectReference Include="..\..\src\AutoConfiguration\Steeltoe.Bootstrap.AutoConfiguration.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,14 @@ public void Tracing_IsAutowired()
[Fact]
public void CloudFoundryContainerSecurity_IsAutowired()
{
using WebApplication host = GetWebApplicationForOnly(SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
using WebApplication host = GetWebApplicationForOnly(SteeltoeAssemblyNames.CommonSecurity);
var configuration = host.Services.GetRequiredService<IConfiguration>();

configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:CertificateFilePath"].Should().NotBeNull();
configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:PrivateKeyFilePath"].Should().NotBeNull();

host.Services.GetService<IOptions<CertificateOptions>>().Should().NotBeNull();
host.Services.GetService<IOptionsChangeTokenSource<CertificateOptions>>().Should().NotBeNull();
host.Services.GetService<IAuthorizationHandler>().Should().NotBeNull();
}

private static WebApplication GetWebApplicationForOnly(string assemblyNameToInclude)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,13 @@ public void Tracing_IsAutowired()
[Fact]
public void CloudFoundryContainerSecurity_IsAutowired()
{
using IWebHost host = GetWebHostForOnly(SteeltoeAssemblyNames.SecurityAuthenticationCloudFoundry);
using IWebHost host = GetWebHostForOnly(SteeltoeAssemblyNames.CommonSecurity);
var configuration = host.Services.GetRequiredService<IConfiguration>();

configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:CertificateFilePath"].Should().NotBeNull();
configuration[$"{CertificateOptions.ConfigurationKeyPrefix}:ContainerIdentity:PrivateKeyFilePath"].Should().NotBeNull();

host.Services.GetService<IOptionsMonitor<CertificateOptions>>()?.Get("ContainerIdentity").Certificate.Should().NotBeNull();
host.Services.GetService<IAuthorizationHandler>().Should().NotBeNull();
}

private static IWebHost GetWebHostForOnly(string assemblyNameToInclude)
Expand Down
2 changes: 1 addition & 1 deletion src/Common/src/Abstractions/Options/CertificateOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ public sealed class CertificateOptions

public X509Certificate2? Certificate { get; set; }

public List<X509Certificate2> IssuerChain { get; set; } = [];
public IList<X509Certificate2> IssuerChain { get; internal set; } = [];
}
1 change: 1 addition & 0 deletions src/Common/src/Abstractions/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Steeltoe.Bootstrap.AutoConfiguration")]
[assembly: InternalsVisibleTo("Steeltoe.Common.Security")]
[assembly: InternalsVisibleTo("Steeltoe.Connectors")]
[assembly: InternalsVisibleTo("Steeltoe.Connectors.EntityFrameworkCore")]
[assembly: InternalsVisibleTo("Steeltoe.Logging.DynamicSerilog")]
109 changes: 109 additions & 0 deletions src/Common/src/Common.Security/CertificateConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using Microsoft.Extensions.Configuration;
using Steeltoe.Common.Options;

namespace Steeltoe.Common.Security;

public static class CertificateConfigurationExtensions
{
/// <summary>
/// Adds file path information for a certificate and (optional) private key to configuration, for use with <see cref="CertificateOptions" />.
/// </summary>
/// <param name="builder">
/// Your <see cref="IConfigurationBuilder" />.
/// </param>
/// <param name="certificateName">
/// Name of the certificate.
/// </param>
/// <param name="certificateFilePath">
/// The path on disk to locate a valid certificate file.
/// </param>
/// <param name="privateKeyFilePath">
/// The path on disk to locate a valid pem-encoded RSA key.
/// </param>
public static IConfigurationBuilder AddCertificate(this IConfigurationBuilder builder, string certificateName, string certificateFilePath,
string? privateKeyFilePath = null)
{
ArgumentGuard.NotNull(builder);
ArgumentGuard.NotNullOrEmpty(certificateFilePath);

string keyPrefix = string.IsNullOrEmpty(certificateName)
? $"{CertificateOptions.ConfigurationKeyPrefix}{ConfigurationPath.KeyDelimiter}"
: $"{CertificateOptions.ConfigurationKeyPrefix}{ConfigurationPath.KeyDelimiter}{certificateName}{ConfigurationPath.KeyDelimiter}";

var keys = new Dictionary<string, string?>
{
{ $"{keyPrefix}CertificateFilePath", certificateFilePath }
};

if (!string.IsNullOrEmpty(privateKeyFilePath))
{
keys[$"{keyPrefix}PrivateKeyFilePath"] = privateKeyFilePath;
}

builder.AddInMemoryCollection(keys);
return builder;
}

/// <summary>
/// Adds PEM files representing application identity to application configuration. When running outside of Cloud Foundry based platforms,
/// will create certificates resembling those found on the platform.
/// </summary>
/// <param name="builder">
/// Your <see cref="IConfigurationBuilder" />.
/// </param>
/// <remarks>
/// Outside of Cloud Foundry, CA and Intermediate certificates will be created a directory above the current project so that they can
/// be shared between different projects operating in the same solution context.
/// </remarks>
public static IConfigurationBuilder AddContainerIdentityCertificate(this IConfigurationBuilder builder)
{
return builder.AddContainerIdentityCertificate(null, null);
}

/// <summary>
/// Adds PEM files representing application identity to application configuration. When running outside of Cloud Foundry based platforms,
/// will create certificates resembling those found on the platform.
/// </summary>
/// <param name="builder">
/// Your <see cref="IConfigurationBuilder" />.
/// </param>
/// <param name="organizationId">
/// (Optional) A GUID representing an organization, for use with Cloud Foundry certificate-based authorization
/// policy.
/// </param>
/// <param name="spaceId">
/// (Optional) A GUID representing a space, for use with Cloud Foundry certificate-based authorization policy.
/// </param>
/// <remarks>
/// Outside of Cloud Foundry, CA and Intermediate certificates will be created a directory above the current project so that they can
/// be shared between different projects operating in the same solution context.
/// </remarks>
public static IConfigurationBuilder AddContainerIdentityCertificate(this IConfigurationBuilder builder, Guid? organizationId, Guid? spaceId)
{
if (!Platform.IsCloudFoundry)
{
organizationId ??= Guid.NewGuid();
spaceId ??= Guid.NewGuid();

var task = new LocalCertificateWriter();
task.Write((Guid)organizationId, (Guid)spaceId);

Environment.SetEnvironmentVariable("CF_SYSTEM_CERT_PATH", Path.Combine(Directory.GetParent(LocalCertificateWriter.ApplicationBasePath)!.ToString(), "GeneratedCertificates"));

Environment.SetEnvironmentVariable("CF_INSTANCE_CERT",
Path.Combine(LocalCertificateWriter.ApplicationBasePath, "GeneratedCertificates", "SteeltoeInstanceCert.pem"));

Environment.SetEnvironmentVariable("CF_INSTANCE_KEY",
Path.Combine(LocalCertificateWriter.ApplicationBasePath, "GeneratedCertificates", "SteeltoeInstanceKey.pem"));
}

string? certificateFile = Environment.GetEnvironmentVariable("CF_INSTANCE_CERT");
string? keyFile = Environment.GetEnvironmentVariable("CF_INSTANCE_KEY");

return certificateFile == null || keyFile == null ? builder : builder.AddCertificate("ContainerIdentity", certificateFile, keyFile);
}
}
Loading

0 comments on commit cf5d7ec

Please sign in to comment.