J K*_*ing 5 azure docker azure-devops identityserver4 azure-pipelines
我正在尝试使用.Net Core Clean Architecture App Template并让它在容器中运行并通过 azure CI/CD 管道进行部署
我在带有端口 5001 的 linux 容器中本地运行了模板的容器化版本,并且一切正常。
我的 azure 管道构建过程正常工作,它在我的容器注册表中创建图像。
问题是,一旦我部署/发布到容器的 Web 应用程序,该应用程序就会失败并引发以下错误:
应用程序启动异常 System.InvalidOperationException:在 Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromStoreCert(String subject, String storeName, StoreLocation storeLocation, DateTimeOffset currentTime)
我做了什么:
按照MS 的这些文档,我创建了一个本地开发证书:
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p { password here }
dotnet dev-certs https --trust
然后我将其作为私有 .pfx 证书导入到 Web 应用程序中。
我添加了一个应用程序设置WEBSITE_LOAD_CERTIFICATES与证书的“拇指”值
我在 Identity Server appSettings.json 部分中使用了导入证书的“主机名” (在我的情况下为主机名 = localhost)
当 Web 应用程序加载时,它显示 :( 应用程序错误和 docker 日志给了我上面引用的错误。
我很确定这与身份服务器设置和 appSettings.json 值有关:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=localhost"
}
}
Run Code Online (Sandbox Code Playgroud)
有人可以帮我弄清楚如何解决这个错误吗?
这肯定与身份服务器有关。我尝试手动将证书设置为 appSettings.json 中的文件,如下所示:
"IdentityServer": {
"Key": {
"Type": "File",
"FilePath": "aspnetapp.pfx",
"Password": "Your_password123"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我收到这个错误:
正在“/app/aspnetapp.pfx”中加载带有存储标志“”的证书文件。应用程序启动异常 System.InvalidOperationException: 加载证书时出错。找不到文件“/app/aspnetapp.pfx”。Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromFile
我将其添加到 dockerfile 中:
WORKDIR /app
COPY ["/aspnetapp.pfx", "/app"]
RUN find /app
Run Code Online (Sandbox Code Playgroud)
如下图所示,文件显示在应用程序的构建目录中:
我还确保 .gitignore 或 .dockerignore 文件不会忽略 aspnetapp.pfx。
我不知道为什么它不会加载这个文件。看起来它就在它应该存在的地方。
所以我使用了 tnc1977 建议并将其作为我的身份密钥设置
"IdentityServer": {
"Key": {
"Type": "File",
"FilePath": "/var/ssl/private/<thumb_value>.p12",
"Password": "Your_password123"
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这又出现了另一个错误:
加载证书时出错。密码不正确或进程没有权限将密钥存储在 Keyset 'EphemeralKeySet' Interop+Crypto+OpenSslCryptographicException: error:23076071:PKCS12routines:PKCS12_parse:mac verify failure
我购买了 Azure 应用证书并添加了一个设置了 TSL 的自定义域,但出现了相同的错误
我现在知道我不能使用证书存储 CurrentUser/My 因为那是用于 Windows 的。Linux 容器必须在代码中手动加载证书。
我正在使用已添加到 azure web 应用程序的 aa 应用程序证书的指纹。它是一个私有的 azure 应用程序证书,并且已经针对自定义域进行了验证。
我将此代码添加到我的 statup.cs configureservices(我知道对这些值进行硬编码不是最佳实践,但我只想看看它是否可以加载证书,我将切换到 env 变量和密钥库):
// linux file path for private keys
var cryptBytes = File.ReadAllBytes("/var/ssl/private/<thumbprint>.p12");
var cert = new X509Certificate2(cryptBytes, "");
services.AddIdentityServer().AddSigningCredential(cert);
Run Code Online (Sandbox Code Playgroud)
我输入了一个空白密码,因为我认为这是您应该做的。我现在在我的 docker 日志中收到以下错误,这让我相信证书已加载,现在该错误与我使用这两个services.AddIdentityServer().AddSigningCredential(cert); 相关。在 startup.cs configureservices和app.UseIdentityServer()在 startup.cs configure:
未处理的异常。System.InvalidOperationException:装饰器已注册类型:IAuthenticationService。
我不确定如何将证书添加到 app.UseIdentityServer(); 线。
经过更多的挖掘,不幸的是@tnc1997 答案将不起作用。在 asp.net core 3 中,我的satrtup.cs 中对app.UseIdentityServer 的调用在内部尊重一种将在 appsetting(environment).json 文件中查找身份服务器 Key、File、Pass 等的方法。
结果,即使我在 tnc1997 所示的代码中加载了证书,应用程序仍然会在设置文件中查找。因此,设置文件必须包含 IS4 密钥的正确详细信息。
此外,azure 不会将证书放在 linux 容器中典型的受信任位置。从我读过的内容来看,似乎唯一的方法是挂载一个卷(在这种情况下是一个 azure 存储文件共享)并使用上传到该文件共享的证书。
我可以确认这在本地有效,但现在我在运行容器时仍然遇到问题,前端加载并且 web api 项目似乎没有启动。我将发布另一个问题来解决该问题。
我认为问题可能是您尝试使用 Windows 证书存储在 Linux 容器中加载证书。
此处的文档很好地概述了如何在 Linux 托管应用程序中使用应用程序服务私有证书:
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
var cert = new X509Certificate2(bytes);
Run Code Online (Sandbox Code Playgroud)
以下是我用来生成签名凭据的步骤:
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout example.com.key -out example.com.crt -subj "/CN=example.com" -days 365替换example.com。openssl pkcs12 -export -out example.com.pfx -inkey example.com.key -in example.com.crt替换example.com。下面的代码示例显示了一个完整的Startup.cs配置,可用于启动和运行 IdentityServer 应用程序:
namespace IdentityServer
{
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
void ConfigureDbContext(DbContextOptionsBuilder builder)
{
builder.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"));
}
var builder = services.AddIdentityServer()
.AddConfigurationStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
.AddOperationalStore(options => { options.ConfigureDbContext = ConfigureDbContext; });
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
try
{
var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
var certificate = new X509Certificate2(bytes);
builder.AddSigningCredential(certificate);
}
catch (FileNotFoundException)
{
throw new Exception($"The certificate with the thumbprint \"{Configuration["WEBSITE_LOAD_CERTIFICATES"].Substring(0, 8)}...\" could not be found.");
}
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseIdentityServer();
}
}
}
Run Code Online (Sandbox Code Playgroud)
下面的代码示例显示了一个完整的DependencyInjection.cs配置,可用于启动和运行 Clean Architecture 应用程序:
namespace CleanArchitecture.Infrastructure
{
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
void ConfigureDbContext(DbContextOptionsBuilder builder)
{
if (configuration.GetValue<bool>("UseInMemoryDatabase"))
{
builder.UseInMemoryDatabase("CleanArchitectureDb");
}
else
{
builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
}
}
services.AddDbContext<ApplicationDbContext>(ConfigureDbContext);
services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
services.AddScoped<IDomainEventService, DomainEventService>();
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
var builder = services.AddIdentityServer()
.AddConfigurationStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
.AddOperationalStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
.AddAspNetIdentity<ApplicationUser>();
var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
var certificate = new X509Certificate2(bytes);
builder.AddSigningCredential(certificate);
services.AddTransient<IDateTime, DateTimeService>();
services.AddTransient<IIdentityService, IdentityService>();
services.AddTransient<ICsvFileBuilder, CsvFileBuilder>();
services.AddAuthentication()
.AddIdentityServerJwt();
return services;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1116 次 |
| 最近记录: |