You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by tp...@apache.org on 2022/07/04 14:44:19 UTC
[nifi] branch main updated: NIFI-9916: ListenTrapSNMP USM parsing refactor.
This is an automated email from the ASF dual-hosted git repository.
tpalfy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 685088a59c NIFI-9916: ListenTrapSNMP USM parsing refactor.
685088a59c is described below
commit 685088a59c034d415c820d7724a2e16dfa4ac6a2
Author: Lehel <Le...@hotmail.com>
AuthorDate: Wed May 11 00:42:30 2022 +0200
NIFI-9916: ListenTrapSNMP USM parsing refactor.
This closes #6034.
Signed-off-by: Tamas Palfy <tp...@apache.org>
---
.../src/main/resources/META-INF/NOTICE | 23 ++++
.../nifi-snmp-bundle/nifi-snmp-processors/pom.xml | 6 +
.../snmp/configuration/V1TrapConfiguration.java | 22 ++--
.../java/org/apache/nifi/snmp/dto/UserDetails.java | 58 ---------
.../snmp/operations/SNMPTrapReceiverHandler.java | 40 +------
.../nifi/snmp/processors/ListenTrapSNMP.java | 129 +++++++++++++++++++--
.../properties/V3SecurityProperties.java | 6 +-
.../apache/nifi/snmp/utils/JsonFileUsmReader.java | 49 ++++++++
.../org/apache/nifi/snmp/utils/JsonUsmReader.java | 41 +++++++
.../nifi/snmp/utils/SecurityNamesUsmReader.java | 42 +++++++
.../org/apache/nifi/snmp/utils/UsmJsonParser.java | 47 ++++++++
.../java/org/apache/nifi/snmp/utils/UsmReader.java | 26 +++++
.../nifi/snmp/utils/UsmUserDeserializer.java | 82 +++++++++++++
.../additionalDetails.html | 5 +-
.../configuration/V1TrapConfigurationTest.java | 30 ++---
.../testrunners/SNMPV3TestRunnerFactory.java | 2 +-
.../operations/SNMPTrapReceiverHandlerTest.java | 68 +++--------
.../nifi/snmp/utils/JsonFileUsmReaderTest.java | 50 ++++++++
.../apache/nifi/snmp/utils/JsonUsmReaderTest.java | 63 ++++++++++
.../nifi/snmp/utils/JsonUsmReaderTestBase.java | 52 +++++++++
.../snmp/utils/SecurityNamesUsmReaderTest.java | 53 +++++++++
.../resources/{users.json => invalid_users.json} | 6 +-
.../src/test/resources/users.json | 4 +-
23 files changed, 710 insertions(+), 194 deletions(-)
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-nar/src/main/resources/META-INF/NOTICE b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-nar/src/main/resources/META-INF/NOTICE
index 8dde122c7b..1ba904292a 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-nar/src/main/resources/META-INF/NOTICE
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-nar/src/main/resources/META-INF/NOTICE
@@ -22,3 +22,26 @@ The following binary components are provided under the Apache Software License v
This product includes software from the Spring Framework,
under the Apache License 2.0 (see: StringUtils.containsWhitespace())
+
+ (ASLv2) Jackson JSON processor
+ The following NOTICE information applies:
+ # Jackson JSON processor
+
+ Jackson is a high-performance, Free/Open Source JSON processing library.
+ It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+ been in development since 2007.
+ It is currently developed by a community of developers, as well as supported
+ commercially by FasterXML.com.
+
+ ## Licensing
+
+ Jackson core and extension components may licensed under different licenses.
+ To find the details that apply to this artifact see the accompanying LICENSE file.
+ For more information, including possible other licensing options, contact
+ FasterXML.com (http://fasterxml.com).
+
+ ## Credits
+
+ A list of contributors may be found from CREDITS file, which is included
+ in some artifacts (usually source distributions); but is always available
+ from the source code management (SCM) system project uses.
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/pom.xml b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/pom.xml
index 81d95301e2..0cc6a3c0bc 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/pom.xml
@@ -55,6 +55,12 @@ language governing permissions and limitations under the License. -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-json-utils</artifactId>
+ <version>1.17.0-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/V1TrapConfiguration.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/V1TrapConfiguration.java
index 896b0d9728..1e77fabdb0 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/V1TrapConfiguration.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/V1TrapConfiguration.java
@@ -20,6 +20,14 @@ import org.apache.nifi.util.StringUtils;
public class V1TrapConfiguration {
+ static final String ENTERPRISE_OID_MUST_BE_SPECIFIED = "Enterprise OID must be specified.";
+ static final String AGENT_ADDRESS_MUST_BE_SPECIFIED = "Agent address must be specified.";
+ public static final String GENERIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_6 = "Generic Trap Type must be between 0 and 6.";
+ public static final String GENERIC_TRAP_TYPE_IS_NOT_A_NUMBER = "Generic Trap Type is not a number.";
+ public static final String SPECIFIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_2147483647 = "Specific Trap Type must be between 0 and 2147483647.";
+ public static final String GENERIC_TRAP_TYPE_IS_6_ENTERPRISE_SPECIFIC_BUT_SPECIFIC_TRAP_TYPE_IS_NOT_PROVIDED = "Generic Trap Type is [6 - Enterprise Specific]" +
+ " but Specific Trap Type is not provided or not a number.";
+
private final String enterpriseOid;
private final String agentAddress;
private final String genericTrapType;
@@ -83,33 +91,31 @@ public class V1TrapConfiguration {
public V1TrapConfiguration build() {
if (StringUtils.isEmpty(enterpriseOid)) {
- throw new IllegalArgumentException("Enterprise OID must be specified.");
+ throw new IllegalArgumentException(ENTERPRISE_OID_MUST_BE_SPECIFIED);
}
if (StringUtils.isEmpty(agentAddress)) {
- throw new IllegalArgumentException("Agent address must be specified.");
+ throw new IllegalArgumentException(AGENT_ADDRESS_MUST_BE_SPECIFIED);
}
final int parsedGenericTrapType;
try {
parsedGenericTrapType = Integer.parseInt(genericTrapType);
if (parsedGenericTrapType < 0 || parsedGenericTrapType > 6) {
- throw new IllegalArgumentException("Generic Trap Type must be between 0 and 6.");
+ throw new IllegalArgumentException(GENERIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_6);
}
} catch (NumberFormatException e) {
- throw new IllegalArgumentException("Generic Trap Type is not a number.");
+ throw new IllegalArgumentException(GENERIC_TRAP_TYPE_IS_NOT_A_NUMBER);
}
if (parsedGenericTrapType == 6) {
try {
final int parsedSpecificTrapType = Integer.parseInt(specificTrapType);
if (parsedSpecificTrapType < 0) {
- throw new IllegalArgumentException("Specific Trap Type must be between 0 and 2147483647.");
+ throw new IllegalArgumentException(SPECIFIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_2147483647);
}
} catch (NumberFormatException e) {
- throw new IllegalArgumentException("Generic Trap Type is [6 - Enterprise Specific] but Specific Trap Type is not provided or not a number.");
+ throw new IllegalArgumentException(GENERIC_TRAP_TYPE_IS_6_ENTERPRISE_SPECIFIC_BUT_SPECIFIC_TRAP_TYPE_IS_NOT_PROVIDED);
}
- } else if (StringUtils.isNotEmpty(specificTrapType)) {
- throw new IllegalArgumentException("Invalid argument: Generic Trap Type is not [6 - Enterprise Specific] but Specific Trap Type is provided.");
}
return new V1TrapConfiguration(this);
}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/dto/UserDetails.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/dto/UserDetails.java
deleted file mode 100644
index 26cc9ff5b1..0000000000
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/dto/UserDetails.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.snmp.dto;
-
-public class UserDetails {
-
- private String securityName;
- private String authProtocol;
- private String authPassphrase;
- private String privProtocol;
- private String privPassphrase;
-
- public UserDetails() {
- }
-
- public UserDetails(final String securityName, final String authProtocol, final String authPassphrase,
- final String privProtocol, final String privPassphrase) {
- this.securityName = securityName;
- this.authProtocol = authProtocol;
- this.authPassphrase = authPassphrase;
- this.privProtocol = privProtocol;
- this.privPassphrase = privPassphrase;
- }
-
- public String getSecurityName() {
- return securityName;
- }
-
- public String getAuthProtocol() {
- return authProtocol;
- }
-
- public String getAuthPassphrase() {
- return authPassphrase;
- }
-
- public String getPrivProtocol() {
- return privProtocol;
- }
-
- public String getPrivPassphrase() {
- return privPassphrase;
- }
-}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandler.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandler.java
index 53b1ff2eda..85cec04281 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandler.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandler.java
@@ -16,16 +16,11 @@
*/
package org.apache.nifi.snmp.operations;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
-import org.apache.nifi.snmp.dto.UserDetails;
import org.apache.nifi.snmp.factory.core.SNMPManagerFactory;
-import org.apache.nifi.snmp.utils.SNMPUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.Snmp;
@@ -38,24 +33,21 @@ import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OctetString;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
-import java.util.Scanner;
public class SNMPTrapReceiverHandler {
private static final Logger logger = LoggerFactory.getLogger(SNMPTrapReceiverHandler.class);
private final SNMPConfiguration configuration;
- private final String usmUsersFilePath;
+ private final List<UsmUser> usmUsers;
private Snmp snmpManager;
private boolean isStarted;
- public SNMPTrapReceiverHandler(final SNMPConfiguration configuration, final String usmUsersFilePath) {
+ public SNMPTrapReceiverHandler(final SNMPConfiguration configuration, final List<UsmUser> usmUsers) {
this.configuration = configuration;
- this.usmUsersFilePath = usmUsersFilePath;
+ this.usmUsers = usmUsers;
snmpManager = new SNMPManagerFactory().createSnmpManagerInstance(configuration);
}
@@ -89,34 +81,10 @@ public class SNMPTrapReceiverHandler {
if (configuration.getVersion() == SnmpConstants.version3) {
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
-
- try (Scanner scanner = new Scanner(new File(usmUsersFilePath))) {
- final String content = scanner.useDelimiter("\\Z").next();
- final ObjectMapper mapper = new ObjectMapper();
- final List<UserDetails> userDetails = mapper.readValue(content, new TypeReference<List<UserDetails>>() {
- });
- userDetails.stream()
- .map(this::convertToUsmUser)
- .forEach(user -> snmpManager.getUSM().addUser(user));
-
- } catch (FileNotFoundException e) {
- throw new ProcessException("USM user file not found, please check the file path and file permissions.", e);
- } catch (JsonProcessingException e) {
- throw new ProcessException("Could not parse USM user file, please check the processor details for examples.", e);
- }
+ usmUsers.forEach(user -> snmpManager.getUSM().addUser(user));
}
}
- private UsmUser convertToUsmUser(final UserDetails user) {
- return new UsmUser(
- new OctetString(user.getSecurityName()),
- SNMPUtils.getAuth(user.getAuthProtocol()),
- new OctetString(user.getAuthPassphrase()),
- SNMPUtils.getPriv(user.getPrivProtocol()),
- new OctetString(user.getPrivPassphrase())
- );
- }
-
// Visible for testing.
void setSnmpManager(final Snmp snmpManager) {
this.snmpManager = snmpManager;
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/ListenTrapSNMP.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/ListenTrapSNMP.java
index b36ff7d226..26931bb458 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/ListenTrapSNMP.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/ListenTrapSNMP.java
@@ -23,23 +23,37 @@ import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnScheduled;
import org.apache.nifi.annotation.lifecycle.OnStopped;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.ConfigVerificationResult;
import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.resource.ResourceCardinality;
+import org.apache.nifi.components.resource.ResourceType;
import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.AbstractSessionFactoryProcessor;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.VerifiableProcessor;
+import org.apache.nifi.processor.util.JsonValidator;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.operations.SNMPTrapReceiverHandler;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
+import org.apache.nifi.snmp.utils.JsonFileUsmReader;
+import org.apache.nifi.snmp.utils.JsonUsmReader;
import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.apache.nifi.snmp.utils.SecurityNamesUsmReader;
+import org.apache.nifi.snmp.utils.UsmReader;
+import org.snmp4j.security.UsmUser;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -54,25 +68,60 @@ import java.util.Set;
@WritesAttribute(attribute = SNMPUtils.SNMP_PROP_PREFIX + "*", description = "Attributes retrieved from the SNMP response. It may include:"
+ " snmp$errorIndex, snmp$errorStatus, snmp$errorStatusText, snmp$nonRepeaters, snmp$requestID, snmp$type, snmp$variableBindings")
@RequiresInstanceClassLoading
-public class ListenTrapSNMP extends AbstractSessionFactoryProcessor {
+public class ListenTrapSNMP extends AbstractSessionFactoryProcessor implements VerifiableProcessor {
+
+ public static final AllowableValue USM_JSON_FILE_PATH = new AllowableValue("usm-json-file-path", "Json File Path", "The path of the JSON file containing the USM users");
+ public static final AllowableValue USM_JSON_CONTENT = new AllowableValue("usm-json-content", "Json Content", "The JSON containing the USM users");
+ public static final AllowableValue USM_SECURITY_NAMES = new AllowableValue("usm-security-names", "Security Names", "In case of noAuthNoPriv security level" +
+ " - the list of security names separated by commas");
public static final PropertyDescriptor SNMP_MANAGER_PORT = new PropertyDescriptor.Builder()
.name("snmp-manager-port")
.displayName("SNMP Manager Port")
.description("The port where the SNMP Manager listens to the incoming traps.")
.required(true)
- .defaultValue("0")
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
- public static final PropertyDescriptor SNMP_USM_USERS_FILE_PATH = new PropertyDescriptor.Builder()
+ public static final PropertyDescriptor SNMP_USM_USER_SOURCE = new PropertyDescriptor.Builder()
+ .name("snmp-usm-users-source")
+ .displayName("USM Users Source")
+ .description("The ways to provide USM User data")
+ .required(true)
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .allowableValues(USM_JSON_CONTENT, USM_JSON_FILE_PATH, USM_SECURITY_NAMES)
+ .dependsOn(BasicProperties.SNMP_VERSION, BasicProperties.SNMP_V3)
+ .build();
+
+ public static final PropertyDescriptor SNMP_USM_USERS_JSON_FILE_PATH = new PropertyDescriptor.Builder()
.name("snmp-usm-users-file-path")
- .displayName("SNMP Users File Path")
+ .displayName("USM Users JSON File Path")
.description("The path of the json file containing the user credentials for SNMPv3. Check Usage for more details.")
- .required(true)
- .defaultValue("")
+ .required(false)
+ .identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE)
.dependsOn(BasicProperties.SNMP_VERSION, BasicProperties.SNMP_V3)
- .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .dependsOn(SNMP_USM_USER_SOURCE, USM_JSON_FILE_PATH)
+ .build();
+
+ public static final PropertyDescriptor SNMP_USM_USERS_JSON = new PropertyDescriptor.Builder()
+ .name("snmp-usm-users-json-content")
+ .displayName("USM Users JSON content")
+ .description("The JSON containing the user credentials for SNMPv3. Check Usage for more details.")
+ .required(false)
+ .dependsOn(BasicProperties.SNMP_VERSION, BasicProperties.SNMP_V3)
+ .dependsOn(SNMP_USM_USER_SOURCE, USM_JSON_CONTENT)
+ .addValidator(JsonValidator.INSTANCE)
+ .build();
+
+ public static final PropertyDescriptor SNMP_USM_SECURITY_NAMES = new PropertyDescriptor.Builder()
+ .name("snmp-usm-security-names")
+ .displayName("SNMP Users Security Names")
+ .description("Security names listed separated by commas in SNMPv3. Check Usage for more details.")
+ .required(false)
+ .dependsOn(BasicProperties.SNMP_VERSION, BasicProperties.SNMP_V3)
+ .dependsOn(V3SecurityProperties.SNMP_SECURITY_LEVEL, V3SecurityProperties.NO_AUTH_NO_PRIV)
+ .dependsOn(SNMP_USM_USER_SOURCE, USM_SECURITY_NAMES)
+ .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.build();
public static final Relationship REL_SUCCESS = new Relationship.Builder()
@@ -90,7 +139,10 @@ public class ListenTrapSNMP extends AbstractSessionFactoryProcessor {
BasicProperties.SNMP_VERSION,
BasicProperties.SNMP_COMMUNITY,
V3SecurityProperties.SNMP_SECURITY_LEVEL,
- SNMP_USM_USERS_FILE_PATH
+ SNMP_USM_USER_SOURCE,
+ SNMP_USM_USERS_JSON_FILE_PATH,
+ SNMP_USM_USERS_JSON,
+ SNMP_USM_SECURITY_NAMES
));
private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
@@ -99,22 +151,59 @@ public class ListenTrapSNMP extends AbstractSessionFactoryProcessor {
)));
private volatile SNMPTrapReceiverHandler snmpTrapReceiverHandler;
+ private volatile List<UsmUser> usmUsers;
+
+
+ @Override
+ public List<ConfigVerificationResult> verify(ProcessContext context, ComponentLog verificationLogger, Map<String, String> attributes) {
+ final List<ConfigVerificationResult> results = new ArrayList<>();
+
+ final String usmUserSource = context.getProperty(SNMP_USM_USER_SOURCE).getValue();
+
+ if (usmUserSource != null) {
+ final UsmReader usmReader = getUsmReader(context, usmUserSource);
+
+ try {
+ if (usmReader != null) {
+ usmReader.readUsm();
+ }
+ } catch (Exception e) {
+ results.add(new ConfigVerificationResult.Builder()
+ .verificationStepName("USM User processing")
+ .outcome(ConfigVerificationResult.Outcome.FAILED)
+ .explanation(e.getMessage() + " " + e.getCause().getMessage())
+ .build());
+ }
+ }
+ return results;
+ }
@OnScheduled
public void initSnmpManager(ProcessContext context) {
final int version = SNMPUtils.getVersion(context.getProperty(BasicProperties.SNMP_VERSION).getValue());
final int managerPort = context.getProperty(SNMP_MANAGER_PORT).asInteger();
- final String usmUsersFilePath = context.getProperty(SNMP_USM_USERS_FILE_PATH).getValue();
+ final String securityLevel = context.getProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL).getValue();
+
SNMPConfiguration configuration;
configuration = SNMPConfiguration.builder()
.setManagerPort(managerPort)
.setVersion(version)
- .setSecurityLevel(context.getProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL).getValue())
+ .setSecurityLevel(securityLevel)
.setCommunityString(context.getProperty(BasicProperties.SNMP_COMMUNITY).getValue())
.build();
- snmpTrapReceiverHandler = new SNMPTrapReceiverHandler(configuration, usmUsersFilePath);
+ final String usmUserSource = context.getProperty(SNMP_USM_USER_SOURCE).getValue();
+
+ if (usmUserSource != null) {
+ final UsmReader usmReader = getUsmReader(context, usmUserSource);
+ if (usmReader != null) {
+ usmUsers = usmReader.readUsm();
+ }
+
+ }
+
+ snmpTrapReceiverHandler = new SNMPTrapReceiverHandler(configuration, usmUsers);
}
@Override
@@ -122,6 +211,7 @@ public class ListenTrapSNMP extends AbstractSessionFactoryProcessor {
if (!snmpTrapReceiverHandler.isStarted()) {
snmpTrapReceiverHandler.createTrapReceiver(processSessionFactory, getLogger());
}
+ context.yield();
}
@OnStopped
@@ -140,4 +230,21 @@ public class ListenTrapSNMP extends AbstractSessionFactoryProcessor {
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return PROPERTY_DESCRIPTORS;
}
+
+ private UsmReader getUsmReader(ProcessContext context, String usmUserSource) {
+ final String usmUsersJsonFilePath = context.getProperty(SNMP_USM_USERS_JSON_FILE_PATH).getValue();
+ final String usmUsersJson = context.getProperty(SNMP_USM_USERS_JSON).getValue();
+ final String usmSecurityNames = context.getProperty(SNMP_USM_SECURITY_NAMES).getValue();
+
+ UsmReader usmReader = null;
+
+ if (USM_JSON_FILE_PATH.getValue().equals(usmUserSource)) {
+ usmReader = new JsonFileUsmReader(usmUsersJsonFilePath);
+ } else if (USM_JSON_CONTENT.getValue().equals(usmUserSource)) {
+ usmReader = new JsonUsmReader(usmUsersJson);
+ } else if (USM_SECURITY_NAMES.getValue().equals(usmUserSource)) {
+ usmReader = new SecurityNamesUsmReader(usmSecurityNames);
+ }
+ return usmReader;
+ }
}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/properties/V3SecurityProperties.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/properties/V3SecurityProperties.java
index 07688d7b15..412f75892a 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/properties/V3SecurityProperties.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/properties/V3SecurityProperties.java
@@ -36,11 +36,11 @@ public class V3SecurityProperties {
// SNMPv3 security levels
public static final AllowableValue NO_AUTH_NO_PRIV = new AllowableValue(SecurityLevel.noAuthNoPriv.name(), SecurityLevel.noAuthNoPriv.name(),
- "No authentication or encryption.");
+ "Communication without authentication and privacy.");
public static final AllowableValue AUTH_NO_PRIV = new AllowableValue(SecurityLevel.authNoPriv.name(), SecurityLevel.authNoPriv.name(),
- "Authentication without encryption.");
+ "Communication with authentication and without privacy.");
public static final AllowableValue AUTH_PRIV = new AllowableValue(SecurityLevel.authPriv.name(), SecurityLevel.authPriv.name(),
- "Authentication and encryption.");
+ "Communication with authentication and privacy.");
// SNMPv3 authentication protocols
public static final AllowableValue MD5 = new AllowableValue("MD5", "MD5",
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonFileUsmReader.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonFileUsmReader.java
new file mode 100644
index 0000000000..b0705cf2b9
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonFileUsmReader.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.snmp4j.security.UsmUser;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Scanner;
+
+public class JsonFileUsmReader implements UsmReader {
+
+ private final String usmUsersFilePath;
+
+ public JsonFileUsmReader(String usmUsersFilePath) {
+ this.usmUsersFilePath = usmUsersFilePath;
+ }
+
+ @Override
+ public List<UsmUser> readUsm() {
+ final List<UsmUser> userDetails;
+ try (Scanner scanner = new Scanner(new File(usmUsersFilePath))) {
+ final String content = scanner.useDelimiter("\\Z").next();
+ userDetails = UsmJsonParser.parse(content);
+ } catch (FileNotFoundException e) {
+ throw new ProcessException("USM user file not found, please check the file path and file permissions.", e);
+ } catch (JsonProcessingException e) {
+ throw new ProcessException("Could not parse USM user file, please check the processor details for examples.", e);
+ }
+ return userDetails;
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonUsmReader.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonUsmReader.java
new file mode 100644
index 0000000000..b23ccd99b9
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/JsonUsmReader.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.snmp4j.security.UsmUser;
+
+import java.util.List;
+
+public class JsonUsmReader implements UsmReader {
+
+ private final String usmUsersJson;
+
+ public JsonUsmReader(String usmUsersJson) {
+ this.usmUsersJson = usmUsersJson;
+ }
+
+ @Override
+ public List<UsmUser> readUsm() {
+ try {
+ return UsmJsonParser.parse(usmUsersJson);
+ } catch (JsonProcessingException e) {
+ throw new ProcessException("Could not parse USM user file, please check the processor details for examples.", e);
+ }
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReader.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReader.java
new file mode 100644
index 0000000000..f742f9abd4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReader.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.OctetString;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SecurityNamesUsmReader implements UsmReader {
+
+ private final String usmSecurityNames;
+
+ public SecurityNamesUsmReader(String usmSecurityNames) {
+ this.usmSecurityNames = usmSecurityNames;
+ }
+
+ @Override
+ public List<UsmUser> readUsm() {
+ return Arrays.stream(usmSecurityNames.trim().split(","))
+ .map(securityName -> new UsmUser(
+ new OctetString(securityName), null, null, null, null)
+ )
+ .collect(Collectors.toList());
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmJsonParser.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmJsonParser.java
new file mode 100644
index 0000000000..3b6c98442c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmJsonParser.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.snmp4j.security.UsmUser;
+
+import java.util.List;
+
+public class UsmJsonParser {
+
+ private UsmJsonParser() {
+ // Utility class, not to instantiate.
+ }
+
+ private static final ObjectMapper MAPPER;
+ private static final SimpleModule MODULE;
+
+ static {
+ MAPPER = new ObjectMapper();
+ MODULE = new SimpleModule();
+ MODULE.addDeserializer(UsmUser.class, new UsmUserDeserializer());
+ MAPPER.registerModule(MODULE);
+ }
+
+ static List<UsmUser> parse(final String json) throws JsonProcessingException {
+ return MAPPER.readValue(json, new TypeReference<List<UsmUser>>() {
+ });
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmReader.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmReader.java
new file mode 100644
index 0000000000..02defebe15
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmReader.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.snmp4j.security.UsmUser;
+
+import java.util.List;
+
+public interface UsmReader {
+
+ List<UsmUser> readUsm();
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmUserDeserializer.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmUserDeserializer.java
new file mode 100644
index 0000000000..f07ccf78a7
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/utils/UsmUserDeserializer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+
+import java.io.IOException;
+
+class UsmUserDeserializer extends StdDeserializer<UsmUser> {
+
+ public UsmUserDeserializer() {
+ super((Class<?>) null);
+ }
+
+ @Override
+ public UsmUser deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ String securityName = node.get("securityName").asText();
+
+ OID authProtocol = null;
+ final JsonNode authProtocolNode = node.get("authProtocol");
+ if (authProtocolNode != null) {
+ authProtocol = SNMPUtils.getAuth(authProtocolNode.asText());
+ }
+
+ OctetString authPassphrase = null;
+ final JsonNode authPassphraseNode = node.get("authPassphrase");
+ if (authPassphraseNode != null) {
+ authPassphrase = new OctetString(authPassphraseNode.asText());
+ }
+
+ if (authProtocol != null && authPassphrase == null) {
+ throw new IllegalArgumentException("Authentication passphrase must be set and at least 8 bytes long if" +
+ "authentication protocol is specified.");
+ }
+
+ OID privProtocol = null;
+ final JsonNode privProtocolNode = node.get("privProtocol");
+ if (privProtocolNode != null) {
+ privProtocol = SNMPUtils.getPriv(privProtocolNode.asText());
+ }
+
+ OctetString privPassphrase = null;
+ final JsonNode privPassphraseNode = node.get("privPassphrase");
+ if (privPassphraseNode != null) {
+ privPassphrase = new OctetString(privPassphraseNode.asText());
+ }
+
+ if (privProtocol != null && privPassphrase == null) {
+ throw new IllegalArgumentException("Privacy passphrase must be set and at least 8 bytes long if" +
+ "authentication protocol is specified.");
+ }
+
+ return new UsmUser(
+ new OctetString(securityName),
+ authProtocol,
+ authPassphrase,
+ privProtocol,
+ privPassphrase
+ );
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/resources/docs/org.apache.nifi.snmp.processors.ListenTrapSNMP/additionalDetails.html b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/resources/docs/org.apache.nifi.snmp.processors.ListenTrapSNMP/additionalDetails.html
index 37aaa668f7..9cffa38cbb 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/resources/docs/org.apache.nifi.snmp.processors.ListenTrapSNMP/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/resources/docs/org.apache.nifi.snmp.processors.ListenTrapSNMP/additionalDetails.html
@@ -24,10 +24,11 @@
<h2>Summary</h2>
<p>
This processor listens to SNMP traps and creates a flowfile from the trap PDU.
- The versions SNMPv1, SNMPv2c and SNMPv3 are supproted. The component is based on <a href="http://www.snmp4j.org/">SNMP4J</a>.
+ The versions SNMPv1, SNMPv2c and SNMPv3 are supported. The component is based on <a href="http://www.snmp4j.org/">SNMP4J</a>.
</p>
<p>
- In case of SNMPv3, users can be specified in a json file. E.g.:
+ SNMPv3 has user-based security. The USM Users Source property allows users to choose between three different ways to provide the USM user database.
+ An example json file containing two users:
<pre>
<code>
[
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/configuration/V1TrapConfigurationTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/configuration/V1TrapConfigurationTest.java
index 1575113165..c7d4e26577 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/configuration/V1TrapConfigurationTest.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/configuration/V1TrapConfigurationTest.java
@@ -20,6 +20,11 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import static org.apache.nifi.snmp.configuration.V1TrapConfiguration.AGENT_ADDRESS_MUST_BE_SPECIFIED;
+import static org.apache.nifi.snmp.configuration.V1TrapConfiguration.ENTERPRISE_OID_MUST_BE_SPECIFIED;
+import static org.apache.nifi.snmp.configuration.V1TrapConfiguration.GENERIC_TRAP_TYPE_IS_6_ENTERPRISE_SPECIFIC_BUT_SPECIFIC_TRAP_TYPE_IS_NOT_PROVIDED;
+import static org.apache.nifi.snmp.configuration.V1TrapConfiguration.GENERIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_6;
+import static org.apache.nifi.snmp.configuration.V1TrapConfiguration.SPECIFIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_2147483647;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
@@ -51,7 +56,7 @@ public class V1TrapConfigurationTest {
@Test
public void testRequireNonNullEnterpriseOid() {
exceptionRule.expect(IllegalArgumentException.class);
- exceptionRule.expectMessage("Enterprise OID must be specified.");
+ exceptionRule.expectMessage(ENTERPRISE_OID_MUST_BE_SPECIFIED);
V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
@@ -62,7 +67,7 @@ public class V1TrapConfigurationTest {
@Test
public void testRequireNonNullAgentAddress() {
exceptionRule.expect(IllegalArgumentException.class);
- exceptionRule.expectMessage("Agent address must be specified.");
+ exceptionRule.expectMessage(AGENT_ADDRESS_MUST_BE_SPECIFIED);
V1TrapConfiguration.builder()
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
@@ -78,7 +83,7 @@ public class V1TrapConfigurationTest {
.genericTrapType("-1")
.build()
);
- assertEquals("Generic Trap Type must be between 0 and 6.", exception.getMessage());
+ assertEquals(GENERIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_6, exception.getMessage());
}
@Test
@@ -89,7 +94,7 @@ public class V1TrapConfigurationTest {
.genericTrapType("7")
.build()
);
- assertEquals("Generic Trap Type must be between 0 and 6.", exception.getMessage());
+ assertEquals(GENERIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_6, exception.getMessage());
}
@Test
@@ -112,7 +117,7 @@ public class V1TrapConfigurationTest {
.specificTrapType("-1")
.build()
);
- assertEquals("Specific Trap Type must be between 0 and 2147483647.", exception.getMessage());
+ assertEquals(SPECIFIC_TRAP_TYPE_MUST_BE_BETWEEN_0_AND_2147483647, exception.getMessage());
}
@Test
@@ -123,19 +128,6 @@ public class V1TrapConfigurationTest {
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.build()
);
- assertEquals("Generic Trap Type is [6 - Enterprise Specific] but Specific Trap Type is not provided or not a number.", exception.getMessage());
+ assertEquals(GENERIC_TRAP_TYPE_IS_6_ENTERPRISE_SPECIFIC_BUT_SPECIFIC_TRAP_TYPE_IS_NOT_PROVIDED, exception.getMessage());
}
-
- @Test
- public void testGenericTrapTypeIsNotEnterpriseSpecificButSpecificTrapTypeIsSet() {
- final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
- .agentAddress(AGENT_ADDRESS)
- .enterpriseOid(ENTERPRISE_OID)
- .genericTrapType("5")
- .specificTrapType("123")
- .build()
- );
- assertEquals("Invalid argument: Generic Trap Type is not [6 - Enterprise Specific] but Specific Trap Type is provided.", exception.getMessage());
- }
-
}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/testrunners/SNMPV3TestRunnerFactory.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/testrunners/SNMPV3TestRunnerFactory.java
index 998766e21f..4dfdd39252 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/testrunners/SNMPV3TestRunnerFactory.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/testrunners/SNMPV3TestRunnerFactory.java
@@ -105,7 +105,7 @@ public class SNMPV3TestRunnerFactory implements SNMPTestRunnerFactory {
final SNMPConfiguration snmpConfiguration = snmpV3ConfigurationFactory.createSnmpListenTrapConfig(managerPort);
runner.setProperty(ListenTrapSNMP.SNMP_MANAGER_PORT, String.valueOf(snmpConfiguration.getManagerPort()));
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
- runner.setProperty(ListenTrapSNMP.SNMP_USM_USERS_FILE_PATH, USM_USERS_FILE_PATH);
+ runner.setProperty(ListenTrapSNMP.SNMP_USM_USERS_JSON_FILE_PATH, USM_USERS_FILE_PATH);
return runner;
}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandlerTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandlerTest.java
index 25a20eaabd..3759df62b5 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandlerTest.java
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandlerTest.java
@@ -16,35 +16,28 @@
*/
package org.apache.nifi.snmp.operations;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
-import org.apache.nifi.snmp.dto.UserDetails;
-import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.apache.nifi.snmp.utils.JsonFileUsmReader;
import org.apache.nifi.util.MockComponentLog;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.snmp4j.Snmp;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.util.HashSet;
import java.util.List;
-import java.util.Scanner;
-import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -95,52 +88,25 @@ public class SNMPTrapReceiverHandlerTest {
}
@Test
- public void testAddUsmUsers() throws JsonProcessingException, FileNotFoundException {
- final Set<String> expectedUserAttributes = new HashSet<>();
- try (Scanner scanner = new Scanner(new File(USERS_JSON))) {
- final String content = scanner.useDelimiter("\\Z").next();
- final ObjectMapper mapper = new ObjectMapper();
- final List<UserDetails> userDetails = mapper.readValue(content, new TypeReference<List<UserDetails>>() {
- });
- userDetails
- .forEach(user -> {
- expectedUserAttributes.add(user.getSecurityName());
- expectedUserAttributes.add(SNMPUtils.getAuth(user.getAuthProtocol()).toString());
- expectedUserAttributes.add(user.getAuthPassphrase());
- expectedUserAttributes.add(SNMPUtils.getPriv(user.getPrivProtocol()).toString());
- expectedUserAttributes.add(user.getPrivPassphrase());
- });
- }
- final Set<String> usmAttributes = new HashSet<>();
- final SNMPConfiguration snmpConfiguration = mock(SNMPConfiguration.class);
- final ProcessSessionFactory mockProcessSessionFactory = mock(ProcessSessionFactory.class);
- final MockComponentLog mockComponentLog = new MockComponentLog("componentId", new Object());
- final Snmp mockSnmpManager = mock(Snmp.class);
- final USM mockUsm = mock(USM.class);
+ public void testAddUsmUsers() {
+ final List<UsmUser> usmUsers = new JsonFileUsmReader(USERS_JSON).readUsm();
- when(snmpConfiguration.getManagerPort()).thenReturn(NetworkUtils.getAvailableUdpPort());
- when(snmpConfiguration.getVersion()).thenReturn(SnmpConstants.version3);
- doAnswer(invocation -> {
- UsmUser usmUser = (UsmUser) invocation.getArgument(0);
- usmAttributes.add(usmUser.getSecurityName().toString());
- usmAttributes.add(usmUser.getAuthenticationProtocol().toString());
- usmAttributes.add(usmUser.getAuthenticationPassphrase().toString());
- usmAttributes.add(usmUser.getPrivacyProtocol().toString());
- usmAttributes.add(usmUser.getPrivacyPassphrase().toString());
- return null;
- }).when(mockUsm).addUser(any(UsmUser.class));
- when(mockSnmpManager.getUSM()).thenReturn(mockUsm);
+ final SNMPConfiguration snmpConfiguration = SNMPConfiguration.builder()
+ .setManagerPort(NetworkUtils.getAvailableUdpPort())
+ .setVersion(SnmpConstants.version3)
+ .build();
- final SNMPTrapReceiverHandler trapReceiverHandler = new SNMPTrapReceiverHandler(snmpConfiguration, USERS_JSON);
- trapReceiverHandler.setSnmpManager(mockSnmpManager);
- trapReceiverHandler.createTrapReceiver(mockProcessSessionFactory, mockComponentLog);
+ final Snmp mockSnmpManager = mock(Snmp.class, RETURNS_DEEP_STUBS);
+ final ArgumentCaptor<UsmUser> usmUserCaptor = ArgumentCaptor.forClass(UsmUser.class);
+ final SNMPTrapReceiverHandler trapReceiverHandler = new SNMPTrapReceiverHandler(snmpConfiguration, usmUsers);
+ trapReceiverHandler.setSnmpManager(mockSnmpManager);
+ trapReceiverHandler.createTrapReceiver(null, null);
+ verify(mockSnmpManager.getUSM(), times(2)).addUser(usmUserCaptor.capture());
verify(mockSnmpManager).addCommandResponder(any(SNMPTrapReceiver.class));
assertTrue(trapReceiverHandler.isStarted());
-
- assertEquals(expectedUserAttributes, usmAttributes);
+ assertEquals(usmUsers, usmUserCaptor.getAllValues());
}
-
}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonFileUsmReaderTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonFileUsmReaderTest.java
new file mode 100644
index 0000000000..098bcd334b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonFileUsmReaderTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.apache.nifi.processor.exception.ProcessException;
+import org.junit.jupiter.api.Test;
+import org.snmp4j.security.UsmUser;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class JsonFileUsmReaderTest extends JsonUsmReaderTestBase {
+
+ @Test
+ void testReadJsonFile() {
+ final UsmReader jsonFileUsmReader = new JsonFileUsmReader(USERS_JSON_PATH);
+ final List<UsmUser> usmUsers = jsonFileUsmReader.readUsm();
+
+ assertEquals(expectedUsmUsers, usmUsers);
+ }
+
+ @Test
+ void testReadJsonFileThrowsException() {
+ final UsmReader jsonFileUsmReader = new JsonFileUsmReader(NOT_FOUND_USERS_JSON_PATH);
+ assertThrows(ProcessException.class, jsonFileUsmReader::readUsm);
+ }
+
+ @Test
+ void testReadInvalidJsonThrowsException() {
+ final UsmReader jsonFileUsmReader = new JsonFileUsmReader(INVALID_USERS_JSON_PATH);
+ assertThrows(ProcessException.class, jsonFileUsmReader::readUsm);
+ }
+
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTest.java
new file mode 100644
index 0000000000..8e36a4bdda
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.apache.nifi.processor.exception.ProcessException;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.snmp4j.security.UsmUser;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class JsonUsmReaderTest extends JsonUsmReaderTestBase {
+
+ private static String USERS_JSON;
+ private static String INVALID_USERS_JSON;
+
+ @BeforeAll
+ public static void setup() throws IOException {
+ USERS_JSON = readFile(USERS_JSON_PATH);
+ INVALID_USERS_JSON = readFile(INVALID_USERS_JSON_PATH);
+ }
+
+ @Test
+ void testReadJson() {
+ final UsmReader jsonUsmReader = new JsonUsmReader(USERS_JSON);
+ final List<UsmUser> usmUsers = jsonUsmReader.readUsm();
+
+ assertEquals(expectedUsmUsers, usmUsers);
+ }
+
+ @Test
+ void testReadInvalidJsonThrowsException() {
+ final UsmReader jsonUsmReader = new JsonUsmReader(INVALID_USERS_JSON);
+ assertThrows(ProcessException.class, jsonUsmReader::readUsm);
+ }
+
+ static String readFile(String path) throws IOException {
+ byte[] encoded = Files.readAllBytes(Paths.get(path));
+ return new String(encoded, StandardCharsets.UTF_8);
+ }
+
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTestBase.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTestBase.java
new file mode 100644
index 0000000000..82402d0503
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/JsonUsmReaderTestBase.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JsonUsmReaderTestBase {
+
+ static final String USERS_JSON_PATH = "src/test/resources/users.json";
+ static final String NOT_FOUND_USERS_JSON_PATH = "src/test/resources/not_found.json";
+ static final String INVALID_USERS_JSON_PATH = "src/test/resources/invalid_users.json";
+
+ static final List<UsmUser> expectedUsmUsers;
+
+ static {
+ expectedUsmUsers = new ArrayList<>();
+ expectedUsmUsers.add(new UsmUser(
+ new OctetString("user1"),
+ new OID("1.3.6.1.6.3.10.1.1.2"),
+ new OctetString("abc12345"),
+ new OID("1.3.6.1.6.3.10.1.2.2"),
+ new OctetString("abc12345")
+ ));
+ expectedUsmUsers.add(new UsmUser(
+ new OctetString("user2"),
+ new OID("1.3.6.1.6.3.10.1.1.3"),
+ new OctetString("abc12345"),
+ new OID("1.3.6.1.4.1.4976.2.2.1.1.2"),
+ new OctetString("abc12345")
+ ));
+ }
+
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReaderTest.java b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReaderTest.java
new file mode 100644
index 0000000000..1a1d590b0c
--- /dev/null
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/utils/SecurityNamesUsmReaderTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.snmp.utils;
+
+import org.junit.jupiter.api.Test;
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.OctetString;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class SecurityNamesUsmReaderTest {
+
+ @Test
+ void testReadJson() {
+ final List<UsmUser> expectedUsmUsers = new ArrayList<>();
+ expectedUsmUsers.add(new UsmUser(
+ new OctetString("user1"),
+ null,
+ null,
+ null,
+ null
+ ));
+ expectedUsmUsers.add(new UsmUser(
+ new OctetString("user2"),
+ null,
+ null,
+ null,
+ null
+ ));
+ final String securityNames = "user1,user2";
+ final UsmReader securityNamesUsmReader = new SecurityNamesUsmReader(securityNames);
+ final List<UsmUser> usmUsers = securityNamesUsmReader.readUsm();
+
+ assertEquals(expectedUsmUsers, usmUsers);
+ }
+}
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/invalid_users.json
similarity index 69%
copy from nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json
copy to nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/invalid_users.json
index b6ce71a154..806440382b 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/invalid_users.json
@@ -1,14 +1,14 @@
[
{
"securityName":"user1",
- "authProtocol":"MD5",
+ "authProtocol":"INVALID",
"authPassphrase":"abc12345",
"privProtocol":"DES",
"privPassphrase":"abc12345"
},
{
- "securityName":"newUser2",
- "authProtocol":"MD5",
+ "securityName":"user2",
+ "authProtocol":"SHA",
"authPassphrase":"abc12345",
"privProtocol":"AES256",
"privPassphrase":"abc12345"
diff --git a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json
index b6ce71a154..113586e9c8 100644
--- a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json
+++ b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/resources/users.json
@@ -7,8 +7,8 @@
"privPassphrase":"abc12345"
},
{
- "securityName":"newUser2",
- "authProtocol":"MD5",
+ "securityName":"user2",
+ "authProtocol":"SHA",
"authPassphrase":"abc12345",
"privProtocol":"AES256",
"privPassphrase":"abc12345"