Setting SSL keystore at runtime in Apache Felix - osgi

I have a service that loads a keystore, but how do I tell Apache Felix to load this at runtime? Jetty 9.4.20 has support to reload the sslContext with SslContextFactory.reload() but how do I get the ServerConnector from felix?
I also tried an approach where I change the bundle properties with ManagedServiceFactory however that fails starting the server. See the example
public void updateSslContext(ManagedServiceFactory mf) throws exception {
Dictionary<String, Object> newProps =new Hashtable<>();
newProps.put("org.apache.felix.https.keystore", "keystore.jks");
newProps.put("org.apache.felix.https.keystore.password", "password");
newProps.put("org.apache.felix.https.keystore.key.password", "1234");
newProps.put("org.apache.felix.https.enable", true);
mf.updated("org.apache.felix.http", newProps);
}
It fails with the following error
[INFO] Started Jetty 9.4.20.v20190813 at port(s) HTTP:8080 HTTPS:8443 on context path / [minThreads=8,maxThreads=200,acceptors=1,selectors=2]
[INFO] Apachde Felix Http Whiteboard Service started
...
...
...
ERROR 20191006 21:23:35 bid#4 - Failed to start Connector: ServerConnector#49d09625{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} (java.io.IOException: Failed to bind to 0.0.0.0/0.0.0.0:8080)
info 20191006 21:23:35 bid#4 - org.eclipse.jetty.server.Server :: jetty-9.4.20.v20190813; built: 2019-08-13T21:28:18.144Z; git: 84700530e645e812b336747464d6fbbf370c9a20; jvm 1.8.0_151-b12
info 20191006 21:23:35 bid#4 - org.eclipse.jetty.server.handler.ContextHandler :: Started o.e.j.s.ServletContextHandler#3ea91c64{/,null,AVAILABLE}
ERROR 20191006 21:23:35 bid#4 - Failed to start Connector: ServerConnector#27be6cdc{SSL,[ssl, http/1.1]}{0.0.0.0:8443} (java.io.IOException: Failed to bind to 0.0.0.0/0.0.0.0:8443)
info 20191006 21:23:35 bid#4 - Stopped Jetty.
ERROR 20191006 21:23:35 bid#4 - Jetty stopped (no connectors available)
ERROR 20191006 21:23:35 bid#4 - Exception while initializing Jetty. (java.lang.NullPointerException)
I would prefer to use SslContextFactory.reload() so that the server doesn't restart completely.

Related

Spring Boot 3.0.0-M5 with native-image result in runtime error: "Check your application's dependencies for a supported servlet web server."

My Spring Cloud 2022.0.0-M5 + Spring Boot 3.0.0-M5 webmvc application works as a normal JVM application but fails when compiled to native:
c.e.m.w.proxy.server.MyServerKt : Starting MyServerKt using Java 17.0.4.1 on acc1dd6cfd4d with PID 1 (/workspace/myserver.MyServerKt started by cnb in /workspace)
c.e.m.w.proxy.server.MyServerKt : The following 1 profile is active: "prod"
o.s.c.c.c.ConfigServerConfigDataLoader : Fetching config from server at : http://configserver:8080
o.s.c.c.c.ConfigServerConfigDataLoader : Located environment: name=application, profiles=[prod], label=null, version=4563ba0531478bdc637b677819dedcebf7bd2bc3, state=null
w.s.c.ServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server
o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
Action:
Check your application's dependencies for a supported servlet web server.
Check the configured web application type.
Do you have any idea where should I start investigating?
All I see in the AOT build log that Tomcat is on the classpath:
[creator] Executing native-image -H:+StaticExecutableWithDynamicLibC --enable-url-protocols=http --initialize-at-run-time=io.netty ... -cp ... :/workspace/BOOT-INF/lib/tomcat-embed-core-10.0.23.jar: ...
AOT building environment info:
[creator] Version info: 'GraalVM 22.2.0 Java 17 CE'
[creator] Java version info: '17.0.4.1+1-LTS'
[creator] C compiler: gcc (linux, x86_64, 7.5.0)

Caused by: java.io.IOException: Invalid keystore format

