
com.github.ncredinburgh.tomcat.ExternalPropertySource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomcat-external-propertysource Show documentation
Show all versions of tomcat-external-propertysource Show documentation
A Tomcat PropertySource class that reads provides property values from an external file.
package com.github.ncredinburgh.tomcat;
import static com.github.ncredinburgh.tomcat.Defaults.DEFAULT_CIPHER_SPEC;
import static com.github.ncredinburgh.tomcat.encryption.PropertiesUtil.isPropertiesFile;
import static java.nio.file.Files.readAllBytes;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import javax.xml.bind.DatatypeConverter;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.IntrospectionUtils;
import com.github.ncredinburgh.tomcat.encryption.Cipher;
import com.github.ncredinburgh.tomcat.encryption.FileEncryptor;
import com.github.ncredinburgh.tomcat.encryption.JCACipher;
/**
* Enables Tomcat to read properties from an external Java properties file and substitute them using
* ${property}
syntax in Tomcat configuration files.
*
* Usage:
*
* Set the following Java system properties on Tomcat startup:
*
* - org.apache.tomcat.util.digester.PROPERTY_SOURCE
* - Set to to the value
com.github.ncredinburgh.tomcat.ExternalPropertySource
* See Tomcat documentation.
*
* - com.github.ncredinburgh.tomcat.ExternalPropertySource.FILENAME
* - The path of the external Java properties file. See Relative Paths.
*
*
* Encryption Support
*
* The property source can read files from an encrypted Java properties file. To enable encryption support
* set the following optional Java system properties on Tomcat startup:
*
*
* - com.github.ncredinburgh.tomcat.ExternalPropertySource.KEYFILE
* - The path to a valid decryption key file. See Relative Paths.
*
* - com.github.ncredinburgh.tomcat.ExternalPropertySource.CIPHER
* - A cipher spec and should be of the form
algorithm/mode/padding
. See {@link javax.crypto.Cipher}.
* If no CIPHER
property is specified, the default cipher is used: {@link Defaults#DEFAULT_CIPHER_SPEC}.
*
* - com.github.ncredinburgh.tomcat.ExternalPropertySource.CIPHERIV
* - The initialization vector required when using some block cipher modes in base64 encoding.
*
*
* Relative Paths
*
* If a relative path is specified in any system property value it will be resolved
* against the current working directory (system property user.dir
).
*/
public class ExternalPropertySource implements IntrospectionUtils.PropertySource {
public static final String FILENAME = ExternalPropertySource.class.getName() + ".FILENAME";
public static final String KEYFILE = ExternalPropertySource.class.getName() + ".KEYFILE";
public static final String CIPHER = ExternalPropertySource.class.getName() + ".CIPHER";
public static final String CIPHERIV = ExternalPropertySource.class.getName() + ".CIPHERIV";
private static final Log LOGGER = LogFactory.getLog(ExternalPropertySource.class);
private final Properties properties = new Properties();
public ExternalPropertySource() throws IOException {
LOGGER.debug("Creating ExternalPropertySource");
LOGGER.debug("Relative filenames are resolved against USER.DIR which is: " + System.getProperty("user.dir"));
String propertyFilename = System.getProperty(FILENAME);
if (propertyFilename != null) {
File propertyFile = new File(propertyFilename);
loadProperties(propertyFile);
} else {
LOGGER.debug("No properties file specified");
}
}
public String getProperty(String key) {
if (properties == null) return null;
return properties.getProperty(key);
}
private void loadProperties(File propertyFile) throws IOException {
LOGGER.info("Reading properties from external file: " + propertyFile.getAbsolutePath());
String keyFilename = System.getProperty(KEYFILE);
if (keyFilename == null) {
loadClearProperties(propertyFile);
} else {
loadEncryptedProperties(propertyFile, new File(keyFilename));
}
if (properties.size() == 0) {
LOGGER.warn("No properties were found in external file");
}
}
private void loadClearProperties(File propertyFile) throws IOException {
if (!isPropertiesFile(new FileReader(propertyFile))) {
LOGGER.warn("The external file does not look like a Java properties file");
}
properties.load(new FileInputStream(propertyFile));
}
private void loadEncryptedProperties(File propertyFile, File keyFile) throws IOException, FileNotFoundException {
if (isPropertiesFile(new FileReader(propertyFile))) {
LOGGER.warn("The external file does not look like an encrypted file");
}
LOGGER.debug("Using decryption key file: " + keyFile.getAbsolutePath());
String cipherSpec = System.getProperty(CIPHER, DEFAULT_CIPHER_SPEC);
LOGGER.debug("Using cipher: " + cipherSpec);
String cipherIV = System.getProperty(CIPHERIV);
LOGGER.debug("Using cipher iv: " + cipherIV);
Cipher cipher = new JCACipher(cipherSpec, readAllBytes(keyFile.toPath()), decodeIV(cipherIV));
FileEncryptor decryptor = new FileEncryptor(cipher);
properties.load(decryptor.decryptFile(propertyFile));
}
private byte[] decodeIV(String iv) {
if (iv == null) return null;
return DatatypeConverter.parseBase64Binary(iv);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy