Пользовательский поставщик для AWS SSM с использованием Microsoft.Configuration.ConfigurationBuilders - PullRequest
0 голосов
/ 24 сентября 2019

Мне кажется, что я застрял при разработке собственного поставщика пар ключ / значение для хранилища параметров (SSM) Amazon System Manager с использованием 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>

Спасибо

...