You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2023/05/11 14:42:44 UTC
[camel-quarkus] branch main updated: Snmp: cover snmp v3 for POLL operation #4881
This is an automated email from the ASF dual-hosted git repository.
ppalaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 56e63f6242 Snmp: cover snmp v3 for POLL operation #4881
56e63f6242 is described below
commit 56e63f62424d7221eb8af6da0546277d88acb774
Author: JiriOndrusek <on...@gmail.com>
AuthorDate: Thu May 4 17:25:28 2023 +0200
Snmp: cover snmp v3 for POLL operation #4881
---
.../quarkus/component/snmp/it/SnmpResource.java | 38 ++++++++++
.../camel/quarkus/component/snmp/it/SnmpRoute.java | 40 +----------
.../camel/quarkus/component/snmp/it/SnmpTest.java | 82 +++++++++-------------
.../component/snmp/it/SnmpTestResource.java | 51 ++++++++++----
4 files changed, 108 insertions(+), 103 deletions(-)
diff --git a/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpResource.java b/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpResource.java
index f76f9c1d13..3a0475e6c7 100644
--- a/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpResource.java
+++ b/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpResource.java
@@ -28,8 +28,11 @@ import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.snmp.SnmpMessage;
import org.eclipse.microprofile.config.inject.ConfigProperty;
@@ -59,6 +62,9 @@ public class SnmpResource {
@Named("snmpTrapResults")
Map<String, Deque<SnmpMessage>> snmpResults;
+ @Inject
+ ConsumerTemplate consumerTemplate;
+
@Inject
ProducerTemplate producerTemplate;
@@ -87,6 +93,9 @@ public class SnmpResource {
String response = pdu.stream()
.flatMap(m -> m.getSnmpMessage().getVariableBindings().stream())
+ //snmp may add null oid to the result - because responder supports v3
+ // (see https://camel.apache.org/components/3.20.x/snmp-component.html#_the_result_of_a_poll)
+ .filter(vb -> !"Null".equals(vb.getVariable().toString()))
.map(vb -> vb.getVariable().toString())
.collect(Collectors.joining(","));
@@ -106,6 +115,35 @@ public class SnmpResource {
return Response.ok().build();
}
+ @Path("/poll/{version}")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response poll(@PathParam("version") int version,
+ @QueryParam("user") String user,
+ @QueryParam("securityLevel") String securityLevel,
+ String oid) {
+ String url = String.format("snmp:%s?protocol=udp&snmpVersion=%d&type=POLL&oids=%s", snmpListenAddress, version, oid);
+ if (user != null) {
+ url = url + "&securityName=" + user;
+ }
+ if (securityLevel != null) {
+ url = url + "&securityLevel=" + securityLevel;
+ }
+
+ //Even if routeBuilder is preferred instead of consumerTemplate, consumerTemplete can be used in a case, when the component uses polling consumers by default.
+ // In this case:
+ // - only polling consumer is used by the SNMP component
+ // - usage of the consumerTemplate reduces a lot of requests between SNMP providers significantly, thus making the tests more stable.
+ Exchange e = consumerTemplate.receive(url);
+
+ String result = e.getIn().getBody(SnmpMessage.class).getSnmpMessage().getVariableBindings().stream()
+ //snmp may add null oid to the result - because responder supports v3
+ // (see https://camel.apache.org/components/3.20.x/snmp-component.html#_the_result_of_a_poll)
+ .filter(vb -> !"Null".equals(vb.getVariable().toString()))
+ .map(v -> v.getVariable().toString()).collect(Collectors.joining(","));
+ return Response.ok(result).build();
+ }
+
@Path("/results/{from}")
@POST
@Produces(MediaType.TEXT_PLAIN)
diff --git a/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpRoute.java b/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpRoute.java
index d6fb2f64f9..8fe4149ece 100644
--- a/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpRoute.java
+++ b/integration-tests-jvm/snmp/src/main/java/org/apache/camel/quarkus/component/snmp/it/SnmpRoute.java
@@ -28,7 +28,6 @@ import jakarta.inject.Singleton;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.snmp.SnmpMessage;
import org.eclipse.microprofile.config.inject.ConfigProperty;
-import org.snmp4j.mp.SnmpConstants;
@ApplicationScoped
public class SnmpRoute extends RouteBuilder {
@@ -39,12 +38,9 @@ public class SnmpRoute extends RouteBuilder {
@ConfigProperty(name = TRAP_V0_PORT)
int trap0Port;
- @ConfigProperty(name = "SnmpRoute_trap_v1")
+ @ConfigProperty(name = TRAP_V1_PORT)
int trap1Port;
- @ConfigProperty(name = "snmpListenAddress")
- String snmpListenAddress;
-
@Inject
@Named("snmpTrapResults")
Map<String, Deque<SnmpMessage>> snmpResults;
@@ -58,33 +54,6 @@ public class SnmpRoute extends RouteBuilder {
//TRAP consumer snmpVersion=1
from("snmp:0.0.0.0:" + trap1Port + "?protocol=udp&type=TRAP&snmpVersion=1")
.process(e -> snmpResults.get("v1_trap").add(e.getIn().getBody(SnmpMessage.class)));
-
- //POLL consumer 2 oids, snmpVersion=0
- from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=0&type=POLL&oids=" +
- SnmpConstants.sysLocation + "," + SnmpConstants.sysContact)
- .process(e -> snmpResults.get("v0_poll2oids").add(e.getIn().getBody(SnmpMessage.class)));
- //POLL consumer 2 oids, snmpVersion=1
- from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=1&type=POLL&oids=" +
- SnmpConstants.sysLocation + "," + SnmpConstants.sysContact)
- .process(e -> snmpResults.get("v1_poll2oids").add(e.getIn().getBody(SnmpMessage.class)));
-
- // POLL consumer starting with dot snmpVersion=0
- from("snmp://" + snmpListenAddress
- + "?protocol=udp&snmpVersion=0&type=POLL&oids=.1.3.6.1.4.1.6527.3.1.2.21.2.1.50")
- .process(e -> snmpResults.get("v0_pollStartingDot").add(e.getIn().getBody(SnmpMessage.class)));
- //POLL consumer startingWith dot snmpVersion=1
- from("snmp://" + snmpListenAddress
- + "?protocol=udp&snmpVersion=1&type=POLL&oids=.1.3.6.1.4.1.6527.3.1.2.21.2.1.50")
- .process(e -> snmpResults.get("v1_pollStartingDot").add(e.getIn().getBody(SnmpMessage.class)));
-
- //POLL consumer snmpVersion=0
- from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=0&type=POLL&oids="
- + SnmpConstants.sysDescr)
- .process(e -> snmpResults.get("v0_poll").add(e.getIn().getBody(SnmpMessage.class)));
- //POLL consumer snmpVersion=1
- from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=1&type=POLL&oids="
- + SnmpConstants.sysDescr)
- .process(e -> snmpResults.get("v1_poll").add(e.getIn().getBody(SnmpMessage.class)));
}
static class Producers {
@@ -95,13 +64,6 @@ public class SnmpRoute extends RouteBuilder {
Map<String, Deque<SnmpMessage>> map = new ConcurrentHashMap<>();
map.put("v0_trap", new ConcurrentLinkedDeque<>());
map.put("v1_trap", new ConcurrentLinkedDeque<>());
- map.put("v0_poll", new ConcurrentLinkedDeque<>());
- map.put("v1_poll", new ConcurrentLinkedDeque<>());
- map.put("v3_poll", new ConcurrentLinkedDeque<>());
- map.put("v0_pollStartingDot", new ConcurrentLinkedDeque<>());
- map.put("v1_pollStartingDot", new ConcurrentLinkedDeque<>());
- map.put("v0_poll2oids", new ConcurrentLinkedDeque<>());
- map.put("v1_poll2oids", new ConcurrentLinkedDeque<>());
return map;
}
}
diff --git a/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTest.java b/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTest.java
index fac78e768c..1220e8aa44 100644
--- a/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTest.java
+++ b/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTest.java
@@ -22,9 +22,11 @@ import java.util.stream.Stream;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
+import io.restassured.specification.RequestSpecification;
import org.hamcrest.Matchers;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
@@ -76,38 +78,44 @@ class SnmpTest {
}
@ParameterizedTest
- @MethodSource("supportedVersions")
+ @ValueSource(ints = { 0, 1, 3 })
public void testPoll(int version) throws Exception {
- String resultsName = "v" + version + "_poll";
+ RequestSpecification rs = RestAssured.given()
+ .body(POLL_OID.toString());
- await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
- String result = RestAssured.given()
- .body(SnmpConstants.sysDescr.toString())
- .post("/snmp/results/" + resultsName)
- .then()
- .statusCode(200)
- .extract().body().asString();
+ if (version == 3) {
+ rs.queryParam("user", "test")
+ .queryParam("securityLevel", 1);
+ }
- return result
- .startsWith("My POLL Printer - response #1,My POLL Printer - response #2,My POLL Printer - response #3");
- });
+ rs.post("/snmp/poll/" + version)
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("My POLL Printer - response #1"));
}
@ParameterizedTest
@MethodSource("supportedVersions")
- public void testPollStartingDot(int version) throws Exception {
- String resultsName = "v" + version + "_pollStartingDot";
-
- await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
- String result = RestAssured.given()
- .body(DOT_OID.toString())
- .post("/snmp/results/" + resultsName)
- .then()
- .statusCode(200)
- .extract().body().asString();
+ public void testPollWith2OIDs(int version) throws Exception {
+ RestAssured.given()
+ .body(TWO_OIDS_A + "," + TWO_OIDS_B)
+ .post("/snmp/poll/" + version)
+ .then()
+ .statusCode(200)
+ .body(Matchers.anyOf(
+ Matchers.equalTo("My 2 OIDs A Printer - response #1,My 2 OIDs B Printer - response #1"),
+ Matchers.equalTo("My 2 OIDs B Printer - response #1,My 2 OIDs A Printer - response #1")));
+ }
- return result.startsWith("My DOT Printer - response #1,My DOT Printer - response #2,My DOT Printer - response #3");
- });
+ @ParameterizedTest
+ @MethodSource("supportedVersions")
+ public void testPollStartingDot(int version) throws Exception {
+ RestAssured.given()
+ .body("." + DOT_OID)
+ .post("/snmp/poll/" + version)
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("My DOT Printer - response #1"));
}
@ParameterizedTest
@@ -134,30 +142,4 @@ class SnmpTest {
.body(Matchers.endsWith("2,My GET_NEXT Printer - response #3"));
}
- @ParameterizedTest
- @MethodSource("supportedVersions")
- public void testPollWith2OIDs(int version) throws Exception {
- String resultsName = "v" + version + "_poll2oids";
-
- await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
- String resultOid1 = RestAssured.given()
- .body(TWO_OIDS_A.toString())
- .post("/snmp/results/" + resultsName)
- .then()
- .statusCode(200)
- .extract().body().asString();
- String resultOid2 = RestAssured.given()
- .body(TWO_OIDS_B.toString())
- .post("/snmp/results/" + resultsName)
- .then()
- .statusCode(200)
- .extract().body().asString();
-
- return resultOid1.startsWith(
- "My 2 OIDs A Printer - response #1,My 2 OIDs A Printer - response #2,My 2 OIDs A Printer - response #3") &&
- resultOid2.startsWith(
- "My 2 OIDs B Printer - response #1,My 2 OIDs B Printer - response #2,My 2 OIDs B Printer - response #3");
- });
-
- }
}
diff --git a/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTestResource.java b/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTestResource.java
index 769c7824b6..c487d4acdc 100644
--- a/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTestResource.java
+++ b/integration-tests-jvm/snmp/src/test/java/org/apache/camel/quarkus/component/snmp/it/SnmpTestResource.java
@@ -34,8 +34,16 @@ import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
+import org.snmp4j.mp.CounterSupport;
+import org.snmp4j.mp.DefaultCounterListener;
+import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.mp.StatusInformation;
+import org.snmp4j.security.AuthSHA;
+import org.snmp4j.security.SecurityModels;
+import org.snmp4j.security.SecurityProtocols;
+import org.snmp4j.security.USM;
+import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
@@ -51,6 +59,7 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
@Override
public Map<String, String> start() {
+ SecurityProtocols.getInstance().addDefaultProtocols();
DefaultUdpTransportMapping udpTransportMapping;
try {
udpTransportMapping = new DefaultUdpTransportMapping(new UdpAddress(LOCAL_ADDRESS));
@@ -59,6 +68,20 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
TestCommandResponder responder = new TestCommandResponder(snmpResponder);
snmpResponder.addCommandResponder(responder);
+ SecurityModels respSecModels = new SecurityModels() {
+ };
+
+ CounterSupport.getInstance().addCounterListener(new DefaultCounterListener());
+ MPv3 mpv3CR = (MPv3) snmpResponder.getMessageDispatcher().getMessageProcessingModel(MPv3.ID);
+ mpv3CR.setLocalEngineID(MPv3.createLocalEngineID(new OctetString("responder")));
+ respSecModels.addSecurityModel(new USM(SecurityProtocols.getInstance(),
+ new OctetString(mpv3CR.getLocalEngineID()), 0));
+ mpv3CR.setSecurityModels(respSecModels);
+
+ snmpResponder.getUSM().addUser(
+ new UsmUser(new OctetString("test"), AuthSHA.ID, new OctetString("changeit"),
+ AuthSHA.ID, new OctetString("changeit")));
+
snmpResponder.listen();
} catch (Exception e) {
throw new RuntimeException(e);
@@ -75,6 +98,7 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
@Override
public void stop() {
+ SecurityProtocols.setSecurityProtocols(null);
if (snmpResponder != null) {
try {
snmpResponder.close();
@@ -115,7 +139,7 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
int numberOfSent = counts.getOrDefault(key, 0);
try {
- PDU response = makeResponse(++numberOfSent, SnmpConstants.version1, vbs);
+ PDU response = makeResponse(pdu, ++numberOfSent, SnmpConstants.version1, vbs);
if (response != null) {
response.setRequestID(pdu.getRequestID());
commandResponder.getMessageDispatcher().returnResponsePdu(
@@ -130,18 +154,18 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
counts.put(key, numberOfSent);
}
- private PDU makeResponse(int counter, int version, Vector<? extends VariableBinding> vbs) {
- PDU responsePDU = new PDU();
+ private PDU makeResponse(PDU originalPDU, int counter, int version, Vector<? extends VariableBinding> vbs) {
+ PDU responsePDU = (PDU) originalPDU.clone();
responsePDU.setType(PDU.RESPONSE);
responsePDU.setErrorStatus(PDU.noError);
responsePDU.setErrorIndex(0);
if (vbs.isEmpty()) {
- VariableBinding vb = generateResponseBinding(counter, SnmpTest.PRODUCE_PDU_OID);
+ VariableBinding vb = generateResponseBinding(counter, version, SnmpTest.PRODUCE_PDU_OID);
if (vb != null) {
responsePDU.add(vb);
}
} else {
- vbs.stream().forEach(vb -> responsePDU.add(generateResponseBinding(counter, vb.getOid())));
+ vbs.stream().forEach(vb -> responsePDU.add(generateResponseBinding(counter, version, vb.getOid())));
}
if (responsePDU.getVariableBindings().isEmpty()) {
return null;
@@ -149,7 +173,7 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
return responsePDU;
}
- private VariableBinding generateResponseBinding(int counter, OID oid) {
+ private VariableBinding generateResponseBinding(int counter, int version, OID oid) {
//get next test
if (SnmpTest.GET_NEXT_OID.equals(oid)) {
//if counter < 2 return the same oid
@@ -166,11 +190,12 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
}
if (SnmpTest.POLL_OID.equals(oid)) {
- if (counter < 4) {
- return new VariableBinding(SnmpTest.POLL_OID,
- new OctetString("My POLL Printer - response #" + counter));
+ if (counter > 1) {
+ throw new RuntimeException(
+ String.format("Not expected request #%d for poll of version %d.", counter, version));
}
-
+ return new VariableBinding(SnmpTest.POLL_OID,
+ new OctetString("My POLL Printer - response #" + counter));
}
if (SnmpTest.PRODUCE_PDU_OID.equals(oid)) {
@@ -195,10 +220,8 @@ public class SnmpTestResource implements QuarkusTestResourceLifecycleManager {
}
if (SnmpTest.DOT_OID.equals(oid)) {
- if (counter < 4) {
- return new VariableBinding(SnmpTest.DOT_OID,
- new OctetString("My DOT Printer - response #" + counter));
- }
+ return new VariableBinding(SnmpTest.DOT_OID,
+ new OctetString("My DOT Printer - response #" + counter));
}
return null;