Allow encoded properties in application.yml

main.class

    public static void main(final String[] args) {
        SpringApplication application=new SpringApplication(IdpUiApplication.class);
        application.addInitializers(new PropertyDecodingContextInitializer());
        application.run(args);
    }

PropertyDecodingContextInitializer.class

package com.ahold.api.idp.ui;

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Base64.Decoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class PropertyDecodingContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    private static final Pattern base64Pattern = Pattern.compile("base64\\((.*?)\\)");

    /**
     * Handle every property and check if it is base64 encoded. overwrite the value with the decoed value.
     */
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        log.debug("initialize: scanning for encoded properties");
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        for (PropertySource<?> propertySource : environment.getPropertySources()) {
            Map<String, Object> propertyOverrides = new LinkedHashMap<>();
            decodeProperties(propertySource, propertyOverrides);
            if (!propertyOverrides.isEmpty()) {
                PropertySource<?> decodedProperties = new MapPropertySource("decoded " + propertySource.getName(),
                        propertyOverrides);
                environment.getPropertySources().addBefore(propertySource.getName(), decodedProperties);
            }
        }
    }

    /**
     * Decode all encoded properties and put them in the overrides map. Also the
     * original properties without encoding are added to the map.
     *
     * @param source - source of the properties
     * @param propertyOverrides - resulting map of decoded properties
     */
    private void decodeProperties(PropertySource<?> source, Map<String, Object> propertyOverrides) {
        if (source instanceof EnumerablePropertySource) {
            EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) source;
            for (String key : enumerablePropertySource.getPropertyNames()) {
                Object rawValue = source.getProperty(key);
                if (rawValue instanceof String) {
                    // Only strings can represent a base64 encoded value
                    String decodedValue = decodeBase64InString((String) rawValue);
                    propertyOverrides.put(key, decodedValue);
                }
            }
        }
    }

    /**
     * @param input - possible base64 code
     * @return decoded string
     */
    private String decodeBase64InString(String input) {
        if (StringUtils.isBlank(input)) return input;

        StringBuffer output = new StringBuffer();
        Matcher matcher = base64Pattern.matcher(input);
        while (matcher.find()) {
            String replacement = decodeBase64(matcher.group(1));
            matcher.appendReplacement(output, replacement);
        }
        matcher.appendTail(output);
        return output.toString();
    }

    /**
     * @param encoded - base64 value
     * @return decoded value
     */
    private String decodeBase64(String encoded) {
        try {
            Decoder base64Decoder = Base64.getDecoder();
            byte[] decodedData = base64Decoder.decode(encoded);
            String decodedString = new String(decodedData, "UTF-8");
            return decodedString;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}