I have a JBoss 7.4.0 installation running in domain mode on a RHEL 7 platform. The JDK version is java version "15.0.2" 2021-01-19
Java(TM) SE Runtime Environment (build 15.0.2+7-27)
I am using the Jboss documentation How to Configure Server Security, specifically section 2.5: Configuring SSL/TLS for the legacy core management authentication mechanism. I am setting up Two-Way SSL/TLS.
I create a keystore, generate key pairs, export and import certificates. The storetype is JCEKS. (I have also tried using PCKS12 and JKS, same issue)
When I try to start the JBoss server I see the following error:
06:47:41,216 INFO [org.jboss.modules] (main) JBoss Modules version 1.11.0.Final-redhat-00001
06:47:41,498 INFO [org.jboss.threads] (main) JBoss Threads version 2.4.0.Final-redhat-00001
06:47:41,514 INFO [org.jboss.as.process.Host Controller.status] (main) WFLYPC0018: Starting process 'Host Controller'
[Host Controller] 06:47:41,982 INFO [org.jboss.modules] (main) JBoss Modules version 1.11.0.Final-redhat-00001
...
[Host Controller] 06:47:43,848 WARN [org.jboss.as.domain.management.security] (MSC service thread 1-1) WFLYDM0111: Keystore /u01/redhat/jboss/domain_74/domain/configuration/application.keystore not found, it will be auto generated on first use with a self signed certificate for host localhost
[Host Controller] 06:47:43,851 INFO [org.jboss.remoting] (MSC service thread 1-3) JBoss Remoting version 5.0.20.SP1-redhat-00001
[Host Controller] 06:47:43,852 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service org.wildfly.core.management.security.realm.CertificateRealm.key-manager: org.jboss.msc.service.StartException in service org.wildfly.core.management.security.realm.CertificateRealm.key-manager: Failed to start service
[Host Controller] at org.jboss.msc#1.4.12.Final-redhat-00001//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1731)
...
[Host Controller] Caused by: java.lang.IllegalStateException: org.jboss.msc.service.StartException in anonymous service: WFLYDM0018: Unable to start service
...
[Host Controller] Caused by: java.io.IOException: Invalid keystore format
So my understanding is the issue is with the keystore format, yet if I use another keystore format I get the same issue.
And, when I run the following command I get success:
./keytool -list -keystore $EAP_HOME/vault/h1vault.jceks
Enter keystore password:
Keystore type: JCEKS
Keystore provider: SunJCE
Your keystore contains 3 entries
h1server_alias, Sep 20, 2022, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 58:58:36:82:EE:B5:88:BB:AF:59:F6:17:F2:9B:D3:29:D6:CC:DD:02:04:E5:3B:50:8A:70:AB:5C:85:59:DD:25
h1vault, Sep 20, 2022, SecretKeyEntry,
host2_alias, Sep 20, 2022, trustedCertEntry,
Certificate fingerprint (SHA-256): 62:07:76:CB:B7:B8:9C:89:6D:36:82:8B:5B:8A:E9:7E:8E:6A:23:8E:51:56:03:B9:F9:98:D3:DA:D4:53:B5:57
I would expect this command to fail if the keystore format was incorrect.
I have read all sorts of threads and so on about this but cannot find an answer.
Appreciate if anyone can suggest possible solutions.
Thanks

Spring boot applications sometimes fails to "bind properties" on high load

