1

简短的问题陈述:
如何从 Cloud Foundry CredHub 获得价值以在内部使用ConfigureServices(IServiceCollection services)

现有条件:
假设我有一个SystemConfig用于保存配置值的类。我在“开发”阶段使用 json 文件和 dotnet 机密的组合来存储这些值,并且可以通过以下方式检索它们

services.Configure<SystemConfig>(Configuration.GetSection("GLOBAL"));

在“SIT”阶段,我使用 Pivotal Cloud Foundry 来托管应用程序,并使用 ConfigServer - CredHub 的组合来存储配置值。CredHub 中的值可以通过内部Configure(IApplicationBuilder app)检索

var credhub = app.ApplicationServices.GetService<IOptions<CloudFoundryServicesOptions>>().Value.Services["credhub"].First(x => x.Name.Equals("credhub-instance"));
var sysConfig = app.ApplicationServices.GetService<IOptions<SystemConfig>>().Value;
sysConfig.SAMPLE_A = credhub.Credentials[nameof(sysConfig.SAMPLE_A)].Value;

当我需要从IdentityModel.AspNetCore内部配置访问令牌管理时,就会出现问题ConfigureServices

services.AddAccessTokenManagement(x => 
{
     x.Client.Clients.Add("key_sample", new IdentityModel.Client.ClientCredentialsTokenRequest()
     {
         Address = "sysConfig.SAMPLE_A",
         ClientId = "taken from sysConfig as well",
         ClientSecret = "taken from sysConfig as well"
     });
});

该方法AddAccessTokenManagement只能在内部使用,ConfigureService(IServiceCollection services)但同时我还没有来自 CredHub 的值,因为它们是在内部检索的Configure(IApplicationBuilder app)
也不推荐使用 ,services.BuildServiceProvider()因为它会创建可能导致意外错误的单例服务的额外副本。

所以问题归结为:

  • 我们可以在里面检索 CredHub 值ConfigureService(IServiceCollection services)吗?
  • 如果不可能,那么我们可以以某种方式设置AddAccessTokenManagement在里面Configure(IApplicationBuilder app)吗?
4

1 回答 1

2

我无法在这里谈论 IdentityModel 的复杂性,乍一看,我看不出有什么能让这方面变得容易的东西,但我有一个应该可以通过自定义方式使用 Steeltoe 连接器的解决方案SsoServiceInfo可以定位。

理想情况下,Steeltoe 会SsoServiceInfo自动绑定这些凭据,但目前没有任何内置的东西可以建立这种连接。当我们在这里完成时,此代码将用于检索服务信息:

services.AddAccessTokenManagement(x =>
{
    var creds = Configuration.GetServiceInfo<SsoServiceInfo>("credhub-instance");
    x.Client.Clients.Add("key_sample", new IdentityModel.Client.ClientCredentialsTokenRequest()
    {
        Address = creds.AuthDomain,
        ClientId = creds.ClientId,
        ClientSecret = creds.ClientSecret
    });
});

为了启用上述代码,我们需要添加一个ServiceInfoFactory可以将您的 credhub 服务实例绑定到的自定义SsoServiceInfo

using Steeltoe.Connector.Services;
using Steeltoe.Extensions.Configuration;

public class AuthServiceInfoFactory : ServiceInfoFactory
{
    public AuthServiceInfoFactory()
        : base(new Tags("credhub"), "credhub")
         // second param here for url scheme won't actually be used but can't be empty
    {
    }

    public override IServiceInfo Create(Service binding)
    {
        // these methods ship with Steeltoe, but look for "client_id" and "client_secret" - customize as desired
        var clientId = GetClientIdFromCredentials(binding.Credentials);
        var clientSecret = GetClientSecretFromCredentials(binding.Credentials);
        var authDomain = GetStringFromCredentials(binding.Credentials, "auth_domain");

        return new SsoServiceInfo(binding.Name, clientId, clientSecret, authDomain);
    }
}

接下来添加ServiceInfoFactoryAssembly属性,AssemblyInfo.cs以便 Steeltoe 可以找到您的新工厂:

using Steeltoe.Connector;

[assembly: ServiceInfoFactoryAssembly]

此外,连接器基于 CloudFoundry 配置提供程序构建,因此请确保您已将其添加到主机构建器或配置构建器中,如下所示:

Host.CreateDefaultBuilder(args)
     .AddCloudFoundryConfiguration();

最后,请注意,从 v3.0 开始,vcap:services除非vcap:application已设置,否则 Steeltoe 将无法识别,因此您可能希望在非 CloudFoundry 环境中使用此配置格式:

  "services": {
    "credhub": [{
      "name": "credhub-instance",
      "credentials": {
        "Client_Id": "myClientId",
        "Client_Secret": "myClientSecret"
      },
      "tags": ["credhub"]
    }]
  }
于 2021-06-24T21:26:11.980 回答