【发布时间】:2020-01-24 20:26:37
【问题描述】:
我似乎被困在使用 NETFramework 4.7.1 为 Amazon 的 System Manager Parameter Store (SSM) 开发自定义键/值对提供程序,该 NETFramework 4.7.1 利用 Microsoft.Configuration.ConfigurationBuilders。
实现:
using System;
using System.Collections.Generic;
using Amazon.SimpleSystemsManagement;
using Amazon.SimpleSystemsManagement.Model;
using Microsoft.Configuration.ConfigurationBuilders;
using System.Linq;
using System.Diagnostics;
using System.Collections.Specialized;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using System.Configuration;
using System.Threading.Tasks;
namespace AXS.Configurations
{
public class ParameterStoreConfigBuilder : KeyValueConfigBuilder
{
public const string envTag = "Environment";
public const string appNameTag = "AppName";
private IAmazonSimpleSystemsManagement client;
/// <summary>
/// Gets or sets an environment (dev|qa|staging|production)
/// </summary>
public string Environment { get; set; }
/// <summary>
/// Gets or sets a AppName
/// </summary>
public string AppName { get; set; }
public ParameterStoreConfigBuilder(IAmazonSimpleSystemsManagement client,
string appName,
string environment)
{
this.client = client;
Environment = environment.ToLower();
AppName = appName;
}
public ParameterStoreConfigBuilder()
{
client = new AmazonSimpleSystemsManagementClient();
}
public override string Description => "Parameter Store";
public override string Name => "SSM";
protected override void LazyInitialize(string name, NameValueCollection config)
{
Optional = false;
base.LazyInitialize(name, config);
string env = UpdateConfigSettingWithAppSettings(envTag);
if (string.IsNullOrWhiteSpace(env))
throw new ArgumentException($"environment must be specified with the '{envTag}' attribute.");
Environment = env;
string appName = UpdateConfigSettingWithAppSettings(appNameTag);
if (string.IsNullOrWhiteSpace(appName))
throw new ArgumentException($"appName must be specified with the '{appNameTag}' attribute.");
AppName = appName;
client = new AmazonSimpleSystemsManagementClient("","", Amazon.RegionEndpoint.USWest2);
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
Trace.TraceInformation($"return values prefix {prefix}");
if (client == null)
return null;
var parameters = new List<Parameter>();
string nextToken = null;
do
{
var response = client.GetParametersByPath(new GetParametersByPathRequest { Path = prefix, Recursive = true, WithDecryption = true, NextToken = nextToken });
nextToken = response.NextToken;
parameters.AddRange(response.Parameters);
} while (!string.IsNullOrEmpty(nextToken));
return parameters.Select(p => new
{
Key = p.Name,
p.Value
}).ToDictionary(parameter => parameter.Key, parameter => parameter.Value, StringComparer.OrdinalIgnoreCase);
}
public override string GetValue(string key)
{
return Task.Run(async () => { return await GetValueAsync(key); }).Result;
}
private async Task<string> GetValueAsync(string key)
{
var name = $"/{Environment}/{AppName}/{key.Replace(':', '/')}";
Trace.WriteLine($"get value async:{name}");
if (client == null)
return null;
try
{
Trace.TraceInformation($"fetch key {name}");
var request = new GetParameterRequest
{
Name = name,
WithDecryption = true
};
var response = await client.GetParameterAsync(request);
var parameter = response.Parameter;
var value = parameter.Type == ParameterType.SecureString ? "*****" : parameter.Value;
Trace.TraceInformation($"fetched name={name} value={value}");
return value;
}
catch (Exception e) when (Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException))) { }
return null;
}
}
}
问题似乎是 AWS SSM client 永远不会被创建。
如果我更改代码并尝试在构造函数中实例化,我会因为递归而得到堆栈溢出异常。
关于如何强制创建 AmazonSimpleSystemsManagementClient 的任何想法?
代码使用来自https://github.com/aspnet/MicrosoftConfigurationBuilders的指导
App.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false"
requirePermission="true" />
</configSections>
<configBuilders>
<builders>
<add name="ParameterStore" Environment="development" AppName="myAppNameforParmStore" type="AXS.Configurations.ParameterStoreConfigBuilder, AXS.Configurations" />
<add name="Env" prefix="appsettings_" stripPrefix="true" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment, Version=2.0.0.0, Culture=neutral" />
</builders>
</configBuilders>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<appSettings configBuilders="Env,ParameterStore">
<add key="Url" value="URL Value for from paramter Store" />
<add key="Secret" value="Some Secret value decrypted" />
</appSettings>
</configuration>
谢谢
【问题讨论】:
-
嗨 Haroon - 我今天决定为自己写一个,首先在网上搜索看看是否有人已经写过,然后在上面找到了你的问题。假设我在接下来的几天内得到一个工作,我会回来发布代码,除非你已经解决了你的问题。
-
@Kirkaiya - 根本问题是 NET 框架与任何第三方库一起工作,这些库也从 web.config 中读取,例如 Amazon 的 Runtime 类以获取配置信息。请参阅以下内容:github.com/aspnet/MicrosoftConfigurationBuilders/issues/78
-
嗨 Haroon - 我实际上通过省略具体构造函数并仅使用静态构造函数以及 GetValue/AllValues 方法中的空检查来解决对构造函数的递归调用。我将在下面发布我的解决方案。它在本地工作,但我还没有在 EC2 或任何东西上测试它。
标签: amazon-web-services .net-4.7.1 aws-parameter-store