How to use keystore in Websphere Liberty and in Java? - websphere

maybe it dumb question but I couldn't find explanation by googling.
There is settings in server.xml file of Websphere Liberty 8.5
<keyStore id="sampleJKSKeyStore"
location="MyKeyStoreFile.jks"
type="JKS" password="myPassword" />
What can I do with this keystore? Can I for example programatically save to and load from PrivateKey / PublicKey which I create by using the following code:
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
final PrivateKey privateKey1=key.getPrivate();
final PublicKey publickey1=key.getPublic();
Thank you in advance!

The keystore configuration essentially just tells the Liberty profile runtime where the keystore is and how to get certificates from it. It can then be associated with the httpEndpoint to store the certificates for https. There are other ways it is used by the Liberty runtime, but the usage is by the runtime, not for applications. If you would like to get application access to it you can raise a request for the product to be enhanced here.

Related

Spring SAML 2.0 extention does not use the public certificate imported in the keystore.jks

I am new to saml 2.0. I'm trying to understand the saml 2.0 springboot extension. I came across the sample app by Vincenzo De Notaris and Thomas Darimont.
Here is the git hub sample: https://github.com/vdenotaris/spring-boot-security-saml-sample
In saml security config, the keymanager bean needs to be defined. Because saml extension uses a private key to sign and a public certificate to verify. Correct me if I'm wrong.
here is the bean definition.
#Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader
.getResource("classpath:/saml/samlKeystore.jks");
String storePass = "nalle123";
Map<String, String> passwords = new HashMap<>();
passwords.put("apollo", "nalle123");
String defaultKey = "apollo";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
here samlKeystore.jks has an expired private key with alias 'apollo'.
There are two more public certificates with alias 'ssocircle' and 'startcom'.
When I run the application, I saw that only the private key is used for signing the message. I could not see where the certificate ssocircle is used. I'm able to see the ssocircle login page and able to log in.
I deleted this certificate from the Keystore, and I tried to log in again, I'm still getting the login page and I am able to successfully log in.
It is the same with keycloak as well. The samlKeystore.jks needs to be imported into the keys section of the client. I don't seem to understand the need for the public certificate.
To Reproduce
Steps to reproduce the behavior.
checkout the code from https://github.com/vdenotaris/spring-boot-security-saml-sample.
in the resources/saml folder delete the ssocircle certificate from samlKeystore.jks, build the project, and run the spring-boot application.
When third-party login is clicked, it successfully lands on the login page and allows you to log in.
Expected behavior
It should not allow you to log in without a valid certificate.
I want to understand the role of the public certificate. how does it work in a production environment
here is the link to keycloak implementation:
https://blog.codecentric.de/secure-spring-boot-app-saml-keycloak

Is it possible to programmatically provide a Java KeyStore and TrustStore to Connector/J?

I'd like to connect to a MySQL/MariaDB RDBMS using Connector/J (or another compatible driver) and provide the keystore and truststore directly to the driver, rather than supplying a filename for an on-disk keystore/truststore.
I'm not storing my keys and certificates on the disk any longer and I'd like to avoid having to drop them into a temporary file just for this purpose.
This answer seems to be no. As the way to configure KeyStore and TrustStore is by providing an URL, not a class/factory.
I think it is possible, if you are willing to go through a log of hoops to make it happen.
Because e.g. clientCertificateKeyStoreUrl will accept a URL, you can supply it one with a custom protocol handler, like mykeysupplier://mykey.
You can write a custom URLConnection class for mekeysupplier and then return whatever bytes you want from the getInputStream() method. You have to register a protocol handler and stuff like that, too.
So, it's kind of horrifically ugly, but I think it can be made to work and will surely try at least a PoC of this idea, because it will likely solve my problem (I posted the original question).
There may be another option.
I re-read the configuration reference for Connector/J and there is a URL property that can be specified for connections: socketFactory. This must be the fully-qualified name of a class which implements Connector/J's interface called SocketFactory (note that this is similar but unrelated to the standard library class javax.net.SocketFactory).
This interface is pretty small:
public interface SocketFaactory {
Socket afterHandshake() throws SocketException, IOException;
Socket beforeHandshake() throws SocketException, IOException;
Socket connect(String host, int portNumber, Properties props) throws SocketException, IOException;
}
Later versions of the driver add a fourth int loginTimeout parameter to the connect method.
At any rate, it looks like this might be the basis for a solution.
Unfortunately, MySQL does not use vanilla TLS connections so it might not be as simple as returning a Socket from a standard customized javax.net.ssl.SSLSocketFactory.
UPDATE
The SSL/TLS magic happens after connection due to the way MySQL manages its protocol (it's not just plain-TLS).
In the 5.1-era drivers, it's done in a class called ExportControlled in a method called getSSLSocketFactoryDefaultOrConfigured. In later versions (I have 8.0-era source in front of me), it's done in the same class but in a different method called performTlsHandshake.
Without significant hacking of the driver source or re-implementation of a ton of code, I suspect that the better solution is to implement the URL-based keystore-loading from this answer.
Yes, it's possible to programmatically provide a Java KeyStore and TrustStore to Connector/J. You can use the java.security.KeyStore and java.security.TrustStore classes to create the keystore and truststore in memory, and then pass them to the Connector/J Driver and Connection classes via the javax.net.ssl.keyStore and javax.net.ssl.trustStore system properties, respectively.
HERE IS A CODE SAMPLE
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
// ...
// Load the keystore and truststore data into memory
byte[] keystoreData = ...;
byte[] truststoreData = ...;
// Create the keystore and truststore objects
KeyStore keyStore = KeyStore.getInstance("JKS");
KeyStore trustStore = KeyStore.getInstance("JKS");
keyStore.load(new ByteArrayInputStream(keystoreData), keystorePassword);
trustStore.load(new ByteArrayInputStream(truststoreData), truststorePassword);
// Set the system properties to use the in-memory keystore and truststore
System.setProperty("javax.net.ssl.keyStore", keyStore);
System.setProperty("javax.net.ssl.trustStore", trustStore);
// Connect to the database using Connector/J
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);

