kubernetes 扩展IdentityServer4服务

neskvpey  于 2023-06-21  发布在  Kubernetes
关注(0)|答案(3)|浏览(141)

我已经遵循了IdentityServer4 quickstarts,并且能够使用Implicit授权使用本地托管的IdentityServer示例来验证我的JavaScript网页(几乎与快速入门中提供的相同)。同样,我的IdentityServer几乎和上面提到的快速入门中提供的完全一样-它只是有一些自定义的用户详细信息。
然后,我将我的应用程序(C# .NET Core)移动到一个docker容器中,并在Kubernetes集群中托管了一个示例(单个示例),并创建了一个Kubernetes服务(一个或多个“真实的”服务的门面),它允许我从集群外部访问身份服务器。我可以修改我的JavaScript网页,并将其指向我的Kubernetes服务,它仍然会很高兴地显示登录页面,而且它看起来像预期的那样工作。
当我将IdentityServer扩展到三个示例(所有示例都在一个Kubernetes服务后提供)时,我开始遇到问题。Kubernetes服务会向每个身份服务器发出循环请求,因此第一个将显示登录页面,但第二个将在我按下登录按钮后尝试处理身份验证。这将导致以下错误:
System.InvalidOperationException:无法解密防伪令牌。--->系统.安全.加密.CryptographicException:在钥匙环中找不到钥匙{19742 e88 - 9dc 6 - 44 a0 - 9 e89-e7 b 09 db 83329}。Microsoft。AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData,Boolean allowOperationsOnRevokedKeys,UnprotectStatus& status)Microsoft。AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData,Boolean ignoreRevocationErrors,Boolean& requiresMigration,Boolean& wasRevoked)Microsoft。AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)Microsoft。AspNetCore. AntiforgerryTokenSerializer.Deserialize(String serializedToken)----内部异常堆栈跟踪结束-- ...还有更多......
所以-我知道我得到这个错误,因为期望是相同的IdentityServer应该服务于它显示的页面的请求(否则防伪令牌将如何工作,对吗?),但我试图理解的是我如何在复制的环境中使此工作。
我不想在不同的IP/端口上托管多个身份服务器;我正在尝试构建一个HA配置,如果一个IdentityServer死亡,调用端点的任何东西都不应该关心(因为请求应该由其他工作示例提供服务)。
我说我正在使用快速启动代码-这意味着在IdentityServer的启动中,有代码看起来像这样...

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

        services.AddIdentityServer(options =>
            {
                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents = true;
            })
            .AddTemporarySigningCredential()
            .AddInMemoryIdentityResources(Config.GetIdentityResources())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients())

我假设我需要用一个证书替换.AddTemporarySigningCredential()逻辑,该证书可以被运行在Kubernetes集群中的IdentityServer的所有示例使用。不知道MVC是如何工作的(MVC 6用于生成IdentityServer服务中的登录页面,我从上面的示例代码中获得)-我想知道仅仅更改代码以使用在所有服务之间共享的适当证书是否足以让原型HA IdentityServer集群工作?
通过工作,我的意思是我的期望是我可以在Kubernetes集群中运行n个IdentityServer示例,有一个Kubernetes服务来充当我运行的IdentityServer的门面,并且能够使用多个IdentityServer示例进行身份验证,这些示例可以共享数据,因为它们都为我的调用Web应用程序提供完全相同的权限。并且可以在一个或多个示例死亡的情况下处理彼此的请求。
任何帮助或见解将不胜感激。

ncgqoxb0

ncgqoxb01#

我想我已经解决了。为了解决这个问题,我做了两件事:
1.创建我自己的X509证书,并在我的每个IdentityServer之间共享此证书。有很多关于如何在网络上创建有效证书的例子;我只是用了

services.AddIdentityServer(...).AddSigningCredential(new X509Certificate2(bytes, "password")

在我的创业课上
1.深入研究MVC框架代码,发现我需要实现一个Key storage provider,以便在Identity Server的MVC部分的不同示例之间共享状态,该部分提供登录页面。
事实证明,有一个Redis backed KSP available from NuGet,这意味着我只需要在我的Kube集群中启动一个私有的redis示例(在我的集群之外无法访问)来共享解密秘密。

/* Note: Use an IP, or resolve from DNS prior to adding redis based key store as direct DNS resolution doesn't work for this inside a K8s cluster, though it works quite happily in a Windows environment. */  
var redis = ConnectionMultiplexer.Connect("1.2.3.4:6379");
services.AddDataProtection()
        .PersistKeysToRedis(redis, "DataProtection-Keys");

我现在可以将我的身份服务扩展到3个示例,并在所有可用示例上使用Kube服务作为门面。我可以在身份服务之间查看Kubernetes循环请求的日志,我的身份验证就像我期望的那样发生。
感谢那些在这篇文章之前就这个问题发表评论的人。

ttcibm8c

ttcibm8c2#

对于使用Kubernetes的用户,可以使用文件系统密钥存储提供程序

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"/app/key-storage"));
}

其中目录“/app/key-storage”被Map到NFS支持的持久卷。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-key-storage
spec:
  selector:
    matchLabels:
      type: nfs-pv
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Mi
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
  labels:
    type: nfs-pv
spec:
  storageClassName: manual
  capacity:
    storage: 10Mi
  accessModes:
    - ReadWriteMany
  nfs:
    server: <server>
    path: /<path>
  persistentVolumeReclaimPolicy: Delete

在IDP部署中

template:
  spec:
    containers:
      - name: <name>
        volumeMounts:
          - name: key-storage
            mountPath: /app/key-storage
            readOnly: false
    volumes:
      - name: key-storage
        persistentVolumeClaim:
        claimName: pvc-key-storage

你需要签署证书。这可以作为秘密添加,然后IDP部署可以使用另一卷来装载秘密(未示出)。

apiVersion: v1
kind: Secret
metadata:
  name: cert-secret
  labels:
    app: <app-label>
type: Opaque
data:
  signingcert.pfx: <base64 cert value>
fykwrbwg

fykwrbwg3#

1.使配置和操作数据存储持久化。
1.使用x509证书对密钥进行签名和验证。
1.添加数据保护并保持密钥共享(在redis,filestore或blobstorage中)。
如果你需要这些的代码块就告诉我

相关问题