All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.xs.hdb.options.ConnectionProperties Maven / Gradle / Ivy

There is a newer version: 2.13.0
Show newest version
package com.sap.xs.hdb.options;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sap.xs.env.Credentials;
import com.sap.xs.env.Service;
import com.sap.xs.hdb.utils.DigestUtils;

/**
 * @deprecated As of 1.9.0, either HanaServiceConnectionHelper or
 *             ConnectionPropertiesBuilder should be used instead.
 */
@Deprecated
public class ConnectionProperties extends Properties {

	private static final String CLIENT_AUTHENTICATION_PRIVATE_KEY = "client_authentication_private_key";

	private static final long serialVersionUID = -1094629476809611586L;

	private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
	private static final String END_CERTIFICATE = "-----END CERTIFICATE-----";

	private static final String BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----";
	private static final String END_PRIVATE_KEY = "-----END PRIVATE KEY-----";

	private static final Logger LOGGER = Logger.getLogger(ConnectionProperties.class.getName());

	private final Service hanaService;
	private Path keyStorePath;

	/**
	 * @param hanaService hana service
	 * @param securityPath security path
	 */
	public ConnectionProperties(Service hanaService, Path securityPath) {
		this.hanaService = hanaService;
		final Credentials credentials = hanaService.getCredentials();
		if (credentials == null) {
			throw new IllegalArgumentException(hanaService.getName() + " has no credentials");
		}

		setUrl(credentials.getUrl());
		setHost(credentials.getHost());
		setPort(credentials.getPort());
		setDriver(credentials.getDriver());
		setUser(credentials.getUser());
		setPassword(credentials.getPassword());
		setEncrypt(credentials.any().get("encrypt"));
		setHostNameInCertificate(credentials.any().get("hostname_in_certificate"));
		setValidateCertificate(credentials.any().get("validate_certificate"));

		if (isClientCertificateProvided()) {
			try {
				String keyStoreName = createKeyStoreFileName();
				String keyStorePassowrd = createKeyStorePassword();
				keyStorePath = securityPath.resolve(keyStoreName).toAbsolutePath();
				setKeyStore(keyStorePath.toString());
				setKeyStorePassword(keyStorePassowrd);
			} catch (NoSuchAlgorithmException e) {
				throw new IllegalArgumentException(
						"Unable to generate secure keystore for service " + hanaService.getName(), e);
			}
		} else {
			keyStorePath = null;
		}
	}

	/**
	 * @return connection property url
	 */
	public String getUrl() {
		return getProperty("url");
	}

	/**
	 * @param url connection property url
	 */
	public final void setUrl(String url) {
		setObjectProperty("url", url);
	}

	/**
	 * @return connection property driver
	 */
	public String getDriver() {
		return getProperty("driver");
	}

	/**
	 * @param driver connection property driver
	 */
	public final void setDriver(String driver) {
		setObjectProperty("driver", driver);
	}

	/**
	 * @return connection property host
	 */
	public String getHost() {
		return getProperty("host");
	}

	/**
	 * @param host connection property host
	 */
	public final void setHost(String host) {
		setObjectProperty("host", host);
	}

	/**
	 * @return connection property port
	 */
	public String getPort() {
		return getProperty("port");
	}

	/**
	 * @param port connection property port
	 */
	public final void setPort(String port) {
		setObjectProperty("port", port);
	}

	/**
	 * @param user connection property user
	 */
	public final void setUser(String user) {
		setObjectProperty("user", user);
	}

	/**
	 * @return connection property user
	 */
	public String getUser() {
		return getProperty("user");
	}

	/**
	 * @param password connection property password
	 */
	public final void setPassword(String password) {
		setObjectProperty("password", password);
	}

	/**
	 * @return connection property password
	 */
	public String getPassword() {
		return getProperty("password");
	}

	/**
	 * @return connection property key store
	 */
	public String getKeyStore() {
		return getProperty("keyStore");
	}

	/**
	 * @param keyStorePath connection property key store path
	 */
	public final void setKeyStore(String keyStorePath) {
		setObjectProperty("keyStore", keyStorePath);
	}

	/**
	 * @return connection property key store password
	 */
	public String getKeyStorePassword() {
		return getProperty("keyStorePassword");
	}

