REST API PUT is broken. GET and UI works fine


(Matt P) #1

Pretty simple test installation from tarball (3.0.0).

Have a beats and syslog input manually created/configured in UI. They work fine.

Started testing the REST API for the purpose of auto-provisioning those inputs on deployment.

GET works fine and returns the two configured inputs.

Trying to update one of the inputs with PUT fails both from CURL and the graylog api-browser (swagger).

PUT gives me a 400. Details of the PUT are below. I pulled the input ID from a GET.

url
http://127.0.0.1:10000/api/system/inputs/5c7ff0657da9870a2cff84de

payload

{
  "title" : "rsyslog",
  "global" : true,
  "content_pack" : null,
  "type" : "org.graylog2.inputs.syslog.tcp.SyslogTCPInput",
  "attributes" : {
    "recv_buffer_size" : 1048576,
    "tcp_keepalive" : false,
    "use_null_delimiter" : false,
    "number_worker_threads" : 2,
    "tls_client_auth_cert_file" : "/opt/graylog/certs/client.crt",
    "force_rdns" : false,
    "bind_address" : "0.0.0.0",
    "tls_cert_file" : "/opt/graylog/certs/server.crt",
    "store_full_message" : false,
    "expand_structured_data" : false,
    "port" : 10003,
    "tls_key_file" : "/opt/graylog/certs/server.key",
    "tls_enable" : true,
    "tls_key_password" : "",
    "max_message_size" : 2097152,
    "tls_client_auth" : "required",
    "override_source" : null,
    "allow_override_date" : true
  },
  "static_fields" : { },
  "node" : null
}

Response:

{
  "type": "ApiError",
  "message": "Can not construct instance of org.graylog2.rest.models.system.inputs.requests.InputCreateRequest, problem: Null configuration\n at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@6b438322; line: 28, column: 1]"
}

These inputs are working. The inputs were created and are editable in the graylog UI (I thought it used the REST API under the hood?).

Graylog is working as far as I can tell (UI comes up, I can login, graylog receive logs on the inputs, I can search, etc). There are no errors in the server.log (until I load swagger).

When I load up the swagger (api-browser) interface there are a ton of exceptions in the server.log file. They all look (I think) like the following but for various different classnames.

# grep -F '[Reflections] could not get type for name' /opt/graylog/log/server.log
2019-03-13T19:55:14.415Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.responses.CollectorList from any class loader
2019-03-13T19:55:14.424Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.system.CollectorSystemConfiguration$Builder from any class loader
2019-03-13T19:55:14.429Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorInput from any class loader
2019-03-13T19:55:14.437Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.CollectorActions from any class loader
2019-03-13T19:55:14.439Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.CollectorUpload$Builder from any class loader
2019-03-13T19:55:14.445Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorConfigurationSnippet from any class loader
2019-03-13T19:55:14.452Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.CollectorConfigurationEtagInvalidation from any class loader
2019-03-13T19:55:14.454Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.responses.CollectorSummary from any class loader
2019-03-13T19:55:14.456Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorConfigurationSummary from any class loader
2019-03-13T19:55:14.462Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.CollectorUpload from any class loader
2019-03-13T19:55:14.466Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.system.CollectorSystemConfiguration from any class loader
2019-03-13T19:55:14.468Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorNodeDetailsSummary from any class loader
2019-03-13T19:55:14.470Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.requests.CollectorRegistrationRequest from any class loader
2019-03-13T19:55:14.481Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.CollectorNodeDetails from any class loader
2019-03-13T19:55:14.482Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorStatus from any class loader
2019-03-13T19:55:14.483Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorConfiguration$Builder from any class loader
2019-03-13T19:55:14.484Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.CollectorService from any class loader
2019-03-13T19:55:14.485Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.responses.CollectorSnippetListResponse from any class loader
2019-03-13T19:55:14.486Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.responses.CollectorOutputListResponse from any class loader
2019-03-13T19:55:14.492Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.responses.CollectorConfigurationListResponse from any class loader
2019-03-13T19:55:14.498Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.Collector from any class loader
2019-03-13T19:55:14.500Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.responses.CollectorRegistrationConfiguration from any class loader
2019-03-13T19:55:14.502Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorMetrics from any class loader
2019-03-13T19:55:14.507Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorConfiguration from any class loader
2019-03-13T19:55:14.509Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorAction from any class loader
2019-03-13T19:55:14.514Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorLogFile from any class loader
2019-03-13T19:55:14.515Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.CollectorStatusList from any class loader
2019-03-13T19:55:14.516Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.responses.CollectorRegistrationResponse from any class loader
2019-03-13T19:55:14.518Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.responses.CollectorInputListResponse from any class loader
2019-03-13T19:55:14.520Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.collectors.rest.models.responses.CollectorRegistrationAction from any class loader
2019-03-13T19:55:14.523Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorOutput from any class loader

A full(er) stack trace for a single exception.

