Describe the bug We are using the spring cloud config server to load configuration into our spring boot app using git and hashicorp vault. The configuration for the server is like this

spring:
  profiles:
    active: git,vault
  cloud:
    config:
      server:
        native:
        git:
          uri: https://our-git-uri
          searchPaths:
            - '{application}'
        vault:
          host: our-vault-host
          scheme: https
          port: 443
          authentication: our-authentication
          kv-version: 2

The configurations being loaded contain vault import configuration similar to this

spring:
  config:
    import: >-
       vault://arbitrary/secret/path1
       vault://arbitrary/secret/path2

The Spring cloud config server loads the configuration successfully and then proceeds to import the properties from the vault paths specified in the configuration, which is exactly what we want. I would then expect these properties to be returned to the application that requested the configuration. They are not - hence the bug report.

I have done some investigation and worked out the following:

There seem to be two barriers to these properties being returned in the response to the configuration request.

Problem 1

The PassthruEnvironmentRepository only 'passes through' configuration in MapPropertySources but the vault properties are stored in EnumerablePropertySources. it is really easy to change this behaviour with the following code change

in PassthruEnvironmentRepository::findOne change MapPropertySource to EnumerablePropertySource

            if (!this.standardSources.contains(name) && source instanceof EnumerablePropertySource<?>) {
                result.add(
                        new PropertySource(name, getMap((EnumerablePropertySource<?>) source, includeOrigin), source));
            }

then PasstheuEnvironmentRepository::getMap can be simplified and still work the same

    private Map<?, ?> getMap(EnumerablePropertySource<?> source, boolean includeOrigin) {
        Map<Object, Object> map = new LinkedHashMap<>();
        if (includeOrigin && source instanceof OriginLookup) {
            Map<?, ?> input = (Map<?, ?>) source.getSource();
            OriginLookup<String> originLookup = (OriginLookup<String>) source;
            for (Object key : input.keySet()) {
                Origin origin = originLookup.getOrigin(key.toString());
                if (origin == null) {
                    map.put(key, source.getProperty(key.toString()));
                    continue;
                }
                String originDesc;
                if (origin instanceof TextResourceOrigin) {
                    TextResourceOrigin tro = (TextResourceOrigin) origin;
                    originDesc = tro.getLocation().toString();
                }
                else {
                    originDesc = origin.toString();
                }
                Object value = source.getProperty(key.toString());
                map.put(key, new PropertyValueDescriptor(value, originDesc));
            }
        }
        else {
            for (String key : source.getPropertyNames()) {
                // Spring Boot wraps the property values in an "origin" detector, so we
                // need
                // to extract the string values
                map.put(key, source.getProperty(key));
            }
        }
        return map;
    }

As MapPropertySource extends EnumerablePropertySource this is backwards compatible and does not change the normal functionality, but now the properties returned from the arbitrary vault path import are available in the property source map.

Problem 2

The next thing that stops the properties from the arbitrary vault paths being returned is the NativeEnvironmentRepository. Even though we do not have the native profile enabled the NativeEnvironmentRepository is used to filter out what is returned. the NativeEnvironmentRepository::matchesLocation method does not return true for the arbitrary vault paths and I cannot fathom a clean way to make this actually happen. This is where I got stuck.

I am very happy with the way that the cloud config server chooses which configuration files to load but it we have a requirement that each active profile may load up different properties from arbitrary vault paths that have nothing to do with the application or profile of the configuration file that they are specifies in. We do not even control those paths on the app side.

It is very frustrating that it so nearly works exactly as we want, but that the properties get filtered out at the end because they are not linked to the active profile in the same way.

We would like to use the cloud-config-server as a one-stop-shop for loading configuration but this is stopping us.

Can this be fixed?

Comment From: ryanjbaxter

Can you please do me a favor and create 3 separate issues so we can cleanly address each one of these?

Comment From: piercer

Hi Ryan,

I am only experiencing one issue - the list of problems was showing you what I had investigated - I don't think they make sense as individual issues.

Conrad

Comment From: ryanjbaxter

if you specify spring.config.import statements in configuration from the config server its going to be too late for Boot to take them into consideration I believe. Boot will already have constructed the list of locations to look for configuration data at that point

Comment From: piercer

Thats not the behaviour we observe. The spring config server loads the configuration for the application and profile and then it performs an import for all of the imports specified in those configuration files. It is exactly the behaviour we want. It picks up the configuration from the files checked out of git and imports the properties from the vault paths. Unfortunately it then does not return the properties loaded from the vault paths.

Comment From: ryanjbaxter

Can you provide a complete, minimal, verifiable sample that reproduces the problem? It should be available as a GitHub (or similar) project or attached to this issue as a zip file.

Comment From: piercer

In order to provide a complete minimal verifiable sample you would need a spring config server, a hashicorp vault installation, a git server and a spring boot application. Not sure how to provide all of that. I'll see what I can do