Graylog2 / graylog2-server

Free and open log management
https://www.graylog.org
Other
7.4k stars 1.06k forks source link

Data Node: failure to upload CA is poorly handled #16832

Closed thll closed 1 year ago

thll commented 1 year ago

Expected Behavior

When I'm uploading a CA and the uploaded file doesn't satisfy requirements, I should get an error message describing that the file is invalid and ideally what is wrong with it.

Probably the key and/or intermediate cert are missing from the file, but the requirements of how exactly the CA file should look like are not documented.

Current Behavior

Trying to upload a CA shows a fraction of a stack trace and then renders the UI unusable. The response I extracted from the browser dev tools looks like this:

<html>
    <head>
        <title>Grizzly 2.4.4</title>
        <style>
            <!--div.header {
                font-family: Tahoma,Arial,sans-serif;
                color: white;
                background-color: #003300;
                font-size: 22px;
                -moz-border-radius-topleft: 10px;
                border-top-left-radius: 10px;
                -moz-border-radius-topright: 10px;
                border-top-right-radius: 10px;
                padding-left: 5px
            }

            div.body {
                font-family: Tahoma,Arial,sans-serif;
                color: black;
                background-color: #FFFFCC;
                font-size: 16px;
                padding-top: 10px;
                padding-bottom: 10px;
                padding-left: 10px
            }

            div.footer {
                font-family: Tahoma,Arial,sans-serif;
                color: white;
                background-color: #666633;
                font-size: 14px;
                -moz-border-radius-bottomleft: 10px;
                border-bottom-left-radius: 10px;
                -moz-border-radius-bottomright: 10px;
                border-bottom-right-radius: 10px;
                padding-left: 5px
            }

            BODY {
                font-family: Tahoma,Arial,sans-serif;
                color: black;
                background-color: white;
            }

            B {
                font-family: Tahoma,Arial,sans-serif;
                color: black;
            }

            A {
                color : black;
            }

            HR {
                color : #999966;
            }

            --></style>
    </head>
    <body>
        <div class="header">Internal Server Error</div>
        <div class="body">
            <b>org.graylog.security.certutil.ca.exceptions.CACreationException: Failed to create a Certificate Authority</b>
            <pre>1: org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer$ResponseWriter.rethrow(GrizzlyHttpContainer.java:297)
     2: org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer$ResponseWriter.failure(GrizzlyHttpContainer.java:279)
     3: org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:438)
     4: org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
     5: org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
     6: org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
     7: org.glassfish.jersey.internal.Errors.process(Errors.java:292)
     8: org.glassfish.jersey.internal.Errors.process(Errors.java:274)
     9: org.glassfish.jersey.internal.Errors.process(Errors.java:244)
    10: org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
        ... 8 more</pre>
            <b>Root Cause: java.util.NoSuchElementException: No value present</b>
            <pre>1: java.base/java.util.Optional.orElseThrow(Unknown Source)
     2: org.graylog.security.certutil.ca.PemCaReader.readCA(PemCaReader.java:115)
     3: org.graylog.security.certutil.CaServiceImpl.upload(CaServiceImpl.java:121)
     4: org.graylog2.bootstrap.preflight.web.resources.PreflightResource.uploadCA(PreflightResource.java:114)
     5: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     6: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     7: java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     8: java.base/java.lang.reflect.Method.invoke(Unknown Source)
     9: org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
    10: org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:134)
        ... 21 more</pre>
            Please see the log for more detail.
        </div>
        <div class="footer">Grizzly 2.4.4</div>
    </body>
</html>

Steps to Reproduce (for bugs)

Create a local CA with mkcert: CAROOT=$(pwd) mkcert localhost. Upload the resulting rootCA.pem as CA in the preflight UI.

I debugged a bit and figured out that the server expects the private key to be present in the .pem file as well. So I added it. But then it turns out we are expecting the key in the older PKCS#1 format, while my key was in the newer PKCS#8. After converting and combining it with the cert like this:

cat rootCA.pem > rootCA-combined.pem && openssl rsa -in rootCA-key.pem -traditional >> rootCA-combined.pem

