Been playing around with DPS recently, and came across a bug in docker-java (here).
If a container is configured with CAP_ADD or CAP_DROP in lowercase, DPS fails with a nasty exception (seen below).
While waiting for docker-java to fix this bug, I figured it would be good if we add some defensive coding here on this side, so it won't fail all DNS lookups if there's a single bad container.
Let me know what you think!
17:56:16.572 [virtual-186646 ] WAR c.m.d.server.dns.RequestHandlerDefault l=101 m=solveAndSummarizeHandlingError status=solverFailed, currentSolverTime=12, totalTime=12, solver=SolverDocker, query=query=A:zoneminder.dj-server.lan, eClass=RuntimeException, msg=com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.github.dockerjava.api.model.Capability` from String "net_raw": not one of the values accepted for Enum class: [ALL, SYS_BOOT, DAC_OVERRIDE, NET_RAW, BLOCK_SUSPEND, FOWNER, IPC_LOCK, IPC_OWNER, SYS_PACCT, NET_BIND_SERVICE, WAKE_ALARM, FSETID, DAC_READ_SEARCH, SYS_CHROOT, AUDIT_READ, SYS_RAWIO, SYS_ADMIN, KILL, MAC_ADMIN, SYS_RESOURCE, CHOWN, PERFMON, SETPCAP, SYS_PTRACE, NET_ADMIN, SETFCAP, SYS_NICE, LINUX_IMMUTABLE, BPF, AUDIT_CONTROL, LEASE, AUDIT_WRITE, SYS_MODULE, MKNOD, SYSLOG, MAC_OVERRIDE, SYS_TIME, SETGID, SETUID, CHECKPOINT_RESTORE, SYS_TTY_CONFIG, NET_BROADCAST]
at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.github.dockerjava.api.command.InspectContainerResponse["HostConfig"]->com.github.dockerjava.api.model.HostConfig["CapDrop"]->java.lang.Object[][0])
java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.github.dockerjava.api.model.Capability` from String "net_raw": not one of the values accepted for Enum class: [ALL, SYS_BOOT, DAC_OVERRIDE, NET_RAW, BLOCK_SUSPEND, FOWNER, IPC_LOCK, IPC_OWNER, SYS_PACCT, NET_BIND_SERVICE, WAKE_ALARM, FSETID, DAC_READ_SEARCH, SYS_CHROOT, AUDIT_READ, SYS_RAWIO, SYS_ADMIN, KILL, MAC_ADMIN, SYS_RESOURCE, CHOWN, PERFMON, SETPCAP, SYS_PTRACE, NET_ADMIN, SETFCAP, SYS_NICE, LINUX_IMMUTABLE, BPF, AUDIT_CONTROL, LEASE, AUDIT_WRITE, SYS_MODULE, MKNOD, SYSLOG, MAC_OVERRIDE, SYS_TIME, SETGID, SETUID, CHECKPOINT_RESTORE, SYS_TTY_CONFIG, NET_BROADCAST]
at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.github.dockerjava.api.command.InspectContainerResponse["HostConfig"]->com.github.dockerjava.api.model.HostConfig["CapDrop"]->java.lang.Object[][0])
at com.github.dockerjava.core.DefaultInvocationBuilder.get(DefaultInvocationBuilder.java:77)
at com.github.dockerjava.core.exec.InspectContainerCmdExec.execute(InspectContainerCmdExec.java:31)
at com.github.dockerjava.core.exec.InspectContainerCmdExec.execute(InspectContainerCmdExec.java:13)
at com.github.dockerjava.core.exec.AbstrSyncDockerCmdExec.exec(AbstrSyncDockerCmdExec.java:21)
at com.github.dockerjava.core.command.AbstrDockerCmd.exec(AbstrDockerCmd.java:33)
at com.github.dockerjava.core.command.InspectContainerCmdImpl.exec(InspectContainerCmdImpl.java:51)
at com.mageddo.dnsproxyserver.docker.dataprovider.ContainerFacadeDefault.inspect(ContainerFacadeDefault.java:48)
at com.mageddo.dnsproxyserver.solver.docker.dataprovider.ContainerDAODefault.lambda$findActiveContainersMatching$0(ContainerDAODefault.java:31)
at java.base@21.0.2/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base@21.0.2/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base@21.0.2/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base@21.0.2/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base@21.0.2/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
at java.base@21.0.2/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base@21.0.2/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
at java.base@21.0.2/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
at java.base@21.0.2/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
at com.mageddo.dnsproxyserver.solver.docker.dataprovider.ContainerDAODefault.findActiveContainersMatching(ContainerDAODefault.java:34)
at com.mageddo.dnsproxyserver.solver.docker.application.ContainerSolvingService.findBestMatch(ContainerSolvingService.java:39)
at com.mageddo.dnsproxyserver.solver.SolverDocker.lambda$handle$0(SolverDocker.java:40)
at com.mageddo.dnsproxyserver.solver.HostnameMatcher.match(HostnameMatcher.java:22)
at com.mageddo.dnsproxyserver.solver.SolverDocker.handle(SolverDocker.java:39)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveAndSummarize(RequestHandlerDefault.java:115)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveAndSummarizeHandlingError(RequestHandlerDefault.java:99)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solve(RequestHandlerDefault.java:82)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveFixingCacheTTL(RequestHandlerDefault.java:73)
at com.mageddo.dnsproxyserver.solver.SolverCache.calculateValueWithoutLocks(SolverCache.java:70)
at com.mageddo.dnsproxyserver.solver.SolverCache.handleRes(SolverCache.java:51)
at com.mageddo.dnsproxyserver.solver.SolverCache.handle(SolverCache.java:40)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveCaching(RequestHandlerDefault.java:66)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.handle(RequestHandlerDefault.java:54)
at com.mageddo.dnsserver.UDPServer.handle(UDPServer.java:55)
at com.mageddo.dnsserver.UDPServer.lambda$start0$0(UDPServer.java:43)
at java.base@21.0.2/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base@21.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base@21.0.2/java.lang.Thread.runWith(Thread.java:1596)
at java.base@21.0.2/java.lang.VirtualThread.run(VirtualThread.java:309)
at java.base@21.0.2/java.lang.VirtualThread$VThreadContinuation$1.run(VirtualThread.java:190)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.github.dockerjava.api.model.Capability` from String "net_raw": not one of the values accepted for Enum class: [ALL, SYS_BOOT, DAC_OVERRIDE, NET_RAW, BLOCK_SUSPEND, FOWNER, IPC_LOCK, IPC_OWNER, SYS_PACCT, NET_BIND_SERVICE, WAKE_ALARM, FSETID, DAC_READ_SEARCH, SYS_CHROOT, AUDIT_READ, SYS_RAWIO, SYS_ADMIN, KILL, MAC_ADMIN, SYS_RESOURCE, CHOWN, PERFMON, SETPCAP, SYS_PTRACE, NET_ADMIN, SETFCAP, SYS_NICE, LINUX_IMMUTABLE, BPF, AUDIT_CONTROL, LEASE, AUDIT_WRITE, SYS_MODULE, MKNOD, SYSLOG, MAC_OVERRIDE, SYS_TIME, SETGID, SETUID, CHECKPOINT_RESTORE, SYS_TTY_CONFIG, NET_BROADCAST]
at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.github.dockerjava.api.command.InspectContainerResponse["HostConfig"]->com.github.dockerjava.api.model.HostConfig["CapDrop"]->java.lang.Object[][0])
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1958)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:1245)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer._deserializeAltString(EnumDeserializer.java:447)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer._fromString(EnumDeserializer.java:304)
at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:273)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:218)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:310)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4881)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3035)
at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:3499)
at com.github.dockerjava.core.DockerObjectDeserializer.deserialize(DockerClientConfig.java:132)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4905)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3893)
at com.github.dockerjava.core.DefaultInvocationBuilder.get(DefaultInvocationBuilder.java:75)
... 37 common frames omitted
17:56:16.572 [virtual-186646 ] WAR c.m.d.server.dns.RequestHandlerDefault l=56 m=handle status=solverFailed, totalTime=13, eClass=NullPointerException, msg=null
java.lang.NullPointerException: null
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solve(RequestHandlerDefault.java:83)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveFixingCacheTTL(RequestHandlerDefault.java:73)
at com.mageddo.dnsproxyserver.solver.SolverCache.calculateValueWithoutLocks(SolverCache.java:70)
at com.mageddo.dnsproxyserver.solver.SolverCache.handleRes(SolverCache.java:51)
at com.mageddo.dnsproxyserver.solver.SolverCache.handle(SolverCache.java:40)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.solveCaching(RequestHandlerDefault.java:66)
at com.mageddo.dnsproxyserver.server.dns.RequestHandlerDefault.handle(RequestHandlerDefault.java:54)
at com.mageddo.dnsserver.UDPServer.handle(UDPServer.java:55)
at com.mageddo.dnsserver.UDPServer.lambda$start0$0(UDPServer.java:43)
at java.base@21.0.2/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base@21.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base@21.0.2/java.lang.Thread.runWith(Thread.java:1596)
at java.base@21.0.2/java.lang.VirtualThread.run(VirtualThread.java:309)
at java.base@21.0.2/java.lang.VirtualThread$VThreadContinuation$1.run(VirtualThread.java:190)
Been playing around with DPS recently, and came across a bug in
docker-java
(here).If a container is configured with
CAP_ADD
orCAP_DROP
in lowercase, DPS fails with a nasty exception (seen below).While waiting for
docker-java
to fix this bug, I figured it would be good if we add some defensive coding here on this side, so it won't fail all DNS lookups if there's a single bad container.Let me know what you think!