Ошибка при привязке параметра из AWS хранилища параметров в Spring Boot - PullRequest
0 голосов
/ 23 апреля 2020

Из-за некоторых известных уязвимостей я не могу использовать spring-cloud-starter- aws -parameter-store-config в своей организации. Поэтому я просто попытался извлечь код из jar и использовать его в своем проекте. Но я не могу привязать параметр из aws store к весенней загрузке. Я получаю следующую ошибку:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'db.username' in value "${db.username}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175) ~[spring-context-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$$Lambda$220/254979217.resolveStringValue(Unknown Source) ~[na:na]
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:908) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1228) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:636) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:397) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    ... 37 common frames omitted

Это файлы, которые я использую

import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties({AwsParamStoreProperties.class})
@ConditionalOnClass({AWSSimpleSystemsManagement.class, AwsParamStorePropertySourceLocator.class})
@ConditionalOnProperty(
        prefix = "aws.paramstore",
        name = {"enabled"},
        matchIfMissing = true
)
public class AwsParamStoreBootstrapConfiguration {
}
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("aws.paramstore")
@Validated
public class AwsParamStoreProperties {

    public static final String CONFIG_PREFIX = "aws.paramstore";

    @NotNull
    @Pattern(
            regexp = "(/[a-zA-Z0-9.\\-_]+)*"
    )
    private String prefix = "/config";

    @NotEmpty
    private String defaultContext = "application";

    @NotNull
    @Pattern(
            regexp = "[a-zA-Z0-9.\\-_/]+"
    )
    private String profileSeparator = "_";

    private boolean failFast = true;
    private String name;
    private boolean enabled = true;

    public AwsParamStoreProperties() {
    }
    //Getter and Setters

}
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathRequest;
import com.amazonaws.services.simplesystemsmanagement.model.GetParametersByPathResult;
import com.amazonaws.services.simplesystemsmanagement.model.Parameter;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.core.env.EnumerablePropertySource;

public class AwsParamStorePropertySource extends EnumerablePropertySource<AWSSimpleSystemsManagement> {
    private String context;
    private Map<String, Object> properties = new LinkedHashMap();

    public AwsParamStorePropertySource(String context, AWSSimpleSystemsManagement ssmClient) {
        super(context, ssmClient);
        this.context = context;
    }

    public void init() {
        GetParametersByPathRequest paramsRequest = (new GetParametersByPathRequest()).withPath(this.context).withRecursive(true).withWithDecryption(true);
        this.getParameters(paramsRequest);
    }

    public String[] getPropertyNames() {
        Set<String> strings = this.properties.keySet();
        return (String[])strings.toArray(new String[strings.size()]);
    }

    public Object getProperty(String name) {
        return this.properties.get(name);
    }

    private void getParameters(GetParametersByPathRequest paramsRequest) {
        GetParametersByPathResult paramsResult = ((AWSSimpleSystemsManagement)this.source).getParametersByPath(paramsRequest);
        Iterator var3 = paramsResult.getParameters().iterator();

        while(var3.hasNext()) {
            Parameter parameter = (Parameter)var3.next();
            String key = parameter.getName().replace(this.context, "").replace('/', '.');
            this.properties.put(key, parameter.getValue());
        }

        if (paramsResult.getNextToken() != null) {
            this.getParameters(paramsRequest.withNextToken(paramsResult.getNextToken()));
        }

    }
}
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.util.ReflectionUtils;

public class AwsParamStorePropertySourceLocator implements PropertySourceLocator {
    private AWSSimpleSystemsManagement ssmClient;
    private AwsParamStoreProperties properties;
    private List<String> contexts = new ArrayList();
    private Log logger = LogFactory.getLog(this.getClass());

    public AwsParamStorePropertySourceLocator(AWSSimpleSystemsManagement ssmClient, AwsParamStoreProperties properties) {
        this.ssmClient = ssmClient;
        this.properties = properties;
    }

    public List<String> getContexts() {
        return this.contexts;
    }

    public PropertySource<?> locate(Environment environment) {
        if (!(environment instanceof ConfigurableEnvironment)) {
            return null;
        } else {
            ConfigurableEnvironment env = (ConfigurableEnvironment)environment;
            String appName = this.properties.getName();
            if (appName == null) {
                appName = env.getProperty("spring.application.name");
            }

            List<String> profiles = Arrays.asList(env.getActiveProfiles());
            String prefix = this.properties.getPrefix();
            String defaultContext = prefix + "/" + this.properties.getDefaultContext();
            this.contexts.add(defaultContext + "/");
            this.addProfiles(this.contexts, defaultContext, profiles);
            String baseContext = prefix + "/" + appName;
            this.contexts.add(baseContext + "/");
            this.addProfiles(this.contexts, baseContext, profiles);
            Collections.reverse(this.contexts);
            CompositePropertySource composite = new CompositePropertySource("aws-param-store");
            Iterator var9 = this.contexts.iterator();

            while(var9.hasNext()) {
                String propertySourceContext = (String)var9.next();

                try {
                    composite.addPropertySource(this.create(propertySourceContext));
                } catch (Exception var12) {
                    if (this.properties.isFailFast()) {
                        this.logger.error("Fail fast is set and there was an error reading configuration from AWS Parameter Store:\n" + var12.getMessage());
                        ReflectionUtils.rethrowRuntimeException(var12);
                    } else {
                        this.logger.warn("Unable to load AWS config from " + propertySourceContext, var12);
                    }
                }
            }

            return composite;
        }
    }

    private AwsParamStorePropertySource create(String context) {
        AwsParamStorePropertySource propertySource = new AwsParamStorePropertySource(context, this.ssmClient);
        propertySource.init();
        return propertySource;
    }

    private void addProfiles(List<String> contexts, String baseContext, List<String> profiles) {
        Iterator var4 = profiles.iterator();

        while(var4.hasNext()) {
            String profile = (String)var4.next();
            contexts.add(baseContext + this.properties.getProfileSeparator() + profile + "/");
        }

    }
}

bootstrap .yml

aws:
  paramstore:
    prefix: /config
    name: sample
    enabled: true
    profileSeparator: _

spring.factories

org.springframework.cloud.bootstrap.BootstrapConfiguration=\com.app.paramstore.AwsParamStoreBootstrapConfiguration
...