6

I'm using Spring Boot 1.2.3 and I'd like to understand if it's possible to decrypt a property value before its injected into a bean annotated with @ConfigurationProperties.

Suppose I have the following in an application.properties file:

appprops.encryptedProperty=ENC(ENCRYPTEDVALUE)

and a sample application like so:

package aaa.bb.ccc.propertyresearch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import javax.annotation.PostConstruct;

@SpringBootApplication
@EnableConfigurationProperties(PropertyResearchApplication.ApplicationProperties.class)
public class PropertyResearchApplication {

    public static void main(String[] args) {
        SpringApplication.run(PropertyResearchApplication.class, args);
    }

    @ConfigurationProperties("appprops")
    public static class ApplicationProperties {
        private String encryptedProperty;

        @PostConstruct
        public void postConstruct() throws Exception {
            System.out.println("ApplicationProperties --> appprops.encryptedProperty = " + encryptedProperty);
        }

        public String getEncryptedProperty() {
            return encryptedProperty;
        }

        public void setEncryptedProperty(String encryptedProperty) {
            this.encryptedProperty = encryptedProperty;
        }
    }
}

In the past I've used a custom PropertySourcesPlaceholderConfigurer to achieve this but it requires setting up a structure like the following:

@Component
public class ApplicationProperties {
    @Value("${appprops.enrcyptedProperty}")
    private String encryptedProperty;

    @PostConstruct
    public void postConstruct() throws Exception {
        System.out.println("ApplicationProperties --> appprops.encryptedProperty = " + encryptedProperty);
    }

    public String getEncryptedProperty() {
        return encryptedProperty;
    }
}

While that in and of itself is not bad I'd like to see if I can leverage the niceties of @ConfigurationProperties with encrypted properties.

Centinul
  • 874
  • 3
  • 10
  • 18
  • 2
    Have you seen this: http://stackoverflow.com/questions/24451110/creating-a-custom-jasypt-propertysource-in-springboot – derkoe Apr 29 '15 at 13:30
  • OP found the answer on http://stackoverflow.com/a/24486190/4094797. Kindly check the link to find the solution. – user2339071 Jul 13 '15 at 16:00

3 Answers3

3

Just drop the following file in your spring project and implement custom decrypt method.

@Component
public class CmtEncryptedPropertyConfigurer extends PropertySourcesPlaceholderConfigurer {

private ConfigurableEnvironment environment;

@Override
public void setEnvironment(Environment environment) {
    super.setEnvironment(environment);
    this.environment = (ConfigurableEnvironment) environment;
}
@Override
protected void loadProperties(Properties props) throws IOException {
    this.localOverride = true;
    for (PropertySource<?> propertySource : environment.getPropertySources()) {
        if (propertySource instanceof EnumerablePropertySource) {
            String[] propertyNames = ((EnumerablePropertySource) propertySource).getPropertyNames();
            for (String propertyName : propertyNames) {
                String propertyValue = propertySource.getProperty(propertyName).toString();
                // put logic to see if decryption required for thsi name/value
                // decrypt here
                String decryptedValue = decrypt(propertyValue);
                // set value here
                props.setProperty(propertyName, decryptedValue);
            }
        }
    }
}}
leoismyname
  • 407
  • 6
  • 11
0

you can use org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer can be add following Spring configuration in spring context xml file.

<context:property-placeholder location="classpath:application.properties"/>


<bean class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer">
        <constructor-arg ref="configurationEncryptor" />
        <property name="location" value="classpath:application.properties" />
    </bean>
    <bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="algorithm" value="PBEWithMD5AndDES" />
        <property name="password" value="password" />
    </bean>
M S Parmar
  • 955
  • 8
  • 22
0

PropertyResourceConfigurer has a convertPropertyValue method which you can override for this purpose.

https://docs.spring.io/autorepo/docs/spring/4.1.6.RELEASE/javadoc-api/org/springframework/beans/factory/config/PropertyResourceConfigurer.html#convertPropertyValue-java.lang.String-

public class EncryptedPropertySourcedPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer {

  @Override
  protected String convertPropertyValue(String originalValue) {
    if(originalValue.startswith("ENC") {
      return decrypt(originalValue.subString(4, originalValue.length() - 1);
    }
    return originalValue;
  }
}
avmohan
  • 1,820
  • 3
  • 20
  • 39
  • This function is never used tho. And here is merge request to fix that https://github.com/spring-projects/spring-framework/pull/23377 – greg Aug 28 '19 at 08:11
  • @greg Then it must be a regression or something because I've definitely used this in the past. – avmohan Aug 28 '19 at 12:38