So every morning we're starting around ~30 spring-boot microservices.
Sometimes one of them is failing to start up.
Running Spring boot 2.1.5.
Today it was with the following error:
2021-11-15 02:18:32.269 INFO 12258023 --- [main] dk.yx.oiltanks.OilTanksApplication : The following profiles are active: prod
2021-11-15 02:19:49.406 ERROR 12258023 --- [main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'spring.mvc.servlet' to org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Servlet:
Reason: Failed to bind properties under 'spring.mvc.servlet' to org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Servlet
Action:
Update your application's configuration
Is there any configuration parameters to increase "bind properties" time ?
All we did to get this application running again was starting it with the normal command.
Configuration file:
endpoints.cors.allowed-methods=GET
endpoints.cors.allowed-origins=*
eureka.client.serviceUrl.defaultZone=**HOSTNAME**:13499/eureka/
eureka.instance.healthCheckUrl=https\://${eureka.hostname}\:${server.port}/actuator/health
eureka.instance.homePageUrl=https\://${eureka.hostname}\:${server.port}/
eureka.instance.hostname=**HOSTNAME**
eureka.instance.nonSecurePortEnabled=false
eureka.instance.securePort=${server.port}
eureka.instance.securePortEnabled=true
eureka.instance.statusPageUrl=https\://${eureka.hostname}\:${server.port}/actuator/info
feign.client.config.default.connectTimeout=1600000
feign.client.config.default.readTimeout=1600000
logging.file.max-history=50
logging.file.max-size=100MB
logging.file=application.log
logging.level.dk.yx.yxdb=INFO
logging.level.dk.yx=INFO
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type.descriptor.sql=INFO
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=INFO
logging.level.org.springframework.web=INFO
management.endpoints.web.cors.allowed-methods=GET
management.endpoints.web.cors.allowed-origins=*
multipart.maxFileSize=-1
multipart.maxRequestSize=-1
pring.mvc.async.request-timeout=300000
server.connection-timeout=999999
server.http.port=3517
server.port=13517
server.ssl.key-alias=yx_dk
server.ssl.key-store-password=**PASSWORD**
server.ssl.key-store-type=PKCS12
server.ssl.key-store=/QOpenSys/etc/ssl/wildcard_yx_dk.p12
spring.application.name=OIL_TANK_SERVICE
spring.datasource.driver-class-name=com.ibm.as400.access.AS400JDBCDriver
spring.datasource.hibernate.default_schema=NHODATA
spring.datasource.hikari.connectionTimeout=90000
spring.datasource.hikari.idleTimeout=120000
spring.datasource.hikari.minimumIdle=3
spring.datasource.password=unreadable
spring.datasource.url=jdbc\:as400\:bmw/;naming\=system;libraries\=NHODATA,QTEMP,YXDTA24,ICEBREAK,NHOPRG,SYSAFD,QGPL,QIDU,OTCONLINE,SMS,YXDB,YXAPP,SMSDB;date format\=eur;time format\=eur;
spring.datasource.username=sqlread
spring.http.multipart.enabled=true
spring.http.multipart.maxFileSize=-1
spring.http.multipart.maxRequestSize=-1
spring.jpa.database-platform=org.hibernate.dialect.DB2Dialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false
spring.mvc.async.request-timeout=999999
spring.output.ansi.enabled=DETECT
spring.profiles.active=prod
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
yx.nps.ip=**IP**
yx.nps.username=**password**
yx.project.description=Service for handling all oiltank related stuff.

Jetty-9 HTTP/2 in OSGi container. Cannot load a HttpFieldPreEncoder implementation for HTTP/2 over ServiceLoader

recently I'm trying to call a REST-service, published over Apache-CXF. Everything is embedded in an Equinox 3.11.0 with Jetty 9.4.1.
Container starts Jetty, configured for HTTP/2:
[main] INFO org.eclipse.jetty.server.Server - jetty-9.4.1.v20170120
[main] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler#6f89f665{/,jar:file:///C:/workspaces/com.ebase.eox/cnf/generated/fw/org.eclipse.osgi/12/0/bundleFile!/,AVAILABLE}
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector#187eb9a8{HTTP/1.1,[http/1.1, h2c]}{0.0.0.0:8080}
[main] INFO org.eclipse.jetty.util.ssl.SslContextFactory - x509=X509#1517f633(jetty,h=[],w=[]) for SslContextFactory#4fe01803(bundleentry://12.fwk1276261147/jettyhome/etc/keystore,bundleentry://12.fwk1276261147/jettyhome/etc/keystore)
[main] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector#3015db78{SSL,[ssl, alpn, h2, http/1.1]}{0.0.0.0:8443}
Wenn i call a REST-Service over https/ssl i get an error:
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at org.eclipse.jetty.http.PreEncodedHttpField.putTo(PreEncodedHttpField.java:119)
at org.eclipse.jetty.http2.hpack.HpackEncoder.encode(HpackEncoder.java:289)
at org.eclipse.jetty.http2.hpack.HpackEncoder.encode(HpackEncoder.java:179)
at org.eclipse.jetty.http2.generator.HeadersGenerator.generateHeaders(HeadersGenerator.java:72)
at org.eclipse.jetty.http2.generator.HeadersGenerator.generate(HeadersGenerator.java:56)
at org.eclipse.jetty.http2.generator.Generator.control(Generator.java:80)
at org.eclipse.jetty.http2.HTTP2Session$ControlEntry.generate(HTTP2Session.java:1143)
at org.eclipse.jetty.http2.HTTP2Flusher.process(HTTP2Flusher.java:168)
at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
at org.eclipse.jetty.http2.HTTP2Session.frame(HTTP2Session.java:676)
at org.eclipse.jetty.http2.HTTP2Session.frames(HTTP2Session.java:648)
at org.eclipse.jetty.http2.HTTP2Stream.headers(HTTP2Stream.java:91)
at org.eclipse.jetty.http2.server.HttpTransportOverHTTP2.commit(HttpTransportOverHTTP2.java:185)
at org.eclipse.jetty.http2.server.HttpTransportOverHTTP2.send(HttpTransportOverHTTP2.java:111)
at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:687)
at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:743)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:234)
at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:218)
... 61 more
It seems (i have proven it), that PreEncodedHttpField cannot load all Implementations of HttpFieldPreEncoder over ServiceLoader.
Iterator<HttpFieldPreEncoder> iter = ServiceLoader.load(HttpFieldPreEncoder.class,PreEncodedHttpField.class.getClassLoader()).iterator();
ServiceLoader sees only a Http1FieldPreEncoder, which is in the same Bundle as PreEncodedHttpField, so observable for a BundleClassLoader. This Implementation is registerd under Index "0".
In my case, it should be used an HTTP/2 Implementation HpackFieldPreEncoder, which bundle in http2-hpack, but not visible for ServiceLoader
Is there any workaround to make this second implementation visible for PreEncodedHttpField to avoid my Exception?
Thank you

