运行 azure kubernetes 服务中的 aspnet core 3.1 MVC 应用程序,在 azure 应用程序网关后面使用 oidc 身份验证并使用 Identity Server 4

Run aspnet core 3.1 MVC application in azure kubernetes service with oidc authentication behind azure application gateway and with Identity Server 4

我是 运行 来自 azure 的 kubernetes 服务中的 aspnet core 3.1 MVC 应用程序。 AKS 在应用程序网关后面。 Azure 应用程序网关入口控制器 pod 在 AKS 中是 运行,我的部署、服务和入口配置如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  name: imagename
  namespace: namespacename
spec:
  replicas: 1
  selector:
    matchLabels:
      app: imagename
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: imagename
    spec:
      containers:
      - name: imagename
        image: acrname.azurecr.io/imagename:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          name: http
        readinessProbe:
          httpGet:
            path: /probes  
            port: 80
          periodSeconds: 30
          timeoutSeconds: 3
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: "dev"
        resources:
          requests:
            cpu: 150m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 500Mi
status: {}
---
apiVersion: v1
kind: Service
metadata:
  name: imagename
  namespace: namespacename
spec:
  selector:
    app: imagename
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: imagename
  namespace: namespacename
  annotations:
    kubernetes.io/ingress.class: azure/application-gateway
    appgw.ingress.kubernetes.io/backend-path-prefix: "/"
    appgw.ingress.kubernetes.io/appgw-ssl-certificate: certificatename
    appgw.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: exampledomain.com.br
    http:
      paths:
      - path: /pathapp/*
        backend:
          serviceName: imagename
          servicePort: 80

身份服务器 pod 已经在 AKS 中 运行,身份验证过程适用于 Bearer 方案。

对于 Cookies 方案,应用程序能够通过身份服务器使用 azure AD 进行身份验证,但在应用程序 pod 的 /signin-oidc 端点的重定向上,我遇到了 404 错误。该应用程序的 pod 日志显示:

An unhandled exception has occurred while executing the request. System.Exception: An error was encountered while handling the remote login. ---> System.Exception: Correlation failed. --- End of inner exception stack trace ---

Configure ASP.NET Core to work with proxy servers and load balancers 中的说明已在应用程序中实现。

在应用程序中重定向到 /signin-oidc 的 pod 的完整可以在下图中看到:

Correlation failed

这是我的启动 class:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuracao = configuration;
        }

        public IConfiguration Configuracao { get; }

        public void ConfigureServices(IServiceCollection servicos)
        {
            servicos.AddApplicationInsightsTelemetry(Configuracao.GetValue<string>("ApplicationInsights:InstrumentationKey"));
            //servicos.AddAICustomizado(Configuracao);

            servicos.AddControllersWithViews();
            servicos.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                    ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
            });
            servicos.AddRazorPages().AddRazorRuntimeCompilation();
            //servicos.AddMvcCustomizado();

            servicos.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
                            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
                            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
                            {
                                options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                                options.ResponseType = OpenIdConnectResponseType.Code;
                                options.Authority = Configuracao.GetValue<string>("Autenticacao:IdentityServer:UrlBase");
                                options.ClientId = "clientimplicit";
                                options.ResponseType = "id_token token";
                                options.SaveTokens = true;
                                options.Scope.Clear();
                                options.Scope.Add("openid");
                                options.Scope.Add("Scope2");
                                options.Scope.Add("Scope3");
                                options.UseTokenLifetime = true;
                                options.RequireHttpsMetadata = false;
                                options.Events.OnRedirectToIdentityProvider = async n =>
                                {
                                    n.ProtocolMessage.RedirectUri = $"{Configuracao.GetValue<string>("Autenticacao:RedirectUri:UrlBase")}signin-oidc";
                                    await Task.FromResult(0);
                                };
                                options.Events.OnRedirectToIdentityProviderForSignOut = async n =>
                                {
                                    n.ProtocolMessage.PostLogoutRedirectUri = $"{Configuracao.GetValue<string>("Autenticacao:RedirectUri:UrlBase")}signout-callback-oidc";
                                    await Task.FromResult(0);
                                };
                            });

            servicos.AddAuthorization();
            //servicos.AddAutenticacaoCustomizada(Configuracao);
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.Use((context, next) =>
            {
                context.Request.Scheme = "https";
                return next();
            });

            app.UseForwardedHeaders();

            if (env.EnvironmentName.Equals("prd", System.StringComparison.CurrentCultureIgnoreCase))
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            //app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAutenticacaoCustomizada();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=cliente}/{action=index}/");
            });
            //app.UseMvcCustomizado(env);
        }
    }

有人可以帮我解决 Correlation failed 错误吗?

所以,经过一番努力让它工作后,我找到了解决方案。

整个问题与我的 Azure 应用程序网关绑定的证书的 de SSL 证书链有关。

有人用错误的方式导出了它,没有包括证书路径:

上图是在Windows服务器上导出证书时需要勾选的复选框。

检查证书链是否在您的网关 运行 git bash 下面的命令,当您在 windows 而不是已安装 openssl:

openssl s_client -showcerts https://domainbindedwithgateway.com.br:443

将正确的证书与链重新绑定后,错误消失。

有关 SSL 证书和负载平衡器等的良好参考,请参阅:

[Azure] Application Gateway certificate gotchas