https://github.com/wsargent/ocapjsse
Object Capability Enabled JSSE classes
https://github.com/wsargent/ocapjsse
capabilities java jsse logging ocap revocation security
Last synced: 4 months ago
JSON representation
Object Capability Enabled JSSE classes
- Host: GitHub
- URL: https://github.com/wsargent/ocapjsse
- Owner: wsargent
- License: apache-2.0
- Created: 2018-08-30T02:51:08.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2018-10-21T04:28:10.000Z (almost 7 years ago)
- Last Synced: 2025-03-14T18:42:29.575Z (7 months ago)
- Topics: capabilities, java, jsse, logging, ocap, revocation, security
- Language: Java
- Homepage: https://tersesystems.com/blog/2018/10/20/jsse-with-object-capabilities/
- Size: 58.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Object Capability (OCAP) Enabled JSSE
This is a small library that provides proxies for JSSE based classes such as `SSLEngine`, `KeyManager` and `TrustManager`, and provides facilities to decorate behavior with logging and revocation.
## Construction
Object capabilities are based around deferred execution and composition, so that instead of dealing with a direct object reference, you deal with a proxy that manages your access to the object.
Proxies are very simple to set up. You define a supplier, and then you delegate all access through resolving that supplier. Here's an example of X509ExtendedKeyManager set up with a proxy:
```java
package com.tersesystems.ocapjsse;public class ProxyX509ExtendedKeyManager extends X509ExtendedKeyManager {
protected Supplier supplier;
public ProxyX509ExtendedKeyManager(Supplier supplier) {
Objects.requireNonNull(supplier);
this.supplier = supplier;
}public String chooseEngineClientAlias(
final String[] keyTypes, final Principal[] issuers, final SSLEngine engine) {
return supplier.get().chooseEngineClientAlias(keyTypes, issuers, engine);
}
// ...
}
```### Logging
Once you have a proxy, you can then set up logging around the manager:
```java
package com.tersesystems.ocapjsse.revocable;public class LoggingX509ExtendedTrustManager extends ProxyX509ExtendedTrustManager {
private final TraceLogger tracer;public LoggingX509ExtendedTrustManager(
final Supplier supplier, final TraceLogger tracer) {
super(supplier);
this.tracer = tracer;
}@Override
public void checkClientTrusted(final X509Certificate[] chain, final String authType,
final Socket socket)
throws CertificateException {
final Object[] params = {chain, authType, socket};
tracer.apply(
"checkClientTrusted", params, () -> super.checkClientTrusted(chain, authType, socket));
}
// ...
}
```This is a lightweight alternative to using the [debugjsse provider](https://github.com/tersesystems/debugjsse), as you can restrict logging to only a single trust manager.
```java
public class LoggingX509ExtendedTrustManagerTest {@Test
public void testLog() throws Exception {
final TraceLogger tracer =
new AbstractTraceLogger() {
@Override
protected void entry(final String methodName, final Object... parameters) {
System.out.println("entry: " + methodName);
}@Override
protected R exit(final R result, final String methodName,
final Object... parameters) {
System.out.println("exit: " + methodName);
return result;
}@Override
protected void exit(final String methodName, final Object... parameters) {
System.out.println("exit: " + methodName);
}@Override
protected void exception(final Throwable e, final String methodName,
final Object... parameters) {
System.out.println("exception: " + methodName);
}
};try {
final SSLContext sslContext = SSLContext.getInstance("TLS");
final TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
final TrustManager[] tms =
Arrays.stream(tmf.getTrustManagers())
.map(LoggingX509ExtendedTrustManager.transform(tracer))
.toArray(TrustManager[]::new);sslContext.init(null, tms, null);
final HttpsURLConnection urlConnection =
(HttpsURLConnection) new URL("https://www.google.com").openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());// Call Google
try (final BufferedReader in =
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {
final String result = in.lines().collect(Collectors.joining());
System.out.println(result);
}
} catch (final Exception e) {
e.printStackTrace();
}
}
}
```### Revocation
You can even use a caretaker to set up revocation. This can be used to break off communication immediately when a security guarantee is violated, or to enforce a time limit on access.
```java
package com.tersesystems.ocapjsse.revocable;public class RevocableTrustManagerTest {
@Test
public void testRevokedEngine() throws Exception {
X509ExtendedTrustManager trustManager = createTrustManager();
assertThat(trustManager).isNotNull();Caretaker caretaker = Caretaker
.create(trustManager, ProxyX509ExtendedTrustManager::new);
X509ExtendedTrustManager proxyTrustManager = caretaker.getCapability();X509Certificate[] issuers = proxyTrustManager.getAcceptedIssuers();
assertThat(issuers).isNotNull();
caretaker.getRevoker().revoke();Throwable throwable = catchThrowable(proxyTrustManager::getAcceptedIssuers);
assertThat(throwable).isInstanceOf(RevokedException.class);
}
}
```For more about revocation, see [managing accessibility with revocation](https://wsargent.github.io/ocaps/guide/management.html#managing-accessibility-with-revocation).