首页 > 解决方案 > 使用 docker 启动 Identity Server 中的 X509Store 异常

问题描述

我正在尝试将我们的 IdentityServer4 项目转换为 docker。我添加了正确的 dockerfile,它可以构建。它是 .net core 3.1 但我得到一个启动错误

PlatformNotSupportedException:Unix LocalMachine X509Store 仅限于 Root 和 CertificateAuthority 存储。

我在另一篇文章IdentityServer4: How to load Signing Credential from Cert Store when in Docker中查看了这个确切的错误, 唯一的答案对我不起作用。这是我的 Dockerfile

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["src/Sentinel.Web/is4.Web.csproj", "src/is4.Web/"]
RUN dotnet restore "src/is4.Web/is4.Web.csproj"
COPY . .
WORKDIR "/src/src/is4.Web"
RUN dotnet build "is4.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "is4.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY "IdentityServerCN.pfx" .
COPY "IdentityServerDataKeysCN.pfx" .
ENTRYPOINT ["dotnet", "Sentinel.Web.dll"]

我什至尝试将其更改为使用开发人员证书,但仍然没有运气

   .AddDeveloperSigningCredential(); // debug only

启动类:

public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("IdentityServer")));

            services
                .AddDbContext<DataKeysContext>(o =>
            {
                o.UseSqlServer(Configuration.GetConnectionString("IdentityServer"));
                o.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
                if (Configuration.GetValue<bool?>("EnableSensitiveDataLogging") ?? false)
                {
                    o.EnableSensitiveDataLogging(); // debug only
                }
            })
            .AddDataProtection()
            .PersistKeysToDbContext<DataKeysContext>()
            .ProtectKeysWithCertificate(GetCertficateFromKeystore(Configuration.GetValue<string>("Certificates:DataProtection")))
            .SetDefaultKeyLifetime(TimeSpan.FromDays(7))
            .SetApplicationName("Sentinel.Web");

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            // If we're in dev allow showing PII for debugging identity server cert issues
            IdentityModelEventSource.ShowPII = Configuration.GetValue<bool?>("ShowIdentityModelPII") ?? false;

            // configures IIS out-of-proc settings (see https://github.com/aspnet/AspNetCore/issues/14882)
            services.Configure<IISOptions>(iis =>
            {
                iis.AuthenticationDisplayName = "Windows";
                iis.AutomaticAuthentication = false;
            });

            // configures IIS in-proc settings
            services.Configure<IISServerOptions>(iis =>
            {
                iis.AuthenticationDisplayName = "Employee Account";
                iis.AutomaticAuthentication = false;
            });

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
            })
                .AddDefaultEndpoints()
                //.AddSigningCredential(GetCertficateFromKeystore(Configuration.GetValue<string>("Certificates:IdentityServer")))
                //.AddSigningCredential(new X509Certificate2("IdentityServerCN.pfx", "pass1234") )
                //.AddInMemoryPersistedGrants()
                .AddOperationalStore(options =>
                {
                    options.DefaultSchema = "dbo";
                    options.ConfigureDbContext = x =>
                        x.UseSqlServer(Configuration.GetConnectionString("IdentityServer"));
                })
                //.AddTestUsers(TestUsers.Users)
                .AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources"))
                .AddInMemoryApiResources(Configuration.GetSection("ApiResources"))
                .AddInMemoryClients(Configuration.GetSection("Clients"))
                .AddAspNetIdentity<ApplicationUser>()
                .AddDeveloperSigningCredential(); // debug only
                services.AddAuthentication()
                    .AddGoogle("Google", options =>
                    {
                        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                        options.ClientId = "xxx.apps.googleusercontent.com";
                        options.ClientSecret = "xxxxxxxxxxxx";
                    });
            // If we did a custom grant store (i.e. instead of using EF we could use dapper)
            //services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
            services.AddTransient<ActiveDirectoryService>();
        }

        public void Configure(IApplicationBuilder app)
        {
            if (Configuration.GetValue<bool?>("ShowDeveloperExceptionPage") ?? false)
            {
                app.UseDeveloperExceptionPage();
                //app.UseDatabaseErrorPage();
            }

            app.UseStaticFiles();

            // CORS handled by identity server settings

            app.UseRouting();
            app.UseIdentityServer();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            });
        }

        private X509Certificate2 GetCertficateFromFileSystem(string keyFilePath, string keyFilePassword)
        {
            // using file
            return new X509Certificate2(keyFilePath, keyFilePassword, X509KeyStorageFlags.MachineKeySet);
        }

        private X509Certificate2 GetCertficateFromKeystore(string keyIssuer)
        {
            // using keystore
            var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadOnly);
            var certificates = store.Certificates.Find(X509FindType.FindByIssuerName, keyIssuer, true);
            if (certificates.Count == 0)
            {
                throw new InvalidOperationException("Could not locate certificate in keystore");
            }
            return certificates[0];
        }
    }

标签: identityserver4asp.net-core-3.1

解决方案


推荐阅读