Using Local File in Spring Yarn application

i need deploy the war file on yarn container for that I am using Spring batch for creating a yarn application that uses embedded jetty server to deploy a war file,when i use a customhandle for handling the request it works fine the application get deployed on yarn but when i use war file as a handler it doesnt works i get a error
java.io.FileNotFoundException: /root/jettywebapps/webapps/Login.war
but the file is actually present at the given location i am stuck how to access the war file from the yarn container
#OnContainerStart
public void publicVoidNoArgsMethod() throws Exception {
String jetty_home="/root/jettywebapps";
Server server = new Server(9090);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/Login");
webapp.setWar(jetty_home+"/webapps/Login.war");
server.setHandler(webapp);
server.start();
server.join();
}
Here is the Stack Trace
2015-04-17 06:05:14.972] boot - 26920 INFO [main] --- ContainerLauncherRunner: Running YarnContainer with parameters []
[2015-04-17 06:05:14.972] boot - 26920 INFO [main] --- ContainerLauncherRunner: Container requested that we wait state, setting up latch
[2015-04-17 06:05:14.975] boot - 26920 INFO [main] --- DefaultYarnContainer: Processing 1 #YarnComponent handlers
[2015-04-17 06:05:15.038] boot - 26920 INFO [main] --- Server: jetty-8.0.4.v20111024
[2015-04-17 06:05:15.080] boot - 26920 WARN [main] --- WebInfConfiguration: Web application not found /root/jettywebapps/webapps/Login.war
[2015-04-17 06:05:15.081] boot - 26920 WARN [main] --- WebAppContext: Failed startup of context o.e.j.w.WebAppContext{/Login,null},/root/jettywebapps/webapps/Login.war
java.io.FileNotFoundException: /root/jettywebapps/webapps/Login.war
at org.eclipse.jetty.webapp.WebInfConfiguration.unpack(WebInfConfiguration.java:479)
at org.eclipse.jetty.webapp.WebInfConfiguration.preConfigure(WebInfConfiguration.java:52)
at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:416)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:452)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:89)
at org.eclipse.jetty.server.Server.doStart(Server.java:262)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at hello.container.HelloPojo.publicVoidNoArgsMethod(HelloPojo.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:112)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:129)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:49)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:342)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:131)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:330)
at org.springframework.yarn.support.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126)
at org.springframework.yarn.container.ContainerMethodInvokerHelper.processInternal(ContainerMethodInvokerHelper.java:229)
at org.springframework.yarn.container.ContainerMethodInvokerHelper.process(ContainerMethodInvokerHelper.java:115)
at org.springframework.yarn.container.MethodInvokingYarnContainerRuntimeProcessor.process(MethodInvokingYarnContainerRuntimeProcessor.java:51)
at org.springframework.yarn.container.ContainerHandler.handle(ContainerHandler.java:99)
at org.springframework.yarn.container.DefaultYarnContainer.getContainerHandlerResults(DefaultYarnContainer.java:174)
at org.springframework.yarn.container.DefaultYarnContainer.runInternal(DefaultYarnContainer.java:77)
please help
Thanks
the container could fetch local files or hdfs files using following code:
Configuration conf = new Configuration();
FileSystem localFS = FileSystem.get(URI.create("file://localhost"), conf);
OutputStream outATXT = localFS.create(new Path("/home/walterchen/a.txt"));
or
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create("hdfs://localhost:9000"), conf);
OutputStream out = fs.create(new Path("/home/a.txt"));

Resources