	/**
	 * @param keyStorePassword connection property key store password
	 */
	public final void setKeyStorePassword(String keyStorePassword) {
		setObjectProperty("keyStorePassword", keyStorePassword);
	}

	/**
	 * Sets connection property.
	 *
	 * @param key the key/name of the property
	 * @param value the value of the property
	 */
	public void setObjectProperty(String key, Object value) {
		if (value != null) {
			super.setProperty(key, value.toString());
		}
	}

	@Override
	public synchronized String toString() {
		final StringBuilder sb = new StringBuilder();
		forEach((key, value) -> sb.append(key).append("=").append(value).append(";"));
		if (sb.length() > 0) {
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

	/**
	 * Initialize key store location for HANA connection for a service.
	 */
	public void initializeKeyStore() {
		if (!isClientCertificateProvided()) {
			LOGGER.log(Level.FINE, "Key Store cannot be created for service " + hanaService.getName()
					+ " because client certificate is not present");
			return;
		}
		if (keyStorePath.toFile().exists()) {
			LOGGER.log(Level.FINE, "Key Store is already created for service " + hanaService.getName());
		} else {
			Path securityPath = keyStorePath.getParent();
			if (!securityPath.toFile().exists()) {
				try {
					Files.createDirectories(securityPath);
				} catch (IOException e) {
					LOGGER.log(Level.SEVERE,
							"Cannot create keyStore location for HANA connection for service instances", e);
					return;
				}
			}
			createKeyStoreForInstance(hanaService);
		}
	}

	private boolean isClientCertificateProvided() {
		Credentials credentials = hanaService.getCredentials();
		return credentials.any().get("client_authentication_certificate") != null &&
				credentials.any().get(CLIENT_AUTHENTICATION_PRIVATE_KEY) != null;
	}

	private String createKeyStoreFileName() throws NoSuchAlgorithmException {
		return DigestUtils.getSha256HexString(hanaService.getName());
	}

	private String createKeyStorePassword() throws NoSuchAlgorithmException {
		final Credentials credentials = hanaService.getCredentials();
		return DigestUtils.getSha256HexString(credentials.any().get(CLIENT_AUTHENTICATION_PRIVATE_KEY).toString());
	}

	private void setHostNameInCertificate(Object hostnameInCertificate) {
		setObjectProperty("hostNameInCertificate", hostnameInCertificate);
	}

	private void setValidateCertificate(Object validateCertificate) {
		setObjectProperty("validateCertificate", validateCertificate);
	}

	private void setEncrypt(Object encrypt) {
		setObjectProperty("encrypt", encrypt);
	}

	private void createKeyStoreForInstance(Service hanaService) {
		String clientAuthenticationPrivateKey = hanaService.getCredentials().any()
				.get(CLIENT_AUTHENTICATION_PRIVATE_KEY).toString();
		String clientAuthenticationCertificate = hanaService.getCredentials().any()
				.get("client_authentication_certificate").toString();

		String pkContent = clientAuthenticationPrivateKey.replace(BEGIN_PRIVATE_KEY, "")
				.replace(END_PRIVATE_KEY, "").replace("\n", "");
		String pkCertificate = clientAuthenticationCertificate.replace(BEGIN_CERTIFICATE, "")
				.replace(END_CERTIFICATE, "").replace("\n", "");

		try {
			KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
			keyStore.load(null);

			char[] password = DigestUtils.getSha256Hex(clientAuthenticationPrivateKey);
			addKeyEntry(keyStore, hanaService.getName(), pkContent, pkCertificate, password);
			keyStore.store(Files.newOutputStream(keyStorePath, StandardOpenOption.CREATE), password);
		} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException
				| InvalidKeySpecException e) {
			LOGGER.log(Level.SEVERE,
					"Cannot create keyStore for HANA connection for service instance " + hanaService.getName(), e);
		}

	}

	private void addKeyEntry(KeyStore keyStore, String alias, String pkContent, String pkCertificate,
			char[] keystorePass)
			throws NoSuchAlgorithmException, InvalidKeySpecException, CertificateException, KeyStoreException {
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(pkContent));
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

		CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
		Certificate cert = certFactory
				.generateCertificate(new ByteArrayInputStream(Base64.getDecoder().decode(pkCertificate)));

		keyStore.setKeyEntry(alias, privateKey, keystorePass, new Certificate[] { cert });
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy