Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode passwords stored in the database for mail, proxy servers, harvesters and map servers. #1715

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/pom.xml
Expand Up @@ -501,6 +501,15 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
</dependency>

<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt-spring31</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -24,12 +24,15 @@
package org.fao.geonet.kernel.setting;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.domain.HarvesterSetting;
import org.fao.geonet.repository.HarvesterSettingRepository;
import org.fao.geonet.utils.Log;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jdom.Element;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -68,6 +71,10 @@ public class HarvesterSettingsManager {
@PersistenceContext
private EntityManager _entityManager;

@Autowired
private StandardPBEStringEncryptor encryptor;


// ---------------------------------------------------------------------------
// ---
// --- API methods
Expand Down Expand Up @@ -139,7 +146,11 @@ public String getValue(String path) {
HarvesterSettingRepository settingsRepo = ApplicationContextHolder.get().getBean(HarvesterSettingRepository.class);
HarvesterSetting s = settingsRepo.findOneByPath(path);

return (s == null) ? null : s.getValue();
if (s == null) {
return null;
} else {
return getSettingValue(s);
}
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -199,7 +210,7 @@ public boolean setValues(Map<String, Object> values) {
success = false;
Log.warning(Geonet.SETTINGS, "Unable to find Settings row for: " + path + ". Check settings table.");
} else {
s.setValue(value);
setSettingValue(s, value);
if (Log.isDebugEnabled(Geonet.SETTINGS)) {
Log.debug(Geonet.SETTINGS, "Set path: " + path + ", value: " + value);
}
Expand All @@ -214,8 +225,17 @@ public boolean setValues(Map<String, Object> values) {

/**
* When adding to a newly created node, path must be 'id:...'.
*
* @param path
* @param name
* @param value
* @return
*/
public String add(String path, Object name, Object value) {
return add(path, name, value, false);
}

public String add(String path, Object name, Object value, boolean encrypted) {
if (name == null)
throw new IllegalArgumentException("Name cannot be null");

Expand All @@ -231,7 +251,8 @@ public String add(String path, Object name, Object value) {
if (parent == null)
return null;

HarvesterSetting child = new HarvesterSetting().setParent(parent).setName(sName).setValue(sValue);
HarvesterSetting child = new HarvesterSetting().setParent(parent).setName(sName).setEncrypted(encrypted);
setSettingValue(child, sValue);

settingsRepo.save(child);
return Integer.toString(child.getId());
Expand Down Expand Up @@ -337,7 +358,7 @@ private Element buildFromMap(HarvesterSetting s, HashMap<Integer, List<Harvester
el.setAttribute("id", Integer.toString(s.getId()));
if (s.getValue() != null) {
Element value = new Element("value");
value.setText(s.getValue());
value.setText(getSettingValue(s));
el.addContent(value);
}

Expand Down Expand Up @@ -367,7 +388,7 @@ private Element build(HarvesterSetting s, int level) {

if (s.getValue() != null) {
Element value = new Element("value");
value.setText(s.getValue());
value.setText(getSettingValue(s));

el.addContent(value);
}
Expand Down Expand Up @@ -401,4 +422,34 @@ private void remove(HarvesterSetting s) {
public void refresh() {
_entityManager.getEntityManagerFactory().getCache().evict(HarvesterSetting.class);
}



/**
* Sets a setting value, encrypting the value if required.
*
* @param s
* @param value
*/
private void setSettingValue(HarvesterSetting s, String value) {
if (s.isEncrypted() && StringUtils.isNotEmpty(value)) {
s.setValue(this.encryptor.encrypt(value));
} else {
s.setValue(value);
}
}

/**
* Retrieves a setting value, decrypting the value if required.
*
* @param s
* @return
*/
private String getSettingValue(HarvesterSetting s) {
if (s.isEncrypted() && StringUtils.isNotEmpty(s.getValue())) {
return this.encryptor.decrypt(s.getValue());
} else {
return s.getValue();
}
}
}
Expand Up @@ -23,6 +23,7 @@

package org.fao.geonet.kernel.setting;

import org.apache.commons.lang.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.NodeInfo;
import org.fao.geonet.constants.Geonet;
Expand All @@ -34,6 +35,7 @@
import org.fao.geonet.repository.SettingRepository;
import org.fao.geonet.repository.SortUtils;
import org.fao.geonet.utils.Log;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jdom.Element;
import org.springframework.beans.factory.annotation.Autowired;

Expand Down Expand Up @@ -66,6 +68,8 @@ public class SettingManager {
private EntityManager _entityManager;
@Autowired
private ServletContext servletContext;
@Autowired
private StandardPBEStringEncryptor encryptor;

private ServletPathFinder pathFinder;

Expand Down Expand Up @@ -103,7 +107,7 @@ public Element getAllAsXML(boolean asTree) {
settingEl.setAttribute("position", String.valueOf(setting.getPosition()));
settingEl.setAttribute("datatype", String.valueOf(setting.getDataType()));
settingEl.setAttribute("internal", String.valueOf(setting.isInternal()));
settingEl.setText(setting.getValue());
settingEl.setText(getSettingValue(setting));
env.addContent(settingEl);
}
}
Expand Down Expand Up @@ -133,8 +137,9 @@ private void buildXmlTree(Element env, Map<String, Element> pathElements, Settin
currentElement.setAttribute("datatype", String.valueOf(dataType.ordinal()));
currentElement.setAttribute("datatypeName", dataType.name());

if (setting.getValue() != null)
currentElement.setText(xmlContentEscaper().escape(setting.getValue()));
if (setting.getValue() != null) {
currentElement.setText(xmlContentEscaper().escape(getSettingValue(setting)));
}
} else {
currentElement.setText("");
}
Expand Down Expand Up @@ -169,7 +174,7 @@ public String getValue(String path) {
Log.error(Geonet.SETTINGS, " Requested setting with name: " + path + " not found. Add it to the settings table.");
return null;
}
String value = se.getValue();
String value = getSettingValue(se);
if (value == null) {
Log.warning(Geonet.SETTINGS, " Requested setting with name: " + path + " but null value found. Check the settings table.");
}
Expand Down Expand Up @@ -286,7 +291,7 @@ public boolean setValue(String key, String value) {

setting.getDataType().validate(value);

setting.setValue(value);
setSettingValue(setting, value);

repo.save(setting);
return true;
Expand Down Expand Up @@ -385,4 +390,33 @@ String getBaseURL() {

return protocol + "://" + host + (port.equals("80") ? "" : ":" + port) + baseURL + "/";
}


/**
* Sets a setting value, encrypting the value if required.
*
* @param s
* @param value
*/
private void setSettingValue(Setting s, String value) {
if (s.isEncrypted() && StringUtils.isNotEmpty(value)) {
s.setValue(this.encryptor.encrypt(value));
} else {
s.setValue(value);
}
}

/**
* Retrieves a setting value, decrypting the value if required.
*
* @param se
* @return
*/
private String getSettingValue(Setting se) {
if (se.isEncrypted() && StringUtils.isNotEmpty(se.getValue())) {
return this.encryptor.decrypt(se.getValue());
} else {
return se.getValue();
}
}
}
9 changes: 9 additions & 0 deletions core/src/test/resources/web-test-context.xml
Expand Up @@ -77,4 +77,13 @@ http://www.fao.org/geonetwork/spring http://www.fao.org/geonetwork/spring/gn-spr
</gns:summaryType>
</gns:summaryTypes>

<bean id="strongEncryptor"
class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="algorithm">
<value>PBEWithMD5AndDES</value>
</property>
<property name="password">
<value>jasypt</value>
</property>
</bean>
</beans>
12 changes: 12 additions & 0 deletions domain/pom.xml
Expand Up @@ -120,6 +120,18 @@
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt-spring31</artifactId>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt-hibernate4</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
43 changes: 43 additions & 0 deletions domain/src/main/java/org/fao/geonet/domain/HarvesterSetting.java
Expand Up @@ -58,6 +58,8 @@ public class HarvesterSetting extends GeonetEntity {
private HarvesterSetting _parent;
private String _name;
private String _value;
private char _encrypted = Constants.YN_FALSE;


/**
* Get the setting id. This is a generated value and as such new instances should not have this
Expand Down Expand Up @@ -185,6 +187,47 @@ public HarvesterSetting setValue(int value) {
return setValue(String.valueOf(value));
}

/**
* For backwards compatibility we need the activated column to be either 'n' or 'y'.
* This is a workaround to allow this until future
* versions of JPA that allow different ways of controlling how types are mapped to the database.
*/
@Column(name = "encrypted", nullable = false, length = 1, columnDefinition="char default 'n'")
protected char getEncrypted_JpaWorkaround() {
return _encrypted;
}

/**
* Set the column value. Constants.YN_ENABLED for true Constants.YN_DISABLED for false.
*
* @param encryptedValue the column value. Constants.YN_ENABLED for true Constants.YN_DISABLED for false.
* @return
*/
protected void setEncrypted_JpaWorkaround(char encryptedValue) {
_encrypted = encryptedValue;
}

/**
* Return true if the setting is public.
*
* @return true if the setting is public.
*/
@Transient
public boolean isEncrypted() {
return Constants.toBoolean_fromYNChar(getEncrypted_JpaWorkaround());
}

/**
* Set true if the setting is private.
*
* @param encrypted true if the setting is private.
*/
public HarvesterSetting setEncrypted(boolean encrypted) {
setEncrypted_JpaWorkaround(Constants.toYN_EnabledChar(encrypted));
return this;
}


/**
* Get the values as a boolean. Returns false if the values is not a boolean.
*
Expand Down
17 changes: 13 additions & 4 deletions domain/src/main/java/org/fao/geonet/domain/MapServer.java
Expand Up @@ -24,20 +24,28 @@
package org.fao.geonet.domain;

import org.fao.geonet.entitylistener.MapServerEntityListenerManager;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.jasypt.hibernate4.type.EncryptedStringType;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.*;

import java.util.Map;

/**
* An entity representing mapserver used for publishing records as WMS, WFS, WCS.
*
* Note: This configuration was previously stored in wEB-INF/geoserver-nodes.xml
*
* @author Francois
*/
@TypeDef(
name="encryptedString",
typeClass=EncryptedStringType.class,
parameters= {
// value will be used later to register encryptor
@Parameter(name="encryptorRegisteredName", value="STRING_ENCRYPTOR")
}
)
@Entity
@Table(name = "Mapservers")
@Cacheable
Expand Down Expand Up @@ -232,6 +240,7 @@ public MapServer setUsername(String _username) {
* @return the password.
*/
@Column(length = 128)
@Type(type="encryptedString")
public String getPassword() {
return _password;
}
Expand Down