Skip to content

Commit 6a1f9cd

Browse files
authored
Added jasypt encrypted password handling. (#361)
1 parent 8fa3af7 commit 6a1f9cd

File tree

7 files changed

+185
-3
lines changed

7 files changed

+185
-3
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@
107107
<version>${springBootVersion}</version>
108108
</dependency>
109109

110+
<dependency>
111+
<groupId>com.github.ulisesbocchio</groupId>
112+
<artifactId>jasypt-spring-boot-starter</artifactId>
113+
<version>2.1.2</version>
114+
</dependency>
115+
110116
<dependency>
111117
<groupId>org.springframework.boot</groupId>
112118
<artifactId>spring-boot-starter-amqp</artifactId>

src/main/java/com/ericsson/ei/EndpointSecurity.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.apache.tomcat.util.codec.binary.Base64;
2121
import org.apache.tomcat.util.codec.binary.StringUtils;
22+
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
2223
import org.json.JSONArray;
2324
import org.json.JSONObject;
2425
import org.slf4j.Logger;
@@ -32,6 +33,8 @@
3233
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
3334
import org.springframework.security.config.http.SessionCreationPolicy;
3435

36+
import com.ericsson.ei.utils.TextFormatter;
37+
3538
@Configuration
3639
@EnableWebSecurity
3740
public class EndpointSecurity extends WebSecurityConfigurerAdapter {
@@ -43,6 +46,9 @@ public class EndpointSecurity extends WebSecurityConfigurerAdapter {
4346

4447
@Value("${ldap.server.list:}")
4548
private String ldapServerList;
49+
50+
@Value("${jasypt.encryptor.password:}")
51+
private String jasyptEncryptorPassword;
4652

4753
@Override
4854
protected void configure(HttpSecurity http) throws Exception {
@@ -85,8 +91,23 @@ private String decodeBase64(String password) {
8591
}
8692

8793
private void addLDAPServersFromList(JSONArray serverList, AuthenticationManagerBuilder auth) throws Exception {
94+
TextFormatter textFormatter = new TextFormatter();
95+
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
96+
97+
encryptor.setPassword(jasyptEncryptorPassword);
98+
8899
for (int i = 0; i < serverList.length(); i++) {
89100
JSONObject server = (JSONObject) serverList.get(i);
101+
String password = server.getString("password");
102+
103+
if (checkIfPasswordEncrypted(password)) {
104+
password = textFormatter.removeEncryptionParentheses(password);
105+
password = encryptor.decrypt(password);
106+
}
107+
else {
108+
password = decodeBase64(server.getString("password"));
109+
}
110+
90111
auth
91112
.eraseCredentials(false)
92113
.ldapAuthentication()
@@ -95,7 +116,11 @@ private void addLDAPServersFromList(JSONArray serverList, AuthenticationManagerB
95116
.url(server.getString("url"))
96117
.root(server.getString("base.dn"))
97118
.managerDn(server.getString("username"))
98-
.managerPassword(decodeBase64(server.getString("password")));
119+
.managerPassword(password);
99120
}
100121
}
122+
123+
private boolean checkIfPasswordEncrypted(final String password) {
124+
return (password.startsWith("ENC(") && password.endsWith(")"));
125+
}
101126
}

src/main/java/com/ericsson/ei/config/ConfigurationLogger.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ private void logConfiguration() {
7070
+ "spring.mail.properties.mail.smtp.starttls.enable: " + env.getProperty("spring.mail.properties.mail.smtp.starttls.enable") + "\n"
7171
+ "er.url: " + env.getProperty("er.url") + "\n"
7272
+ "ldap.enabled: " + env.getProperty("ldap.enabled") + "\n"
73-
+ "ldap.server.list: " + env.getProperty("ldap.server.list") + "\n"
7473
+ "logging.level.root: " + env.getProperty("logging.level.root") + "\n"
7574
+ "logging.level.org.springframework.web: " + env.getProperty("logging.level.org.springframework.web") + "\n"
7675
+ "logging.level.com.ericsson.ei: " + env.getProperty("logging.level.com.ericsson.ei") + "\n"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2019 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package com.ericsson.ei.utils;
19+
20+
21+
/**
22+
* Class that handles and formatting Strings for different needs
23+
* and can be used in different classes.
24+
*
25+
*/
26+
public class TextFormatter {
27+
28+
/**
29+
* Function that removes ENC parentheses from encrypted string.
30+
* Commonly used for password properties that has a format "ENC(d23d2ferwf4t55)"
31+
* This function removes "ENC(" text and end ")" parentheses and return only the
32+
* encryption as string.
33+
*
34+
* Function handle also "ENC(<encrypted password>" with missing end , ')', parentheses.
35+
*
36+
* @param stringWithEncryptionParantheses The string that contains the ENC() string.
37+
*
38+
* @return Then string formatted encrypted password without ENC().
39+
*/
40+
public String removeEncryptionParentheses(String stringWithEncryptionParantheses) {
41+
String formattedEncryptionString = stringWithEncryptionParantheses.replace("ENC(","");
42+
int lastParanthesesOccurenxeIndex = formattedEncryptionString.lastIndexOf(")");
43+
if (lastParanthesesOccurenxeIndex == -1) {
44+
return formattedEncryptionString;
45+
}
46+
formattedEncryptionString = formattedEncryptionString.subSequence(0, lastParanthesesOccurenxeIndex).toString();
47+
return formattedEncryptionString;
48+
}
49+
}

src/main/resources/application.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ rabbitmq.host: localhost
2525
rabbitmq.port: 5672
2626
rabbitmq.user: myuser
2727
rabbitmq.password: myuser
28+
# Check configuration documentation for using jasypt encrypted passswords
2829
# Valid TLS versions: 'TLSv1.2', 'TLSv1.1', 'TLSv1', 'TLS', 'SSLv3', 'SSLv2', 'SSL'
2930
rabbitmq.tlsVersion:
3031
rabbitmq.exchange.name: ei-exchange
@@ -48,6 +49,7 @@ spring.data.mongodb.host: localhost
4849
spring.data.mongodb.port: 27017
4950
#spring.data.mongodb.username:
5051
#spring.data.mongodb.password:
52+
# Check configuration documentation for using jasypt encrypted passswords
5153
spring.data.mongodb.database: eiffel_intelligence
5254
# we cannot have empty username and password property here
5355
# if these properties are empty, remove or comment them
@@ -123,6 +125,8 @@ er.url:
123125
# Settings for ldap server if ldap authentication is needed.
124126
# For security reasons and to avoid authorization problems this
125127
# password should be encoded in base64. It will be decoded in EndpointSecurity.java.
128+
#
129+
# Password field can also be Jasypt encoded, check configuration documentation for info.
126130
ldap.enabled: false
127131
ldap.server.list: [{\
128132
"url": "",\
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
Copyright 2019 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package com.ericsson.ei.utils;
19+
20+
import static org.junit.Assert.assertEquals;
21+
import org.junit.Test;
22+
23+
import com.ericsson.ei.utils.TextFormatter;
24+
25+
public class TextFormatterTest {
26+
27+
@Test
28+
public void testRemoveEncryptionParentheses() {
29+
final String encryptedPassword = "ENC(m0++Ua2Pe1j/5X/x8NpKsQ==)";
30+
final String expectedEncryptedPassword = "m0++Ua2Pe1j/5X/x8NpKsQ==";
31+
32+
assertEquals("Failed to remove ENC() from encrypted password property string.",
33+
expectedEncryptedPassword,
34+
new TextFormatter().removeEncryptionParentheses(encryptedPassword));
35+
}
36+
37+
@Test
38+
public void testRemoveEncryptionParenthesesWithMissingEndParentheses() {
39+
final String encryptedPassword = "ENC(m0++Ua2Pe1j/5X/x8NpKsQ==";
40+
final String expectedEncryptedPassword = "m0++Ua2Pe1j/5X/x8NpKsQ==";
41+
42+
assertEquals("Failed to remove ENC() from encrypted password property string.",
43+
expectedEncryptedPassword,
44+
new TextFormatter().removeEncryptionParentheses(encryptedPassword));
45+
}
46+
}

wiki/markdown/configuration.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,57 @@ and the settings are defined in the **ldap.server.list** property.
168168
"password": "",\
169169
"user.filter": "uid={0}"\
170170
}\
171-
]\
171+
]\
172+
173+
## Password encryption
174+
175+
In a production environment and filesystems, administrator most likely don't want to store passwords in clear text.
176+
177+
These Eiffel-Intelligence password properties can be provided encrypted:
178+
179+
rabbitmq.password
180+
spring.data.mongodb.password
181+
182+
183+
A password property is configured by providing the encrypted password in this format.
184+
185+
some.component.password=ENC(<encrypted password>)
186+
187+
188+
Ldap encrypted password is set inside **ldap.server.list** property according the example below:
189+
190+
ldap.server.list=[{\
191+
"url": "<ldap address>",\
192+
"base.dn": "<dn>",\
193+
"username": "<username>",\
194+
"password": "ENC(<encrypted password>)",\
195+
"user.filter": "<filter>"\
196+
}]
197+
198+
How and examples of how to encrypt passwords can be found on Jasypt homepage.
199+
On Jasypt homepage encrypt.sh script can be downloaded, which can be used to encrypt passwords:
200+
201+
http://www.jasypt.org/cli.html
202+
203+
Short guide about encrypting passwords:
204+
205+
**1** Encrypt actual component password with secret encrypting password.
206+
Encrypting password should be a secret password and is created/generated by administator user and should not be written/stored in application.properties or any other config files near the application in the filesystem:
207+
208+
./encrypt.sh input="<the actual component password>" password=<the secret encryptor password>
209+
210+
**2** That above step will generate the encrypted component password, example:
211+
212+
rv/2O+hOT4GJSPmmF/cF1w==
213+
214+
**3** Now open application.properties file and add the new encrypted password to the specific component password property with "ENC(<encrypted password>)" format:
215+
216+
some.component.password=ENC(rv/2O+hOT4GJSPmmF/cF1w==)
217+
218+
Do step 1 to 3 for all component passwords and properties in application.properties. Remember to use same secret encryptor password for all components passwords.
219+
220+
**4** Now its time to run Eiffel-Intelligence with these encrypted passwords in application.properties.
221+
Eiffel-Intelligence will decrypt password properties with help of the provided secret encryptor password at run-time.
222+
Execute Eiffel-Intelligence with "jasypt.encryptor.password=<the secret encryptor password>" flag, example:
223+
224+
java -jar eiffel-intelligence-<version>.war --jasypt.encryptor.password=<the secret encryptor password> --spring.config.location=/path/to/application.properties

0 commit comments

Comments
 (0)