I got past the first error but ended up getting the following new error:

server log excerpt datanode-graylog-1-1 | 2023-10-06 07:22:46,720 ERROR: org.graylog.security.certutil.ca.PemCaReader - Could not find certificate: Uninitialized keystore datanode-graylog-1-1 | java.security.KeyStoreException: Uninitialized keystore datanode-graylog-1-1 | at java.security.KeyStore.setKeyEntry(Unknown Source) ~[?:?] datanode-graylog-1-1 | at org.graylog.security.certutil.ca.PemCaReader.addCert(PemCaReader.java:101) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog.security.certutil.ca.PemCaReader.lambda$readCA$2(PemCaReader.java:120) ~[graylog.jar:?] datanode-graylog-1-1 | at java.util.Optional.ifPresent(Unknown Source) ~[?:?] datanode-graylog-1-1 | at org.graylog.security.certutil.ca.PemCaReader.readCA(PemCaReader.java:119) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog.security.certutil.CaServiceImpl.upload(CaServiceImpl.java:121) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog2.bootstrap.preflight.web.resources.PreflightResource.uploadCA(PreflightResource.java:114) ~[graylog.jar:?] datanode-graylog-1-1 | at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] datanode-graylog-1-1 | at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at java.lang.reflect.Method.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52) ~[graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:134) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:177) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:81) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:292) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:274) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:244) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:356) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:200) [graylog.jar:?] datanode-graylog-1-1 | at com.codahale.metrics.InstrumentedExecutorService$InstrumentedRunnable.run(InstrumentedExecutorService.java:180) [graylog.jar:?] datanode-graylog-1-1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:?] datanode-graylog-1-1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:?] datanode-graylog-1-1 | at java.lang.Thread.run(Unknown Source) [?:?] datanode-graylog-1-1 | 2023-10-06 07:22:46,724 ERROR: org.graylog.security.certutil.CaServiceImpl - Could not write CA: Failed to save keystore to Mongo collection for node GRAYLOG CA datanode-graylog-1-1 | org.graylog.security.certutil.ca.exceptions.KeyStoreStorageException: Failed to save keystore to Mongo collection for node GRAYLOG CA datanode-graylog-1-1 | at org.graylog.security.certutil.keystore.storage.KeystoreMongoStorage.writeKeyStore(KeystoreMongoStorage.java:59) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog.security.certutil.keystore.storage.SmartKeystoreStorage.writeKeyStore(SmartKeystoreStorage.java:47) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog.security.certutil.CaServiceImpl.upload(CaServiceImpl.java:127) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog2.bootstrap.preflight.web.resources.PreflightResource.uploadCA(PreflightResource.java:114) ~[graylog.jar:?] datanode-graylog-1-1 | at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] datanode-graylog-1-1 | at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at java.lang.reflect.Method.invoke(Unknown Source) ~[?:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52) ~[graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:134) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:177) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:81) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:292) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:274) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:244) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:356) [graylog.jar:?] datanode-graylog-1-1 | at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:200) [graylog.jar:?] datanode-graylog-1-1 | at com.codahale.metrics.InstrumentedExecutorService$InstrumentedRunnable.run(InstrumentedExecutorService.java:180) [graylog.jar:?] datanode-graylog-1-1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:?] datanode-graylog-1-1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:?] datanode-graylog-1-1 | at java.lang.Thread.run(Unknown Source) [?:?] datanode-graylog-1-1 | Caused by: java.security.KeyStoreException: Uninitialized keystore datanode-graylog-1-1 | at java.security.KeyStore.aliases(Unknown Source) ~[?:?] datanode-graylog-1-1 | at org.graylog.security.certutil.keystore.storage.SinglePasswordKeystoreContentMover.moveContents(SinglePasswordKeystoreContentMover.java:39) ~[graylog.jar:?] datanode-graylog-1-1 | at org.graylog.security.certutil.keystore.storage.KeystoreMongoStorage.writeKeyStore(KeystoreMongoStorage.java:53) ~[graylog.jar:?] datanode-graylog-1-1 | ... 30 more

Your Environment

dennisoelkers commented 1 year ago

Fixed in #16844.