Populate configuration properties from environment post processor

Viewed 243

I am using java-cfenv library and implemented custom ``EnvProcessor`.

public class VaultServiceProcessor implements CfEnvProcessor {
    @Override
    public boolean accept(CfService service) {
        return service.existsByLabelStartsWith("cf-vault");
    }

    @Override
    public void process(CfCredentials cfCredentials, Map<String, Object> properties) {
        properties.put("endpoint", cfCredentials.getString("endpoint"));
        properties.put("role_id", cfCredentials.getString("role_id"));
        properties.put("secret_id", cfCredentials.getString("secret_id"));
        properties.put("org_secret_path", cfCredentials.getString("org_secret_path"));
        properties.put("space_secret_path", cfCredentials.getString("space_secret_path"));
        properties.put("service_secret_path", cfCredentials.getString("service_secret_path"));

        properties.put("spring.cloud.vault.host", cfCredentials.getString("endpoint"));
        String port = cfCredentials.getString("port"); // does not exist
        if (null == port) { // are there cases when it is not https?
            port = cfCredentials.getString("endpoint").startsWith("https") ? "443" : "80";
        }
        properties.put("spring.cloud.vault.port", port);
        properties.put("spring.cloud.vault.scheme", "443".equals(port) ? "https" : "http");

        properties.put("spring.cloud.vault.authentication", "APPROLE");
        properties.put("spring.cloud.vault.app-role.role-id", cfCredentials.getString("role_id"));
        properties.put("spring.cloud.vault.app-role.secret-id", cfCredentials.getString("secret_id"));
    }

    @Override
    public CfEnvProcessorProperties getProperties() {
        return CfEnvProcessorProperties.builder()
            .propertyPrefixes("core.application.vault")
            .build();
    }
}

I have ConfigurationProperties bean, that supposed to be populated by the properties I processed in the processor

@Profile("cloud")
@Configuration
@ConfigurationProperties("core.application.vault")
public class VaultCloudProperties {
    private String roleId;
    private String secretId;
    private String orgSecretPath;
    private String spaceSecretPath;
    private String serviceSecretPath;

    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }

    public String getSecretId() {
        return secretId;
    }

    public void setSecretId(String secretId) {
        this.secretId = secretId;
    }

    public String getOrgSecretPath() {
        return orgSecretPath;
    }

    public void setOrgSecretPath(String orgSecretPath) {
        this.orgSecretPath = orgSecretPath;
    }

    public String getSpaceSecretPath() {
        return spaceSecretPath;
    }

    public void setSpaceSecretPath(String spaceSecretPath) {
        this.spaceSecretPath = spaceSecretPath;
    }

    public String getServiceSecretPath() {
        return serviceSecretPath;
    }

    public void setServiceSecretPath(String serviceSecretPath) {
        this.serviceSecretPath = serviceSecretPath;
    }

    @Override
    public String toString() {
        return "VaultServiceInfo [roleId=" + roleId + ", secretId=" + secretId + ", orgSecretPath="
            + orgSecretPath + ", spaceSecretPath=" + spaceSecretPath + ", serviceSecretPath="
            + serviceSecretPath + "]";
    }
}

And then I have configuration that supposed to use those properties

@Configuration
@Profile("cloud")
@ConditionalOnProperty(name = "spring.cloud.vault.enabled", matchIfMissing = false)
@EnableConfigurationProperties({VaultGenericBackendProperties.class, VaultCloudProperties.class})
@Import(VaultBootstrapConfiguration.class)
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class MultiBackendsVaultConnectorBootstrapConfiguration {

  private static final String VERSION_BACKEND_PREFIX = "^/v1/";

  @Bean
  public VaultConfigurer cloudVaultConfigurer(Environment environment, VaultCloudProperties cloudProperties) {
    List<SecretBackendMetadata> backends = new ArrayList<>();
    String keyName = environment.getProperty("spring.cloud.vault.defaultKey");
    backends.add(
      GenericSecretBackendMetadata
        .create(cloudProperties.getServiceSecretPath().replaceAll(VERSION_BACKEND_PREFIX, ""), keyName));
    backends.add(
      GenericSecretBackendMetadata
        .create(cloudProperties.getSpaceSecretPath().replaceAll(VERSION_BACKEND_PREFIX, ""), keyName));
    backends.add(
      GenericSecretBackendMetadata
        .create(cloudProperties.getOrgSecretPath().replaceAll(VERSION_BACKEND_PREFIX, ""), keyName));

    return new VaultConnectorConfigurer(backends);
  }

The problem is that VaultCloudProperties are not populated. I can see all the correct values inside Environment variable though (inside PropertySource).

What is the problem?

1 Answers

It seems like I needed to do two things.

First was to add marker interface Aware to configuration properties

public class VaultCloudProperties implements Aware {

And the second thing is I needed to populate properties with prefixes

properties.put("core.application.vault.endpoint", cfCredentials.getString("endpoint"));
properties.put("core.application.vault.role_id", cfCredentials.getString("role_id"));
properties.put("core.application.vault.secret_id", cfCredentials.getString("secret_id"));
properties.put("core.application.vault.org_secret_path", cfCredentials.getString("org_secret_path"));
properties.put("core.application.vault.space_secret_path", cfCredentials.getString("space_secret_path"));
properties.put("core.application.vault.service_secret_path", cfCredentials.getString("service_secret_path"));

After that, VaultCloudProperties got all the correct values

Related