Centinul
Centinul

Reputation: 884

How to decrypt properties used in @ConfigurationProperties beans?

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.

Upvotes: 6

Views: 5061

Answers (3)

avmohan
avmohan

Reputation: 1970

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;
  }
}

Upvotes: 0

leoismyname
leoismyname

Reputation: 407

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);
            }
        }
    }
}}

Upvotes: 3

M S Parmar
M S Parmar

Reputation: 974

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>

Upvotes: 0

Related Questions