We have spring boot based app on netty, and recently we've added this piece of code:
SslContextBuilder.forClient()
.enableOcsp(true)
.sslProvider(SslProvider.OPENSSL)
For this to work we have added this dependecy:
io.netty:netty-tcnative-boringssl-static:2.0.62.Final
When we want to run it on k8s we got error:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.netty.handler.ssl.SslContext]: Factory method 'sslContext' threw exception with message: failed to load the required native library
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178) ~[spring-beans-6.1.1.jar:6.1.1]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-6.1.1.jar:6.1.1]
... 117 common frames omitted
Caused by: java.lang.UnsatisfiedLinkError: failed to load the required native library
at io.netty.handler.ssl.OpenSsl.ensureAvailability(OpenSsl.java:616) ~[netty-handler-4.1.101.Final.jar:4.1.101.Final]
at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:835) ~[netty-handler-4.1.101.Final.jar:4.1.101.Final]
at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:615) ~[netty-handler-4.1.101.Final.jar:4.1.101.Final]
with causes:
Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_tcnative_linux_aarch_64_fedora.so
at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:186)
... 134 common frames omitted
Suppressed: java.lang.UnsatisfiedLinkError: no netty_tcnative_linux_aarch_64_fedora in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
at java.base/java.lang.ClassLoader.loadLibrary(Unknown Source)
and
Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_tcnative_aarch_64.so
at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:186)
... 134 common frames omitted
Suppressed: java.lang.UnsatisfiedLinkError: no netty_tcnative_aarch_64 in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
and
Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_tcnative.so
at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:186)
... 134 common frames omitted
Suppressed: java.lang.UnsatisfiedLinkError: no netty_tcnative in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
Problem seems to be in jar as there is no native library inside called:
META-INF/native/libnetty_tcnative_linux_aarch_64_fedora.so
or
META-INF/native/libnetty_tcnative_aarch_64.so
or
META-INF/native/libnetty_tcnative.so
Even if I downgrade to 2.0.47(meaning: before changes introduces in 2.0.48) the only linux-related native files are:
META-INF/native/libnetty_tcnative_linux_aarch_64.so
META-INF/native/libnetty_tcnative_linux_x86_64.so
But OpenSsl.loadTcNative() requires native libs to be called as in stacktraces above as there is this piece of code:
String staticLibName = "netty_tcnative";
// First, try loading the platform-specific library. Platform-specific
// libraries will be available if using a tcnative uber jar.
if ("linux".equals(os)) {
Set<String> classifiers = PlatformDependent.normalizedLinuxClassifiers();
for (String classifier : classifiers) {
libNames.add(staticLibName + "_" + os + '_' + arch + "_" + classifier);
}
// generic arch-dependent library
libNames.add(staticLibName + "_" + os + '_' + arch);
// Fedora SSL lib so naming (libssl.so.10 vs libssl.so.1.0.0).
// note: should already be included from the classifiers but if not, we use this as an
// additional fallback option here
libNames.add(staticLibName + "_" + os + '_' + arch + "_fedora");
} else {
libNames.add(staticLibName + "_" + os + '_' + arch);
}
libNames.add(staticLibName + "_" + arch);
libNames.add(staticLibName);
This code is many years old, so this is not introduced recently, and this makes me wondering how this could work for anyone...
I've made a try on my mac(thus different native library name than on linux) and do this trick with reflection:
Method method = NativeLibraryLoader.class.getDeclaredMethod("getResource", String.class, ClassLoader.class);
method.setAccessible(true);
method.invoke(null,"META-INF/native/libnetty_tcnative_osx_aarch_64.jnilib",this.getClass().getClassLoader());
and lib is correctly loaded. But this will not make
SslContextBuilder.forClient()
...
.enableOcsp(true)
.sslProvider(SslProvider.OPENSSL)
.build();
working correctly as wrong names are hardcoded in above mentioned OpenSsl.loadTcNative().
Is this a bug in netty-tcnative-boringssl?
I don't find any corporate-grade solution, renaming libs is no-go for us. Any ideas?
// In gradle, we need to specify the classifier for netty-tcnative for every arch/os Combo.