2019-03-13T19:55:14.523Z WARN  [Reflections] could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorOutput from any class loader
org.reflections.ReflectionsException: could not get type for name org.graylog.plugins.collector.configurations.rest.models.CollectorOutput
	at org.reflections.ReflectionUtils.forName(ReflectionUtils.java:390) [graylog.jar:?]
	at org.reflections.Reflections.expandSuperTypes(Reflections.java:381) [graylog.jar:?]
	at org.reflections.Reflections.<init>(Reflections.java:126) [graylog.jar:?]
	at org.reflections.Reflections.<init>(Reflections.java:168) [graylog.jar:?]
	at org.graylog2.shared.rest.documentation.generator.Generator.<init>(Generator.java:99) [graylog.jar:?]
	at org.graylog2.shared.rest.resources.documentation.DocumentationResource.<init>(DocumentationResource.java:82) [graylog.jar:?]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [?:1.8.0_201]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0_201]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0_201]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) [?:1.8.0_201]
	at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1375) [graylog.jar:?]
	at org.jvnet.hk2.internal.ClazzCreator.createMe(ClazzCreator.java:272) [graylog.jar:?]
	at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:366) [graylog.jar:?]
	at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:487) [graylog.jar:?]
	at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162) [graylog.jar:?]
	at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2022) [graylog.jar:?]
	at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:774) [graylog.jar:?]
	at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:737) [graylog.jar:?]
	at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:707) [graylog.jar:?]
	at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:172) [graylog.jar:?]
	at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:284) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:109) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:92) [graylog.jar:?]
	at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:61) [graylog.jar:?]
	at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197) [graylog.jar:?]
	at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:318) [graylog.jar:?]
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [graylog.jar:?]
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [graylog.jar:?]
	at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [graylog.jar:?]
	at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [graylog.jar:?]
	at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [graylog.jar:?]
	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [graylog.jar:?]
	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [graylog.jar:?]
	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [graylog.jar:?]
	at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384) [graylog.jar:?]
	at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224) [graylog.jar:?]
	at com.codahale.metrics.InstrumentedExecutorService$InstrumentedRunnable.run(InstrumentedExecutorService.java:181) [graylog.jar:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_201]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_201]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_201]
Caused by: java.lang.ClassNotFoundException: org.graylog.plugins.collector.configurations.rest.models.CollectorOutput
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[?:1.8.0_201]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_201]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[?:1.8.0_201]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_201]
	at org.reflections.ReflectionUtils.forName(ReflectionUtils.java:388) ~[graylog.jar:?]
	... 43 more

So a classpath issue it appears to be.

My install is obviously a bit non-standard (for graylog) as I am using the tarball, installing in opt and using non-standard config paths. The fact the rest of graylog seems to be working normally makes me suspicious that there is something hard-coded or not using the same configuration conventions as the rest of the graylog codebase.

Relevant excerpt from my systemd unit:

[Service]
Type=simple
Environment=JAVA_HOME=/opt/java/current
WorkingDirectory=/opt/graylog/current

ExecStart=/opt/java/current/bin/java  -Xms1g -Xmx1g -XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow  -jar  -Dlog4j.configurationFile=file:///opt/graylog/log4j2.xml -Djava.library.path=/opt/graylog/current/lib/sigar /opt/graylog/current/graylog.jar server  --configfile /opt/graylog/graylog.conf --no-pid-file

Any ideas?


(dennis) #2

Hey @md218676 and welcome to the community!

Thanks for asking this. You are assuming (correctly) that you can use the same format for PUT and GET. Unfortunately this is not the case (one of the legacies we are dragging around). The format for a PUT is:

{
  title: String,
  type: String,
  global: Boolean,
  configuration: Map<String, Object>,
  node: String
}

So for your example it would like this:

{
  "title": "rsyslog",
  "type": "org.graylog2.inputs.syslog.tcp.SyslogTCPInput",
  "global": true,
  "configuration": {
    "recv_buffer_size" : 1048576,
    "tcp_keepalive" : false,
    "use_null_delimiter" : false,
    "number_worker_threads" : 2,
    "tls_client_auth_cert_file" : "/opt/graylog/certs/client.crt",
    "force_rdns" : false,
    "bind_address" : "0.0.0.0",
    "tls_cert_file" : "/opt/graylog/certs/server.crt",
    "store_full_message" : false,
    "expand_structured_data" : false,
    "port" : 10003,
    "tls_key_file" : "/opt/graylog/certs/server.key",
    "tls_enable" : true,
    "tls_key_password" : "",
    "max_message_size" : 2097152,
    "tls_client_auth" : "required",
    "override_source" : null,
    "allow_override_date" : true
  },
  "node": null
}

Regarding the swagger exceptions you see: Is swagger working for you? We are investigating the exception, for afaics it should not impact the functionality of swagger.

I hope this helps!


(Matt P) #3

Thanks for clarifying. I’m excited there is an easy fix and sorry if I missed that in the docs…a few minutes later I remember I couldn’t find the docs for the REST API and took the swagger interface to be self-documenting or something. Did I miss them somewhere? Link would be awesome so I don’t have to keep asking here. :slight_smile:

I guess the same thing is true for POST as PUT?

Other than described (the PUT issue and the exceptions in the logs), swagger seems to work.