Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions docs/asciidoc/modules/jasypt.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
== Jasypt

Decrypt configuration properties using http://www.jasypt.org

=== Usage

1) Add the dependency:

[dependency, artifactId="jooby-jasypt"]
.

2) Setup properties:

.application.conf
[source, properties]
----
jasypt.password = password <1>

enc.property = "uTSqb9grs1+vUv3iN8lItC0kl65lMG+8" <2>
----

3) Install

.Java
[source, java, role="primary"]
----
import io.jooby.jasypt.JasyptModule;

{
install(new JasyptModule()); <3>

String property = getConfig().getString("property"); <4>

System.out.println(property);
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
import io.jooby.jasypt.JasyptModule

{
install(JasyptModule()) <3>

val property = config.getString("property") <4>

println(property)
}
----

<1> Configure jasypt password. Jasypt use this to encrypt/decrypt values
<2> Prefix encrypted properties with `enc`
<3> Install Jasypt
<4> Get a decrypted property

Due Jasypt overrides configuration properties, must be installed at very beginning of the
application. Once installed, you can access to decrypted properties.

By default, encrypted properties must be prefixed with `enc`, you can change this by setting
your own/preferred prefix:

install(new JasyptModule().setPrefix("secret"));

Module also export an instance of `PBEStringEncryptor`:

.Java
[source, java, role="primary"]
----
import io.jooby.jasypt.JasyptModule;

{
install(new JasyptModule());

PBEStringEncryptor encryptor = require(PBEStringEncryptor.class);
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
import io.jooby.jasypt.JasyptModule

{
install(JasyptModule())

val encryptor = require(PBEStringEncryptor::class)
}
----

==== Securing password

Password can be configured as application property. It is accessed using the `jasypt.password`
property name. It is important to keep your password safe and private.

One simple way is to use a default password for development and override it with an environment variable. For example:

.application.conf
[source, properties]
----
jasypt.password = mypassword
jasypt.password = ${?JASYPT_PASSWORD}
----

Here Jasypt will use a default value of `mypassword`, unless an environment variable `JASYPT_PASSWORD` is set.

Another option is to keep the password in the file system. For that you need to provide your own
password provider:

.File password provider
[source, java]
----
{
install(new JasyptModule(config -> {
return new String(Files.path(Paths.get("mypassword"), UTF-8));
}));
}
----

The password provider let you read password from multiple sources.

==== Options

Advanced configuration options are available from configuration file:

.application.conf
[source, properties]
----
jasypt.password = mypassword

jasypt.algorithm = PBEWithMD5AndDES
jasypt.keyObtentionIterations = 1000
jasypt.poolSize = 2
jasypt.ivGeneratorClassName = classname
jasypt.saltGeneratorClassName = org.jasypt.salt.RandomSaltGenerator
jasypt.providerName = SunJCE
----

A `PooledPBEStringEncryptor` encryptor is configured when `poolSize` is set.
1 change: 1 addition & 0 deletions docs/asciidoc/modules/modules.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Available modules are listed next.
* link:/modules/thymeleaf[Thymeleaf]: Thymeleaf template engine.

=== Security
* link:/modules/jasypt[Jasypt]: Encripted configuration files.
* link:/modules/pac4j[Pac4j]: Security engine module.

=== Session Store
Expand Down
42 changes: 27 additions & 15 deletions jooby/src/main/java/io/jooby/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,37 @@ public class Environment {

private final List<String> actives;

private final Config conf;
private Config config;

private final ClassLoader classLoader;

/**
* Creates a new environment.
*
* @param classLoader Class loader.
* @param conf Application configuration.
* @param config Application configuration.
* @param actives Active environment names.
*/
public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config config,
@Nonnull String... actives) {
this(classLoader, conf, Arrays.asList(actives));
this(classLoader, config, Arrays.asList(actives));
}

/**
* Creates a new environment.
*
* @param classLoader Class loader.
* @param conf Application configuration.
* @param config Application configuration.
* @param actives Active environment names.
*/
public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config config,
@Nonnull List<String> actives) {
this.classLoader = classLoader;
this.actives = actives.stream()
.map(String::trim)
.map(String::toLowerCase)
.collect(Collectors.toList());
this.conf = conf;
this.config = config;
}

/**
Expand All @@ -83,8 +83,8 @@ public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
* @return Property or default value.
*/
public @Nonnull String getProperty(@Nonnull String key, @Nonnull String defaults) {
if (hasPath(conf, key)) {
return conf.getString(key);
if (hasPath(config, key)) {
return config.getString(key);
}
return defaults;
}
Expand All @@ -96,8 +96,8 @@ public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
* @return Property value or <code>null</code> when missing.
*/
public @Nullable String getProperty(@Nonnull String key) {
if (hasPath(conf, key)) {
return conf.getString(key);
if (hasPath(config, key)) {
return config.getString(key);
}
return null;
}
Expand Down Expand Up @@ -136,10 +136,10 @@ public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
* @return Properties under that key or empty map.
*/
public @Nonnull Map<String, String> getProperties(@Nonnull String key, @Nullable String prefix) {
if (hasPath(conf, key)) {
if (hasPath(config, key)) {
Map<String, String> settings = new HashMap<>();
String p = prefix == null || prefix.length() == 0 ? "" : prefix + ".";
conf.getConfig(key).entrySet().stream()
config.getConfig(key).entrySet().stream()
.forEach(e -> {
Object value = e.getValue().unwrapped();
if (value instanceof List) {
Expand All @@ -159,7 +159,19 @@ public Environment(@Nonnull ClassLoader classLoader, @Nonnull Config conf,
* @return Application configuration.
*/
public @Nonnull Config getConfig() {
return conf;
return config;
}

/**
* Set configuration properties. Please note setting a configuration object must be done at very
* early application stage.
*
* @param config Configuration properties.
* @return This environment.
*/
public Environment setConfig(@Nonnull Config config) {
this.config = config;
return this;
}

/**
Expand Down Expand Up @@ -207,7 +219,7 @@ public boolean isActive(@Nonnull String name, String... names) {
}

@Override public String toString() {
return actives + "\n" + toString(conf).trim();
return actives + "\n" + toString(config).trim();
}

private String toString(final Config conf) {
Expand Down
53 changes: 53 additions & 0 deletions modules/jooby-jasypt/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<parent>
<groupId>io.jooby</groupId>
<artifactId>modules</artifactId>
<version>2.9.4-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>jooby-jasypt</artifactId>

<dependencies>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby</artifactId>
<version>${jooby.version}</version>
</dependency>

<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Loading