embedded Jetty start without certificate and when cert available load it

I have embedded Jetty server in my Java code. I am loading a SSL certificate by using SslContextFactory class. My problem is when Jetty server starts that time .jks file is not present at the mentioned file path because it is generated dynamically and stores in the path. As .jks file is not present so server is not starting and giving NullPointerException. I will use sslContextFactory.reload() when certificate available on path but I am not sure how to deal with NullPointerException at the starting time.
Is there way to tell Jetty start without certificate and when sslContextFactory.reload() reloads the certificate.
Update
Jetty Version : 9.4.26.v20200117
I am using below code to load certificate.
private final static String KEYSTORE_LOCATION = "/home/myproject/keystore.jks";
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(getKeystoreLocation());
sslContextFactory.setKeyStorePassword("temp");
sslContextFactory.setKeyManagerPassword("temp");
private static String getKeystoreLocation() throws MalformedURLException {
File file = new File(KEYSTORE_LOCATION);
URL url = file.toURI().toURL();
return url.toExternalForm();
}
I am getting NullPointerException for file. Can you please let me know what missing here?
Use Jetty 9.4.46 (or newer).
Jetty 9.4.26 is subject to a few security issues now - see https://www.eclipse.org/jetty/security_reports.php for details
Is this SslContextFactory for Server or for Client use?
Server uses SslContextFactory.Server, and client uses SslContextFactory.Client implementations. (your old version of Jetty might not have this distinction, which was a source of a few issues in the past)
The configured keystore/truststore file(s) needs to exist once you start Jetty.
Even if that keystore/truststore file is a dummy/empty one, it needs to exist.
Once you start, you can replace the keystore/truststore file(s) and the SslContextFactory will detect the changed file and reload the SslContextFactory.

Apache HttpClient for RestTemplate default behaviour if not setting up SSLSocketFactory and SSLContext

I am using Spring RestTemplate (config using HttpClient) to make a restful service call for a URL with https.
I explicitly setup SSL using following code:
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial().setProtocol().build
return new SSLConnectionSocketFactory(sslContext)
It works without any problem.
What would be the default behaviour if I don't setup SSLSocketFactory and SSLContext for HttpClient? Will it look for the cacerts under the installed JDK or it will disable the ssl?
I say Yes If your https website can be passed by your browser, or your certificate file is coming from the Certificate Authority such as GlobalSign, Verisign
we can see the SSLContext and SSLSocketFactory will be created automatically, so you can visit https without doing anything
if your certificate file is not trusted, and import to jdk cacerts still can't solve this, because HttpClient download the certificate file via SSLSocket, not from the jdk cacerts

remove keyManager bean in securityContext file?

How can I remove the keyManager bean in securityContext.xml and the jks file ?
I don't really need it to generate the metadata of my Service Provider.
Thanks.
See Spring SAML manual chapter 8.1:
In case your application doesn't need to create digital signatures
and/or decrypt incoming messages, it is possible to use an empty
implementation of the keystore which doesn't require any JKS file -
org.springframework.security.saml.key.EmptyKeyManager.

Resources