NIFI-3328: SendTrapSNMP and ListenTrapSNMP processors added.

This commit is contained in:
Lehel Boér 2021-05-20 17:08:02 +02:00 committed by Tamas Palfy
parent dfd8adfd8e
commit bd7536b257
79 changed files with 5243 additions and 1598 deletions

View File

@ -51,6 +51,12 @@ language governing permissions and limitations under the License. -->
<version>1.16.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
@ -61,7 +67,7 @@ language governing permissions and limitations under the License. -->
<configuration>
<excludes>
<!-- test data -->
<exclude>src/test/resources/testdata/*</exclude>
<exclude>src/test/resources/*</exclude>
</excludes>
</configuration>
</plugin>

View File

@ -18,10 +18,11 @@ package org.apache.nifi.snmp.configuration;
public class SNMPConfiguration {
private final String agentHost;
private final String agentPort;
private final int managerPort;
private final String targetHost;
private final String targetPort;
private final int retries;
private final int timeout;
private final long timeoutInMs;
private final int version;
private final String authProtocol;
private final String authPassphrase;
@ -31,10 +32,11 @@ public class SNMPConfiguration {
private final String securityLevel;
private final String communityString;
SNMPConfiguration(final String agentHost,
final String agentPort,
SNMPConfiguration(final int managerPort,
final String targetHost,
final String targetPort,
final int retries,
final int timeout,
final long timeoutInMs,
final int version,
final String authProtocol,
final String authPassphrase,
@ -43,10 +45,11 @@ public class SNMPConfiguration {
final String securityName,
final String securityLevel,
final String communityString) {
this.agentHost = agentHost;
this.agentPort = agentPort;
this.managerPort = managerPort;
this.targetHost = targetHost;
this.targetPort = targetPort;
this.retries = retries;
this.timeout = timeout;
this.timeoutInMs = timeoutInMs;
this.version = version;
this.authProtocol = authProtocol;
this.authPassphrase = authPassphrase;
@ -57,20 +60,24 @@ public class SNMPConfiguration {
this.communityString = communityString;
}
public String getAgentHost() {
return agentHost;
public int getManagerPort() {
return managerPort;
}
public String getAgentPort() {
return agentPort;
public String getTargetHost() {
return targetHost;
}
public String getTargetPort() {
return targetPort;
}
public int getRetries() {
return retries;
}
public int getTimeout() {
return timeout;
public long getTimeoutInMs() {
return timeoutInMs;
}
public int getVersion() {
@ -104,4 +111,95 @@ public class SNMPConfiguration {
public String getCommunityString() {
return communityString;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int managerPort;
private String targetHost;
private String targetPort;
private int retries;
private long timeoutInMs = 500L;
private int version;
private String authProtocol;
private String authPassphrase;
private String privacyProtocol;
private String privacyPassphrase;
private String securityName;
private String securityLevel;
private String communityString;
public Builder setManagerPort(final int managerPort) {
this.managerPort = managerPort;
return this;
}
public Builder setTargetHost(final String targetHost) {
this.targetHost = targetHost;
return this;
}
public Builder setTargetPort(final String targetPort) {
this.targetPort = targetPort;
return this;
}
public Builder setRetries(final int retries) {
this.retries = retries;
return this;
}
public Builder setTimeoutInMs(final long timeoutInMs) {
this.timeoutInMs = timeoutInMs;
return this;
}
public Builder setVersion(final int version) {
this.version = version;
return this;
}
public Builder setAuthProtocol(final String authProtocol) {
this.authProtocol = authProtocol;
return this;
}
public Builder setAuthPassphrase(final String authPassphrase) {
this.authPassphrase = authPassphrase;
return this;
}
public Builder setPrivacyProtocol(final String privacyProtocol) {
this.privacyProtocol = privacyProtocol;
return this;
}
public Builder setPrivacyPassphrase(final String privacyPassphrase) {
this.privacyPassphrase = privacyPassphrase;
return this;
}
public Builder setSecurityName(final String securityName) {
this.securityName = securityName;
return this;
}
public Builder setSecurityLevel(final String securityLevel) {
this.securityLevel = securityLevel;
return this;
}
public Builder setCommunityString(String communityString) {
this.communityString = communityString;
return this;
}
public SNMPConfiguration build() {
return new SNMPConfiguration(managerPort, targetHost, targetPort, retries, timeoutInMs, version, authProtocol,
authPassphrase, privacyProtocol, privacyPassphrase, securityName, securityLevel, communityString);
}
}
}

View File

@ -1,100 +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.configuration;
public class SNMPConfigurationBuilder {
private String agentHost;
private String agentPort;
private int retries;
private int timeout;
private int version;
private String authProtocol;
private String authPassphrase;
private String privacyProtocol;
private String privacyPassphrase;
private String securityName;
private String securityLevel;
private String communityString;
public SNMPConfigurationBuilder setAgentHost(final String agentHost) {
this.agentHost = agentHost;
return this;
}
public SNMPConfigurationBuilder setAgentPort(final String agentPort) {
this.agentPort = agentPort;
return this;
}
public SNMPConfigurationBuilder setRetries(final int retries) {
this.retries = retries;
return this;
}
public SNMPConfigurationBuilder setTimeout(final int timeout) {
this.timeout = timeout;
return this;
}
public SNMPConfigurationBuilder setVersion(final int version) {
this.version = version;
return this;
}
public SNMPConfigurationBuilder setAuthProtocol(final String authProtocol) {
this.authProtocol = authProtocol;
return this;
}
public SNMPConfigurationBuilder setAuthPassphrase(final String authPassphrase) {
this.authPassphrase = authPassphrase;
return this;
}
public SNMPConfigurationBuilder setPrivacyProtocol(final String privacyProtocol) {
this.privacyProtocol = privacyProtocol;
return this;
}
public SNMPConfigurationBuilder setPrivacyPassphrase(final String privacyPassphrase) {
this.privacyPassphrase = privacyPassphrase;
return this;
}
public SNMPConfigurationBuilder setSecurityName(final String securityName) {
this.securityName = securityName;
return this;
}
public SNMPConfigurationBuilder setSecurityLevel(final String securityLevel) {
this.securityLevel = securityLevel;
return this;
}
public SNMPConfigurationBuilder setCommunityString(final String communityString) {
this.communityString = communityString;
return this;
}
public SNMPConfiguration build() {
final boolean isValid = agentHost != null && agentPort != null;
if (!isValid) {
throw new IllegalStateException("Required properties are not set.");
}
return new SNMPConfiguration(agentHost, agentPort, retries, timeout, version, authProtocol, authPassphrase, privacyProtocol, privacyPassphrase, securityName, securityLevel, communityString);
}
}

View File

@ -0,0 +1,117 @@
/*
* 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.configuration;
import org.apache.nifi.util.StringUtils;
public class V1TrapConfiguration {
private final String enterpriseOid;
private final String agentAddress;
private final String genericTrapType;
private final String specificTrapType;
private V1TrapConfiguration(final V1TrapConfiguration.Builder builder) {
this.enterpriseOid = builder.enterpriseOid;
this.agentAddress = builder.agentAddress;
this.genericTrapType = builder.genericTrapType;
this.specificTrapType = builder.specificTrapType;
}
public String getEnterpriseOid() {
return enterpriseOid;
}
public String getAgentAddress() {
return agentAddress;
}
public int getGenericTrapType() {
return Integer.parseInt(genericTrapType);
}
public Integer getSpecificTrapType() {
if (StringUtils.isNotEmpty(specificTrapType)) {
return Integer.parseInt(specificTrapType);
}
return null;
}
public static V1TrapConfiguration.Builder builder() {
return new V1TrapConfiguration.Builder();
}
public static final class Builder {
String enterpriseOid;
String agentAddress;
String genericTrapType;
String specificTrapType;
public Builder enterpriseOid(String enterpriseOid) {
this.enterpriseOid = enterpriseOid;
return this;
}
public Builder agentAddress(String agentAddress) {
this.agentAddress = agentAddress;
return this;
}
public Builder genericTrapType(String genericTrapType) {
this.genericTrapType = genericTrapType;
return this;
}
public Builder specificTrapType(String specificTrapType) {
this.specificTrapType = specificTrapType;
return this;
}
public V1TrapConfiguration build() {
if (StringUtils.isEmpty(enterpriseOid)) {
throw new IllegalArgumentException("Enterprise OID must be specified.");
}
if (StringUtils.isEmpty(agentAddress)) {
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.");
}
} catch (NumberFormatException e) {
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.");
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Generic Trap Type is [6 - Enterprise Specific] but Specific Trap Type is not provided or not a number.");
}
} 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);
}
}
}

View File

@ -14,12 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.snmp.exception;
package org.apache.nifi.snmp.configuration;
public class CreateSNMPClientException extends SNMPException {
public class V2TrapConfiguration {
public CreateSNMPClientException(final String errorMessage) {
super(errorMessage);
private final String trapOidValue;
public V2TrapConfiguration(final String trapOidValue) {
if (trapOidValue.isEmpty()) {
throw new IllegalArgumentException("Trap OID Value must be specified.");
}
this.trapOidValue = trapOidValue;
}
public String getTrapOidValue() {
return trapOidValue;
}
}

View File

@ -1,25 +1,21 @@
/*
* 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.exception;
public class CloseSNMPClientException extends SNMPException {
public CloseSNMPClientException(final String errorMessage) {
super(errorMessage);
}
}
/*
* 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 enum ErrorStatus {
FAILURE, SUCCESS
}

View File

@ -1,34 +1,37 @@
/*
* 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.operations;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import java.io.IOException;
public interface SNMPRequestHandler {
SNMPSingleResponse get(final String oid) throws IOException;
SNMPTreeResponse walk(final String oid);
SNMPSingleResponse set(final FlowFile flowfile) throws IOException;
void close();
}
/*
* 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 SNMPResponseStatus {
private final String errorMessage;
private final ErrorStatus errorStatus;
public SNMPResponseStatus(String errorMessage, ErrorStatus errorStatus) {
this.errorMessage = errorMessage;
this.errorStatus = errorStatus;
}
public String getErrorMessage() {
return errorMessage;
}
public ErrorStatus getErrorStatus() {
return errorStatus;
}
}

View File

@ -38,7 +38,6 @@ public class SNMPSingleResponse {
return responsePdu.getErrorStatus() == PDU.noError;
}
public Map<String, String> getAttributes() {
return SNMPUtils.getPduAttributeMap(responsePdu);
}
@ -65,4 +64,5 @@ public class SNMPSingleResponse {
public boolean isReportPdu() {
return responsePdu.getType() == PDU.REPORT;
}
}

View File

@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
public class SNMPTreeResponse {
@ -56,4 +57,11 @@ public class SNMPTreeResponse {
.filter(TreeEvent::isError)
.forEach(event -> logger.error("Error occured in SNMP walk event: {}", event.getErrorMessage()));
}
public boolean isError() {
final Optional<TreeEvent> first = events.stream()
.filter(TreeEvent::isError)
.findFirst();
return first.isPresent();
}
}

View File

@ -0,0 +1,58 @@
/*
* 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;
}
}

View File

@ -22,4 +22,8 @@ public class SNMPException extends RuntimeException {
super(errorMessage);
}
public SNMPException(final Exception exception) {
super(exception);
}
}

View File

@ -1,91 +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.factory;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.exception.CreateSNMPClientException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.IOException;
import java.util.Optional;
public abstract class AbstractSNMPFactory {
private static final Logger logger = LoggerFactory.getLogger(AbstractSNMPFactory.class);
protected AbstractSNMPFactory() {
// hide implicit constructor
}
protected static Snmp createSnmpClient() {
final Snmp snmp;
try {
snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
return snmp;
} catch (IOException e) {
final String errorMessage = "Creating SNMP client failed.";
logger.error(errorMessage, e);
throw new CreateSNMPClientException(errorMessage);
}
}
protected static Target createUserTarget(final SNMPConfiguration configuration) {
final UserTarget userTarget = new UserTarget();
setupTargetBasicProperties(userTarget, configuration);
final int securityLevel = SecurityLevel.valueOf(configuration.getSecurityLevel()).getSnmpValue();
userTarget.setSecurityLevel(securityLevel);
final String securityName = configuration.getSecurityName();
Optional.ofNullable(securityName).map(OctetString::new).ifPresent(userTarget::setSecurityName);
return userTarget;
}
protected static Target createCommunityTarget(final SNMPConfiguration configuration) {
final Target communityTarget = new CommunityTarget();
setupTargetBasicProperties(communityTarget, configuration);
final String community = configuration.getCommunityString();
Optional.ofNullable(community).map(OctetString::new).ifPresent(communityTarget::setSecurityName);
return communityTarget;
}
private static void setupTargetBasicProperties(final Target target, final SNMPConfiguration configuration) {
final int snmpVersion = configuration.getVersion();
final String host = configuration.getAgentHost();
final String port = configuration.getAgentPort();
final int retries = configuration.getRetries();
final int timeout = configuration.getTimeout();
target.setVersion(snmpVersion);
target.setAddress(new UdpAddress(host + "/" + port));
target.setRetries(retries);
target.setTimeout(timeout);
}
}

View File

@ -1,70 +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.factory;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class CompositeSNMPFactory implements SNMPFactory {
private static final String INVALID_SNMP_VERSION = "SNMP version is not supported.";
private static final List<SNMPFactory> FACTORIES;
static {
final List<SNMPFactory> factories = Arrays.asList(new V1SNMPFactory(), new V2cSNMPFactory(), new V3SNMPFactory());
FACTORIES = Collections.unmodifiableList(factories);
}
@Override
public boolean supports(final int version) {
return !getMatchingFactory(version).isPresent();
}
@Override
public Snmp createSnmpManagerInstance(final SNMPConfiguration configuration) {
final Optional<SNMPFactory> factory = getMatchingFactory(configuration.getVersion());
if (!factory.isPresent()) {
throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
}
return factory.get().createSnmpManagerInstance(configuration);
}
@Override
public Target createTargetInstance(final SNMPConfiguration configuration) {
final Optional<SNMPFactory> factory = getMatchingFactory(configuration.getVersion());
if (!factory.isPresent()) {
throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
}
return factory.get().createTargetInstance(configuration);
}
private Optional<SNMPFactory> getMatchingFactory(final int version) {
for (final SNMPFactory factory : FACTORIES) {
if (factory.supports(version)) {
return Optional.of(factory);
}
}
return Optional.empty();
}
}

View File

@ -1,76 +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.factory;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
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 java.util.Optional;
public class V3SNMPFactory extends AbstractSNMPFactory implements SNMPFactory {
@Override
public boolean supports(final int version) {
return SnmpConstants.version3 == version;
}
@Override
public Snmp createSnmpManagerInstance(final SNMPConfiguration configuration) {
final Snmp snmp = createSnmpClient();
// If there's a USM instance associated with the MPv3 bound to this Snmp instance (like an agent running
// on the same host) it is not null.
if (snmp.getUSM() == null) {
final OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());
final USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0);
SecurityModels.getInstance().addSecurityModel(usm);
}
final String username = configuration.getSecurityName();
final OID authProtocol = Optional.ofNullable(configuration.getAuthProtocol())
.map(SNMPUtils::getAuth).orElse(null);
final OID privacyProtocol = Optional.ofNullable(configuration.getPrivacyProtocol())
.map(SNMPUtils::getPriv).orElse(null);
final String authPassword = configuration.getAuthPassphrase();
final String privacyPassword = configuration.getPrivacyPassphrase();
final OctetString authPasswordOctet = authPassword != null ? new OctetString(authPassword) : null;
final OctetString privacyPasswordOctet = privacyPassword != null ? new OctetString(privacyPassword) : null;
// Add user information.
snmp.getUSM().addUser(
new OctetString(username),
new UsmUser(new OctetString(username), authProtocol, authPasswordOctet,
privacyProtocol, privacyPasswordOctet));
return snmp;
}
@Override
public Target createTargetInstance(final SNMPConfiguration configuration) {
return createUserTarget(configuration);
}
}

View File

@ -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.factory.core;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.operations.SNMPResourceHandler;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.smi.UdpAddress;
public interface SNMPContext {
default SNMPResourceHandler createSNMPResourceHandler(final SNMPConfiguration snmpConfiguration) {
return new SNMPResourceHandler(
createSnmpManagerInstance(snmpConfiguration),
createTargetInstance(snmpConfiguration)
);
}
default void setupTargetBasicProperties(final Target target, final SNMPConfiguration configuration) {
final int snmpVersion = configuration.getVersion();
final String host = configuration.getTargetHost();
final String port = configuration.getTargetPort();
final int retries = configuration.getRetries();
final long timeout = configuration.getTimeoutInMs();
target.setVersion(snmpVersion);
target.setAddress(new UdpAddress(host + "/" + port));
target.setRetries(retries);
target.setTimeout(timeout);
}
Snmp createSnmpManagerInstance(final SNMPConfiguration configuration);
Target createTargetInstance(final SNMPConfiguration configuration);
}

View File

@ -0,0 +1,48 @@
/*
* 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.factory.core;
import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
import org.snmp4j.mp.SnmpConstants;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class SNMPFactoryProvider {
private SNMPFactoryProvider() {
// not to instantiate
}
private static final String INVALID_SNMP_VERSION = "SNMP version is not supported: %s";
private static final Map<Integer, SNMPContext> FACTORIES;
static {
final Map<Integer, SNMPContext> factories = new HashMap<>();
factories.put(SnmpConstants.version1, new V1V2cSNMPFactory());
factories.put(SnmpConstants.version2c, new V1V2cSNMPFactory());
factories.put(SnmpConstants.version3, new V3SNMPFactory());
FACTORIES = Collections.unmodifiableMap(factories);
}
public static SNMPContext getFactory(final int version) {
return Optional.ofNullable(FACTORIES.get(version))
.orElseThrow(() -> new InvalidSnmpVersionException(String.format(INVALID_SNMP_VERSION, version)));
}
}

View File

@ -14,27 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.snmp.factory;
package org.apache.nifi.snmp.factory.core;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
public class V2cSNMPFactory extends AbstractSNMPFactory implements SNMPFactory {
import java.io.IOException;
@Override
public boolean supports(final int version) {
return SnmpConstants.version2c == version;
}
public class SNMPManagerFactory {
private static final String LOCALHOST = "127.0.0.1";
@Override
public Snmp createSnmpManagerInstance(final SNMPConfiguration configuration) {
return createSnmpClient();
}
@Override
public Target createTargetInstance(final SNMPConfiguration configuration) {
return createCommunityTarget(configuration);
final String managerAddress = LOCALHOST + "/" + configuration.getManagerPort();
final Snmp snmpManager;
try {
snmpManager = new Snmp(new DefaultUdpTransportMapping(new UdpAddress(managerAddress)));
snmpManager.listen();
} catch (IOException e) {
throw new ProcessException(e);
}
return snmpManager;
}
}

View File

@ -14,27 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.snmp.factory;
package org.apache.nifi.snmp.factory.core;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.snmp4j.Snmp;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Target;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OctetString;
public class V1SNMPFactory extends AbstractSNMPFactory implements SNMPFactory {
import java.util.Optional;
@Override
public boolean supports(final int version) {
return SnmpConstants.version1 == version;
}
@Override
public Snmp createSnmpManagerInstance(final SNMPConfiguration configuration) {
return createSnmpClient();
}
public class V1V2cSNMPFactory extends SNMPManagerFactory implements SNMPContext {
@Override
public Target createTargetInstance(final SNMPConfiguration configuration) {
return createCommunityTarget(configuration);
final Target communityTarget = new CommunityTarget();
setupTargetBasicProperties(communityTarget, configuration);
final String community = configuration.getCommunityString();
Optional.ofNullable(community).map(OctetString::new).ifPresent(communityTarget::setSecurityName);
return communityTarget;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.factory.core;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityLevel;
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 java.util.Optional;
public class V3SNMPFactory extends SNMPManagerFactory implements SNMPContext {
@Override
public Snmp createSnmpManagerInstance(final SNMPConfiguration configuration) {
final Snmp snmpManager = super.createSnmpManagerInstance(configuration);
// Create USM.
final OctetString localEngineId = new OctetString(MPv3.createLocalEngineID());
final USM usm = new USM(SecurityProtocols.getInstance(), localEngineId, 0);
SecurityModels.getInstance().addSecurityModel(usm);
Optional.ofNullable(configuration.getSecurityName())
.map(OctetString::new)
.ifPresent(securityName -> {
OID authProtocol = Optional.ofNullable(configuration.getAuthProtocol())
.map(SNMPUtils::getAuth).orElse(null);
OctetString authPassphrase = Optional.ofNullable(configuration.getAuthPassphrase())
.map(OctetString::new).orElse(null);
OID privacyProtocol = Optional.ofNullable(configuration.getPrivacyProtocol())
.map(SNMPUtils::getPriv).orElse(null);
OctetString privacyPassphrase = Optional.ofNullable(configuration.getPrivacyPassphrase())
.map(OctetString::new).orElse(null);
snmpManager.getUSM().addUser(securityName, new UsmUser(securityName, authProtocol, authPassphrase,
privacyProtocol, privacyPassphrase));
});
return snmpManager;
}
@Override
public Target createTargetInstance(final SNMPConfiguration configuration) {
final UserTarget userTarget = new UserTarget();
setupTargetBasicProperties(userTarget, configuration);
final int securityLevel = SecurityLevel.valueOf(configuration.getSecurityLevel()).getSnmpValue();
userTarget.setSecurityLevel(securityLevel);
final String securityName = configuration.getSecurityName();
Optional.ofNullable(securityName).map(OctetString::new).ifPresent(userTarget::setSecurityName);
return userTarget;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.factory.trap;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.Target;
import org.snmp4j.smi.IpAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
/**
* Factory class to create SNMPv1-Trap-PDU for SNMPv1.
*/
public class V1TrapPDUFactory {
private static final PDUFactory v1PduFactory = new DefaultPDUFactory(PDU.V1TRAP);
final Target target;
final Instant startTime;
public V1TrapPDUFactory(final Target target, final Instant startTime) {
this.target = target;
this.startTime = startTime;
}
public PDU get(final V1TrapConfiguration v1TrapConfiguration) {
final PDUv1 pdu = (PDUv1) v1PduFactory.createPDU(target);
Optional.ofNullable(v1TrapConfiguration.getEnterpriseOid()).map(OID::new).ifPresent(pdu::setEnterprise);
Optional.ofNullable(v1TrapConfiguration.getAgentAddress()).map(IpAddress::new).ifPresent(pdu::setAgentAddress);
pdu.setGenericTrap(v1TrapConfiguration.getGenericTrapType());
Optional.ofNullable(v1TrapConfiguration.getSpecificTrapType()).ifPresent(pdu::setSpecificTrap);
final long elapsedMillis = Duration.between(startTime, Instant.now()).toMillis();
pdu.setTimestamp(elapsedMillis);
return pdu;
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.factory.trap;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.snmp4j.PDU;
import org.snmp4j.Target;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TimeTicks;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import java.time.Duration;
import java.time.Instant;
/**
* Factory class to create SNMPv2-Trap-PDU for SNMPv2c and SNMPv3.
*/
public class V2TrapPDUFactory {
private static final PDUFactory v2PduFactory = new DefaultPDUFactory(PDU.TRAP);
final Target target;
final Instant startTime;
public V2TrapPDUFactory(final Target target, final Instant startTime) {
this.target = target;
this.startTime = startTime;
}
public PDU get(final V2TrapConfiguration v2TrapConfiguration) {
final PDU pdu = v2PduFactory.createPDU(target);
pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OctetString(v2TrapConfiguration.getTrapOidValue())));
final long elapsedMillis = Duration.between(startTime, Instant.now()).toMillis();
pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(elapsedMillis)));
return pdu;
}
}

View File

@ -0,0 +1,150 @@
/*
* 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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.exception.SNMPWalkException;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import org.snmp4j.util.TreeEvent;
import org.snmp4j.util.TreeUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.apache.nifi.snmp.operations.SNMPResourceHandler.REQUEST_TIMEOUT_EXCEPTION_TEMPLATE;
public class GetSNMPHandler {
private static final PDUFactory getPduFactory = new DefaultPDUFactory(PDU.GET);
protected static final String EMPTY_SUBTREE_EXCEPTION_MESSAGE = "Agent is not available, the %s OID not found or user not found. " +
"Please, check if (1) the agent is available, (2) the processor's SNMP version matches the agent version, " +
"(3) the OID is correct, (4) The user is valid.";
protected static final String SNMP_ERROR_EXCEPTION_MESSAGE = "Agent is not available, OID not found or user not found. " +
"Please, check if (1) the agent is available, (2) the processor's SNMP version matches the agent version, " +
"(3) the OID is correct, (4) The user is valid.";
protected static final String LEAF_ELEMENT_EXCEPTION_MESSAGE = "OID not found or it is a single leaf element. The leaf element " +
"associated with this %s OID does not contain child OIDs. Please check if the OID exists in the agent " +
"MIB or specify a parent OID with at least one child element";
private final SNMPResourceHandler snmpResourceHandler;
private TreeUtils treeUtils;
public GetSNMPHandler(final SNMPResourceHandler snmpResourceHandler) {
this.snmpResourceHandler = snmpResourceHandler;
this.treeUtils = new TreeUtils(snmpResourceHandler.getSnmpManager(), getPduFactory);
}
public SNMPSingleResponse get(final String oid) throws IOException {
final Target target = snmpResourceHandler.getTarget();
final Snmp snmpManager = snmpResourceHandler.getSnmpManager();
final PDU pdu = getPduFactory.createPDU(target);
pdu.add(new VariableBinding(new OID(oid)));
final PDU responsePdu = getResponsePdu(target, snmpManager, pdu);
return new SNMPSingleResponse(target, responsePdu);
}
public Optional<SNMPSingleResponse> get(final Map<String, String> flowFileAttributes) throws IOException {
final Target target = snmpResourceHandler.getTarget();
final Snmp snmpManager = snmpResourceHandler.getSnmpManager();
final PDU pdu = getPduFactory.createPDU(target);
VariableBinding[] variableBindings = SNMPUtils.addGetVariables(flowFileAttributes);
if (variableBindings.length == 0) {
return Optional.empty();
}
pdu.addAll(variableBindings);
final PDU responsePdu = getResponsePdu(target, snmpManager, pdu);
return Optional.of(new SNMPSingleResponse(target, responsePdu));
}
public SNMPTreeResponse walk(final String oid) {
final Target target = snmpResourceHandler.getTarget();
final List<TreeEvent> subtree = treeUtils.getSubtree(target, new OID(oid));
evaluateSubtreeErrors(oid, subtree);
return new SNMPTreeResponse(target, subtree);
}
public Optional<SNMPTreeResponse> walk(final Map<String, String> flowFileAttributes) {
final Target target = snmpResourceHandler.getTarget();
final List<TreeEvent> subtree;
final OID[] oids = SNMPUtils.addWalkVariables(flowFileAttributes);
if (oids.length == 0) {
return Optional.empty();
}
subtree = treeUtils.walk(target, oids);
evaluateSubtreeErrors(Arrays.toString(oids), subtree);
return Optional.of(new SNMPTreeResponse(target, subtree));
}
private PDU getResponsePdu(Target target, Snmp snmpManager, PDU pdu) throws IOException {
final ResponseEvent response = snmpManager.get(pdu, target);
final PDU responsePdu = response.getResponse();
if (responsePdu == null) {
throw new RequestTimeoutException(String.format(REQUEST_TIMEOUT_EXCEPTION_TEMPLATE, "read"));
}
return responsePdu;
}
private void evaluateSubtreeErrors(String oid, List<TreeEvent> subtree) {
if (subtree.isEmpty()) {
throw new SNMPWalkException(String.format(EMPTY_SUBTREE_EXCEPTION_MESSAGE, oid));
}
if (isSnmpError(subtree)) {
throw new SNMPWalkException(SNMP_ERROR_EXCEPTION_MESSAGE);
}
if (isLeafElement(subtree)) {
throw new SNMPWalkException(String.format(LEAF_ELEMENT_EXCEPTION_MESSAGE, oid));
}
}
private boolean isSnmpError(final List<TreeEvent> subtree) {
return subtree.size() == 1 && subtree.get(0).getVariableBindings() == null;
}
private boolean isLeafElement(final List<TreeEvent> subtree) {
return subtree.size() == 1 && subtree.get(0).getVariableBindings().length == 0;
}
// Visible for testing
void setTreeUtils(final TreeUtils treeUtils) {
this.treeUtils = treeUtils;
}
}

View File

@ -1,38 +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.operations;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.factory.CompositeSNMPFactory;
import org.apache.nifi.snmp.factory.SNMPFactory;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
public final class SNMPRequestHandlerFactory {
public static SNMPRequestHandler createStandardRequestHandler(final SNMPConfiguration configuration) {
final SNMPFactory snmpFactory = new CompositeSNMPFactory();
final Snmp snmpClient = snmpFactory.createSnmpManagerInstance(configuration);
final Target target = snmpFactory.createTargetInstance(configuration);
return new StandardSNMPRequestHandler(snmpClient, target);
}
private SNMPRequestHandlerFactory() {
// This should not be instantiated.
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.operations;
import org.apache.nifi.processor.exception.ProcessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.smi.Integer32;
import java.io.IOException;
public class SNMPResourceHandler {
public static final String INVALID_FLOWFILE_EXCEPTION_MESSAGE = "Could not read the variable bindings from the " +
"flowfile. Please, add the OIDs to set in separate properties. E.g. Property name: snmp$1.3.6.1.2.1.1.1.0 " +
"Value: Example value. ";
public static final String REQUEST_TIMEOUT_EXCEPTION_TEMPLATE = "Request timed out. Please check if (1). the " +
"agent host and port is correctly set, (2). the agent is running, (3). the agent SNMP version corresponds" +
" with the processor's one, (4) the community string is correct and has %1$s access, (5) In case of SNMPv3" +
" check if the user credentials are valid and the user in a group with %1$s access.";
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final Snmp snmpManager;
private final Target target;
public SNMPResourceHandler(final Snmp snmpManager, final Target target) {
this.snmpManager = snmpManager;
this.target = target;
}
public Snmp getSnmpManager() {
return snmpManager;
}
public Target getTarget() {
return target;
}
public void close() {
try {
if (snmpManager.getUSM() != null) {
snmpManager.getUSM().removeAllUsers();
SecurityModels.getInstance().removeSecurityModel(new Integer32(snmpManager.getUSM().getID()));
}
snmpManager.close();
} catch (IOException e) {
final String errorMessage = "Could not close SNMP manager.";
logger.error(errorMessage, e);
throw new ProcessException(errorMessage);
}
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.operations;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import java.util.Map;
import static org.apache.nifi.snmp.processors.ListenTrapSNMP.REL_FAILURE;
import static org.apache.nifi.snmp.processors.ListenTrapSNMP.REL_SUCCESS;
public class SNMPTrapReceiver implements CommandResponder {
private final ProcessSessionFactory processSessionFactory;
private final ComponentLog logger;
public SNMPTrapReceiver(final ProcessSessionFactory processSessionFactory, final ComponentLog logger) {
this.processSessionFactory = processSessionFactory;
this.logger = logger;
}
@Override
public void processPdu(final CommandResponderEvent event) {
final PDU pdu = event.getPDU();
if (isValidTrapPdu(pdu)) {
final ProcessSession processSession = processSessionFactory.createSession();
final FlowFile flowFile = createFlowFile(processSession, pdu);
processSession.getProvenanceReporter().create(flowFile, event.getPeerAddress() + "/" + pdu.getRequestID());
if (pdu.getErrorStatus() == PDU.noError) {
processSession.transfer(flowFile, REL_SUCCESS);
} else {
processSession.transfer(flowFile, REL_FAILURE);
}
processSession.commitAsync();
} else {
logger.error("Request timed out or parameters are incorrect.");
}
}
private FlowFile createFlowFile(final ProcessSession processSession, final PDU pdu) {
FlowFile flowFile = processSession.create();
final Map<String, String> attributes;
if (pdu instanceof PDUv1) {
attributes = SNMPUtils.getV1TrapPduAttributeMap((PDUv1) pdu);
} else {
attributes = SNMPUtils.getPduAttributeMap(pdu);
}
flowFile = processSession.putAllAttributes(flowFile, attributes);
return flowFile;
}
private boolean isValidTrapPdu(final PDU pdu) {
return pdu != null && (pdu.getType() == PDU.V1TRAP || pdu.getType() == PDU.TRAP);
}
}

View File

@ -0,0 +1,124 @@
/*
* 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.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;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
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 Snmp snmpManager;
private boolean isStarted;
public SNMPTrapReceiverHandler(final SNMPConfiguration configuration, final String usmUsersFilePath) {
this.configuration = configuration;
this.usmUsersFilePath = usmUsersFilePath;
snmpManager = new SNMPManagerFactory().createSnmpManagerInstance(configuration);
}
public void createTrapReceiver(final ProcessSessionFactory processSessionFactory, final ComponentLog logger) {
addUsmUsers();
SNMPTrapReceiver trapReceiver = new SNMPTrapReceiver(processSessionFactory, logger);
snmpManager.addCommandResponder(trapReceiver);
isStarted = true;
}
public boolean isStarted() {
return isStarted;
}
public void close() {
try {
if (snmpManager.getUSM() != null) {
snmpManager.getUSM().removeAllUsers();
SecurityModels.getInstance().removeSecurityModel(new Integer32(snmpManager.getUSM().getID()));
}
snmpManager.close();
isStarted = false;
} catch (IOException e) {
final String errorMessage = "Could not close SNMP manager.";
logger.error(errorMessage, e);
throw new ProcessException(errorMessage);
}
}
private void addUsmUsers() {
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);
}
}
}
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;
}
}

View File

@ -0,0 +1,75 @@
/*
* 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.operations;
import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.factory.trap.V1TrapPDUFactory;
import org.apache.nifi.snmp.factory.trap.V2TrapPDUFactory;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import java.io.IOException;
import java.time.Instant;
import java.util.Map;
public class SendTrapSNMPHandler {
private final SNMPResourceHandler snmpResourceHandler;
private final ComponentLog logger;
private final V1TrapPDUFactory v1TrapPDUFactory;
private final V2TrapPDUFactory v2TrapPDUFactory;
public SendTrapSNMPHandler(final SNMPResourceHandler snmpResourceHandler, final Instant startTime, final ComponentLog logger) {
this.snmpResourceHandler = snmpResourceHandler;
this.logger = logger;
v1TrapPDUFactory = createV1TrapPduFactory(startTime);
v2TrapPDUFactory = createV2TrapPduFactory(startTime);
}
public void sendTrap(final Map<String, String> flowFileAttributes, final V1TrapConfiguration trapConfiguration) throws IOException {
final PDU pdu = v1TrapPDUFactory.get(trapConfiguration);
sendTrap(flowFileAttributes, pdu);
}
public void sendTrap(final Map<String, String> flowFileAttributes, final V2TrapConfiguration trapConfiguration) throws IOException {
final PDU pdu = v2TrapPDUFactory.get(trapConfiguration);
sendTrap(flowFileAttributes, pdu);
}
private void sendTrap(Map<String, String> flowFileAttributes, PDU pdu) throws IOException {
final Target target = snmpResourceHandler.getTarget();
final Snmp snmpManager = snmpResourceHandler.getSnmpManager();
final boolean isAnyVariableAdded = SNMPUtils.addVariables(pdu, flowFileAttributes);
if (!isAnyVariableAdded) {
logger.debug("No optional SNMP specific variables found in flowfile.");
}
snmpManager.send(pdu, target);
}
V1TrapPDUFactory createV1TrapPduFactory(final Instant startTime) {
return new V1TrapPDUFactory(snmpResourceHandler.getTarget(), startTime);
}
V2TrapPDUFactory createV2TrapPduFactory(final Instant startTime) {
return new V2TrapPDUFactory(snmpResourceHandler.getTarget(), startTime);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import static org.apache.nifi.snmp.operations.SNMPResourceHandler.REQUEST_TIMEOUT_EXCEPTION_TEMPLATE;
public class SetSNMPHandler {
private static PDUFactory setPduFactory = new DefaultPDUFactory(PDU.SET);
private final SNMPResourceHandler snmpResourceHandler;
public SetSNMPHandler(final SNMPResourceHandler snmpResourceHandler) {
this.snmpResourceHandler = snmpResourceHandler;
}
public Optional<SNMPSingleResponse> set(final Map<String, String> flowFileAttributes) throws IOException {
Target target = snmpResourceHandler.getTarget();
Snmp snmpManager = snmpResourceHandler.getSnmpManager();
final PDU pdu = setPduFactory.createPDU(target);
final boolean isAnySnmpVariableInFlowFile = SNMPUtils.addVariables(pdu, flowFileAttributes);
if (isAnySnmpVariableInFlowFile) {
final ResponseEvent response = snmpManager.set(pdu, target);
final PDU responsePdu = response.getResponse();
if (responsePdu == null) {
throw new RequestTimeoutException(String.format(REQUEST_TIMEOUT_EXCEPTION_TEMPLATE, "write"));
}
return Optional.of(new SNMPSingleResponse(target, responsePdu));
} else {
return Optional.empty();
}
}
// visible for testing
static void setSetPduFactory(final PDUFactory setPduFactory) {
SetSNMPHandler.setPduFactory = setPduFactory;
}
}

View File

@ -1,148 +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.operations;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.CloseSNMPClientException;
import org.apache.nifi.snmp.exception.InvalidFlowFileException;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.exception.SNMPWalkException;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import org.snmp4j.util.TreeEvent;
import org.snmp4j.util.TreeUtils;
import java.io.IOException;
import java.util.List;
final class StandardSNMPRequestHandler implements SNMPRequestHandler {
private static final Logger logger = LoggerFactory.getLogger(StandardSNMPRequestHandler.class);
private static final PDUFactory getPduFactory = new DefaultPDUFactory(PDU.GET);
private static final PDUFactory setPduFactory = new DefaultPDUFactory(PDU.SET);
private final Snmp snmpManager;
private final Target target;
StandardSNMPRequestHandler(final Snmp snmpManager, final Target target) {
this.snmpManager = snmpManager;
this.target = target;
}
/**
* Construct the PDU to perform the SNMP Get request and returns
* the result in order to create the flow file.
*
* @return {@link ResponseEvent}
*/
public SNMPSingleResponse get(final String oid) throws IOException {
final PDU pdu = getPduFactory.createPDU(target);
pdu.add(new VariableBinding(new OID(oid)));
final ResponseEvent response = snmpManager.get(pdu, target);
final PDU responsePdu = response.getResponse();
if (responsePdu == null) {
throw new RequestTimeoutException("Request timed out. Please check if (1). the agent host and port is correctly set, " +
"(2). the agent is running, (3). the agent SNMP version corresponds with the processor's one, (4) the " +
"community string is correct and has read access, (5) In case of SNMPv3 check if the user credentials " +
"are valid and the user in a group with read access.");
}
return new SNMPSingleResponse(target, responsePdu);
}
/**
* Perform a SNMP walk and returns the list of {@link TreeEvent}
*
* @return the list of {@link TreeEvent}
*/
public SNMPTreeResponse walk(final String oid) {
final TreeUtils treeUtils = new TreeUtils(snmpManager, getPduFactory);
final List<TreeEvent> subtree = treeUtils.getSubtree(target, new OID(oid));
if (subtree.isEmpty()) {
throw new SNMPWalkException(String.format("The subtree associated with the specified OID %s is empty.", oid));
}
if (isSnmpError(subtree)) {
throw new SNMPWalkException("Agent is not available, OID not found or user not found. Please, check if (1) the " +
"agent is available, (2) the processor's SNMP version matches the agent version, (3) the OID is " +
"correct, (4) The user is valid.");
}
if (isLeafElement(subtree)) {
throw new SNMPWalkException(String.format("OID not found or it is a single leaf element. The leaf element " +
"associated with this %s OID does not contain child OIDs. Please check if the OID exists in the agent " +
"MIB or specify a parent OID with at least one child element", oid));
}
return new SNMPTreeResponse(target, subtree);
}
private boolean isSnmpError(final List<TreeEvent> subtree) {
return subtree.size() == 1 && subtree.get(0).getVariableBindings() == null;
}
private boolean isLeafElement(final List<TreeEvent> subtree) {
return subtree.size() == 1 && subtree.get(0).getVariableBindings().length == 0;
}
/**
* Executes the SNMP set request and returns the response.
*
* @param flowFile FlowFile which contains variables for the PDU
* @return Response event
* @throws IOException IO Exception
*/
public SNMPSingleResponse set(final FlowFile flowFile) throws IOException {
final PDU pdu = setPduFactory.createPDU(target);
if (SNMPUtils.addVariables(pdu, flowFile.getAttributes())) {
final ResponseEvent response = snmpManager.set(pdu, target);
final PDU responsePdu = response.getResponse();
if (responsePdu == null) {
throw new RequestTimeoutException("Request timed out. Please check if (1). the agent host and port is correctly set, " +
"(2). the agent is running, (3). the agent SNMP version corresponds with the processor's one, (4) the " +
"community string is correct and has write access, (5) In case of SNMPv3 check if the user credentials " +
"are valid and the user in a group with write access.");
}
return new SNMPSingleResponse(target, responsePdu);
}
throw new InvalidFlowFileException("Could not read the variable bindings from the flowfile. Please, " +
"add the OIDs to set in separate properties. E.g. Property name: snmp$1.3.6.1.2.1.1.1.0 Value: Example value. ");
}
public void close() {
try {
if (snmpManager.getUSM() != null) {
snmpManager.getUSM().removeAllUsers();
SecurityModels.getInstance().removeSecurityModel(new Integer32(snmpManager.getUSM().getID()));
}
snmpManager.close();
} catch (IOException e) {
final String errorMessage = "Could not close SNMP client.";
logger.error(errorMessage, e);
throw new CloseSNMPClientException(errorMessage);
}
}
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.snmp.processors;
import org.apache.nifi.annotation.behavior.RequiresInstanceClassLoading;
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.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.AbstractProcessor;
@ -27,21 +26,20 @@ import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.configuration.SNMPConfigurationBuilder;
import org.apache.nifi.snmp.dto.ErrorStatus;
import org.apache.nifi.snmp.dto.SNMPResponseStatus;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPValue;
import org.apache.nifi.snmp.exception.SNMPException;
import org.apache.nifi.snmp.factory.core.SNMPFactoryProvider;
import org.apache.nifi.snmp.logging.SLF4JLogFactory;
import org.apache.nifi.snmp.operations.SNMPRequestHandler;
import org.apache.nifi.snmp.operations.SNMPRequestHandlerFactory;
import org.apache.nifi.snmp.operations.SNMPResourceHandler;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.log.LogFactory;
import org.snmp4j.mp.SnmpConstants;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
@ -55,49 +53,7 @@ abstract class AbstractSNMPProcessor extends AbstractProcessor {
LogFactory.setLogFactory(new SLF4JLogFactory());
}
private static final String SHA_2_ALGORITHM = "Provides authentication based on the HMAC-SHA-2 algorithm.";
private static final String NO_SUCH_OBJECT = "noSuchObject";
// SNMP versions
public static final AllowableValue SNMP_V1 = new AllowableValue("SNMPv1", "v1", "SNMP version 1");
public static final AllowableValue SNMP_V2C = new AllowableValue("SNMPv2c", "v2c", "SNMP version 2c");
public static final AllowableValue SNMP_V3 = new AllowableValue("SNMPv3", "v3", "SNMP version 3 with improved security");
// SNMPv3 security levels
public static final AllowableValue NO_AUTH_NO_PRIV = new AllowableValue("noAuthNoPriv", "noAuthNoPriv",
"No authentication or encryption.");
public static final AllowableValue AUTH_NO_PRIV = new AllowableValue("authNoPriv", "authNoPriv",
"Authentication without encryption.");
public static final AllowableValue AUTH_PRIV = new AllowableValue("authPriv", "authPriv",
"Authentication and encryption.");
// SNMPv3 authentication protocols
public static final AllowableValue MD5 = new AllowableValue("MD5", "MD5",
"Provides authentication based on the HMAC-MD5 algorithm.");
public static final AllowableValue SHA = new AllowableValue("SHA", "SHA",
"Provides authentication based on the HMAC-SHA algorithm.");
public static final AllowableValue HMAC128SHA224 = new AllowableValue("HMAC128SHA224", "SHA224",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC192SHA256 = new AllowableValue("HMAC192SHA256", "SHA256",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC256SHA384 = new AllowableValue("HMAC256SHA384", "SHA384",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC384SHA512 = new AllowableValue("HMAC384SHA512", "SHA512",
SHA_2_ALGORITHM);
// SNMPv3 encryption
public static final AllowableValue DES = new AllowableValue("DES", "DES",
"Symmetric-key algorithm for the encryption of digital data. DES has been considered insecure" +
"because of the feasilibity of brute-force attacks. We recommend using the AES encryption protocol.");
public static final AllowableValue DES3 = new AllowableValue("3DES", "3DES",
"Symmetric-key block cipher, which applies the DES cipher algorithm three times to each data block." +
" 3DES has been considered insecure has been deprecated by NIST in 2017. We recommend using the AES encryption protocol.");
private static final String AES_DESCRIPTION = "AES is a symmetric algorithm which uses the same 128, 192, or 256 bit" +
" key for both encryption and decryption (the security of an AES system increases exponentially with key length).";
public static final AllowableValue AES128 = new AllowableValue("AES128", "AES128", AES_DESCRIPTION);
public static final AllowableValue AES192 = new AllowableValue("AES192", "AES192", AES_DESCRIPTION);
public static final AllowableValue AES256 = new AllowableValue("AES256", "AES256", AES_DESCRIPTION);
public static final PropertyDescriptor AGENT_HOST = new PropertyDescriptor.Builder()
.name("snmp-hostname")
@ -117,136 +73,31 @@ abstract class AbstractSNMPProcessor extends AbstractProcessor {
.addValidator(StandardValidators.PORT_VALIDATOR)
.build();
public static final PropertyDescriptor SNMP_VERSION = new PropertyDescriptor.Builder()
.name("snmp-version")
.displayName("SNMP Version")
.description("Three significant versions of SNMP have been developed and deployed. " +
"SNMPv1 is the original version of the protocol. More recent versions, " +
"SNMPv2c and SNMPv3, feature improvements in performance, flexibility and security.")
.required(true)
.allowableValues(SNMP_V1, SNMP_V2C, SNMP_V3)
.defaultValue(SNMP_V1.getValue())
.build();
public static final PropertyDescriptor SNMP_COMMUNITY = new PropertyDescriptor.Builder()
.name("snmp-community")
.displayName("SNMP Community")
.description("SNMPv1 and SNMPv2 use communities to establish trust between managers and agents." +
" Most agents support three community names, one each for read-only, read-write and trap." +
" These three community strings control different types of activities. The read-only community" +
" applies to get requests. The read-write community string applies to set requests. The trap" +
" community string applies to receipt of traps.")
.required(true)
.sensitive(true)
.defaultValue("public")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V1, SNMP_V2C)
.build();
public static final PropertyDescriptor SNMP_SECURITY_LEVEL = new PropertyDescriptor.Builder()
.name("snmp-security-level")
.displayName("SNMP Security Level")
.description("SNMP version 3 provides extra security with User Based Security Model (USM). The three levels of security is " +
"1. Communication without authentication and encryption (NoAuthNoPriv). " +
"2. Communication with authentication and without encryption (AuthNoPriv). " +
"3. Communication with authentication and encryption (AuthPriv).")
.required(true)
.allowableValues(NO_AUTH_NO_PRIV, AUTH_NO_PRIV, AUTH_PRIV)
.defaultValue(NO_AUTH_NO_PRIV.getValue())
.dependsOn(SNMP_VERSION, SNMP_V3)
.build();
public static final PropertyDescriptor SNMP_SECURITY_NAME = new PropertyDescriptor.Builder()
.name("snmp-security-name")
.displayName("SNMP Security Name")
.description("User name used for SNMP v3 Authentication.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V3)
.build();
public static final PropertyDescriptor SNMP_AUTH_PROTOCOL = new PropertyDescriptor.Builder()
.name("snmp-authentication-protocol")
.displayName("SNMP Authentication Protocol")
.description("Hash based authentication protocol for secure authentication.")
.required(true)
.allowableValues(MD5, SHA, HMAC128SHA224, HMAC192SHA256, HMAC256SHA384, HMAC384SHA512)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_NO_PRIV, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_AUTH_PASSWORD = new PropertyDescriptor.Builder()
.name("snmp-authentication-passphrase")
.displayName("SNMP Authentication Passphrase")
.description("Passphrase used for SNMP authentication protocol.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_NO_PRIV, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_PRIVACY_PROTOCOL = new PropertyDescriptor.Builder()
.name("snmp-private-protocol")
.displayName("SNMP Privacy Protocol")
.description("Privacy allows for encryption of SNMP v3 messages to ensure confidentiality of data.")
.required(true)
.allowableValues(DES, DES3, AES128, AES192, AES256)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_PRIVACY_PASSWORD = new PropertyDescriptor.Builder()
.name("snmp-private-protocol-passphrase")
.displayName("SNMP Privacy Passphrase")
.description("Passphrase used for SNMP privacy protocol.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_RETRIES = new PropertyDescriptor.Builder()
.name("snmp-retries")
.displayName("Number of Retries")
.description("Set the number of retries when requesting the SNMP Agent.")
.required(false)
.defaultValue("0")
.addValidator(StandardValidators.NON_NEGATIVE_INTEGER_VALIDATOR)
.build();
public static final PropertyDescriptor SNMP_TIMEOUT = new PropertyDescriptor.Builder()
.name("snmp-timeout")
.displayName("Timeout (ms)")
.description("Set the timeout (in milliseconds) when requesting the SNMP Agent.")
.required(false)
.defaultValue("5000")
.addValidator(StandardValidators.NON_NEGATIVE_INTEGER_VALIDATOR)
.build();
protected volatile SNMPRequestHandler snmpRequestHandler;
protected volatile SNMPResourceHandler snmpResourceHandler;
@OnScheduled
public void initSnmpManager(final ProcessContext context) throws InitializationException {
final int version = SNMPUtils.getVersion(context.getProperty(SNMP_VERSION).getValue());
public void initSnmpManager(final ProcessContext context) {
final int version = SNMPUtils.getVersion(context.getProperty(BasicProperties.SNMP_VERSION).getValue());
final SNMPConfiguration configuration;
try {
configuration = new SNMPConfigurationBuilder()
.setAgentHost(context.getProperty(AGENT_HOST).getValue())
.setAgentPort(context.getProperty(AGENT_PORT).toString())
.setRetries(context.getProperty(SNMP_RETRIES).asInteger())
.setTimeout(context.getProperty(SNMP_TIMEOUT).asInteger())
.setVersion(version)
.setAuthProtocol(context.getProperty(SNMP_AUTH_PROTOCOL).getValue())
.setAuthPassphrase(context.getProperty(SNMP_AUTH_PASSWORD).getValue())
.setPrivacyProtocol(context.getProperty(SNMP_PRIVACY_PROTOCOL).getValue())
.setPrivacyPassphrase(context.getProperty(SNMP_PRIVACY_PASSWORD).getValue())
.setSecurityName(context.getProperty(SNMP_SECURITY_NAME).getValue())
.setSecurityLevel(context.getProperty(SNMP_SECURITY_LEVEL).getValue())
.setCommunityString(context.getProperty(SNMP_COMMUNITY).getValue())
.build();
} catch (IllegalStateException e) {
throw new InitializationException(e);
}
snmpRequestHandler = SNMPRequestHandlerFactory.createStandardRequestHandler(configuration);
final String targetHost = getTargetHost(context);
final String targetPort = getTargetPort(context);
configuration = SNMPConfiguration.builder()
.setTargetHost(targetHost)
.setTargetPort(targetPort)
.setRetries(context.getProperty(BasicProperties.SNMP_RETRIES).asInteger())
.setTimeoutInMs(context.getProperty(BasicProperties.SNMP_TIMEOUT).asInteger())
.setVersion(version)
.setAuthProtocol(context.getProperty(V3SecurityProperties.SNMP_AUTH_PROTOCOL).getValue())
.setAuthPassphrase(context.getProperty(V3SecurityProperties.SNMP_AUTH_PASSWORD).getValue())
.setPrivacyProtocol(context.getProperty(V3SecurityProperties.SNMP_PRIVACY_PROTOCOL).getValue())
.setPrivacyPassphrase(context.getProperty(V3SecurityProperties.SNMP_PRIVACY_PASSWORD).getValue())
.setSecurityName(context.getProperty(V3SecurityProperties.SNMP_SECURITY_NAME).getValue())
.setSecurityLevel(context.getProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL).getValue())
.setCommunityString(context.getProperty(BasicProperties.SNMP_COMMUNITY).getValue())
.build();
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(configuration);
}
/**
@ -254,61 +105,61 @@ abstract class AbstractSNMPProcessor extends AbstractProcessor {
*/
@OnStopped
public void close() {
if (snmpRequestHandler != null) {
snmpRequestHandler.close();
snmpRequestHandler = null;
if (snmpResourceHandler != null) {
snmpResourceHandler.close();
snmpResourceHandler = null;
}
}
/**
* Method to add attribute in flow file
*
* @param key attribute key
* @param value attribute value
* @param flowFile flow file to update
* @param processSession session
* @return updated flow file
*/
protected FlowFile addAttribute(final String key, final String value, FlowFile flowFile, final ProcessSession processSession) {
final Map<String, String> attributes = new HashMap<>();
attributes.put(key, value);
flowFile = processSession.putAllAttributes(flowFile, attributes);
return flowFile;
protected void handleResponse(final ProcessContext context, final ProcessSession processSession, final FlowFile flowFile, final SNMPSingleResponse response,
final Relationship success, final Relationship failure, final String provenanceAddress) {
final SNMPResponseStatus snmpResponseStatus = processResponse(response);
processSession.putAllAttributes(flowFile, response.getAttributes());
if (snmpResponseStatus.getErrorStatus() == ErrorStatus.FAILURE) {
getLogger().error("SNMP request failed, response error: " + snmpResponseStatus.getErrorMessage());
processSession.getProvenanceReporter().modifyAttributes(flowFile, response.getTargetAddress() + provenanceAddress);
processSession.transfer(flowFile, failure);
context.yield();
} else {
processSession.getProvenanceReporter().modifyAttributes(flowFile, response.getTargetAddress() + provenanceAddress);
processSession.transfer(flowFile, success);
}
}
protected void processResponse(final ProcessSession processSession, FlowFile flowFile, final SNMPSingleResponse response,
final String provenanceAddress, final Relationship success) {
protected SNMPResponseStatus processResponse(final SNMPSingleResponse response) {
if (response.isValid()) {
if (response.isReportPdu()) {
final String oid = response.getVariableBindings().get(0).getOid();
final Optional<String> reportPduErrorMessage = SNMPUtils.getErrorMessage(oid);
if (!reportPduErrorMessage.isPresent()) {
throw new SNMPException(String.format("SNMP request failed, Report-PDU returned, but no error message found. " +
"Please, check the OID %s in an online OID repository.", oid));
return new SNMPResponseStatus(String.format("Report-PDU returned, but no error message found. " +
"Please, check the OID %s in an online OID repository.", oid), ErrorStatus.FAILURE);
}
throw new SNMPException("SNMPRequest failed, Report-PDU returned. " + reportPduErrorMessage.get());
return new SNMPResponseStatus("Report-PDU returned. " + reportPduErrorMessage.get(), ErrorStatus.FAILURE);
}
checkV2cV3VariableBindings(response);
flowFile = processSession.putAllAttributes(flowFile, response.getAttributes());
processSession.transfer(flowFile, success);
processSession.getProvenanceReporter().receive(flowFile, provenanceAddress);
return checkV2cV3VariableBindings(response);
} else {
final String error = response.getErrorStatusText();
throw new SNMPException("SNMP request failed, response error: " + error);
final String errorMessage = response.getErrorStatusText();
return new SNMPResponseStatus(errorMessage, ErrorStatus.FAILURE);
}
}
private void checkV2cV3VariableBindings(SNMPSingleResponse response) {
if (response.getVersion() != SnmpConstants.version1) {
private SNMPResponseStatus checkV2cV3VariableBindings(SNMPSingleResponse response) {
if (response.getVersion() == SnmpConstants.version2c || response.getVersion() == SnmpConstants.version3) {
final Optional<SNMPValue> firstVariableBinding = response.getVariableBindings().stream().findFirst();
if (firstVariableBinding.isPresent()) {
final String value = firstVariableBinding.get().getVariable();
if (NO_SUCH_OBJECT.equals(value)) {
throw new SNMPException("SNMP Request failed, OID not found.");
return new SNMPResponseStatus("OID not found.", ErrorStatus.FAILURE);
}
} else {
throw new SNMPException("Empty SNMP response: no variable binding found.");
return new SNMPResponseStatus("Empty SNMP response: no variable binding found.", ErrorStatus.FAILURE);
}
}
return new SNMPResponseStatus("Successful SNMP Response", ErrorStatus.SUCCESS);
}
protected abstract String getTargetHost(ProcessContext processContext);
protected abstract String getTargetPort(ProcessContext processContext);
}

View File

@ -22,6 +22,7 @@ import org.apache.nifi.annotation.behavior.WritesAttribute;
import org.apache.nifi.annotation.behavior.WritesAttributes;
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.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
@ -31,8 +32,10 @@ import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.SNMPException;
import org.apache.nifi.snmp.exception.SNMPWalkException;
import org.apache.nifi.snmp.operations.GetSNMPHandler;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.snmp.validators.OIDValidator;
@ -41,16 +44,20 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Retrieving data from configured SNMP agent which, upon each invocation of
* {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
* {@link FlowFile} containing in its properties the information retrieved.
* Performs an SNMP Get operation based on processor or incoming FlowFile attributes.
* Upon each invocation of {@link #onTrigger(ProcessContext, ProcessSession)}
* method, in case of a valid incoming FlowFile, it will inspect the attributes of
* the FlowFile and look for attributes with name formatted as "snmp$OID" to set the
* attribute value to this OID.
* The output {@link FlowFile} won't have any content.
*/
@Tags({"snmp", "get", "oid", "walk"})
@InputRequirement(Requirement.INPUT_FORBIDDEN)
@InputRequirement(Requirement.INPUT_ALLOWED)
@CapabilityDescription("Retrieves information from SNMP Agent with SNMP Get request and outputs a FlowFile with information" +
" in attributes and without any content")
@WritesAttributes({
@ -74,11 +81,12 @@ public class GetSNMP extends AbstractSNMPProcessor {
"A manager-to-agent request to retrieve the value of multiple variables. Snmp WALK also traverses all subnodes " +
"under the specified OID.");
// OID to request (if walk, it is the root ID of the request).
public static final PropertyDescriptor OID = new PropertyDescriptor.Builder()
.name("snmp-oid")
.displayName("OID")
.description("Each OID (object identifier) identifies a variable that can be read or set via SNMP.")
.description("Each OID (object identifier) identifies a variable that can be read or set via SNMP." +
" This value is not taken into account for an input flowfile and will be omitted. Can be set to empty" +
"string when the OIDs are provided through flowfile.")
.required(true)
.addValidator(new OIDValidator())
.build();
@ -95,7 +103,8 @@ public class GetSNMP extends AbstractSNMPProcessor {
public static final PropertyDescriptor TEXTUAL_OID = new PropertyDescriptor.Builder()
.name("snmp-textual-oid")
.displayName("Textual OID")
.description("The textual OID to request.")
.description("The textual form of the numeric OID to request. This property is user defined, not processed and appended to " +
"the outgoing flowfile.")
.required(false)
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.defaultValue(null)
@ -114,16 +123,16 @@ public class GetSNMP extends AbstractSNMPProcessor {
protected static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
AGENT_HOST,
AGENT_PORT,
SNMP_VERSION,
SNMP_COMMUNITY,
SNMP_SECURITY_LEVEL,
SNMP_SECURITY_NAME,
SNMP_AUTH_PROTOCOL,
SNMP_AUTH_PASSWORD,
SNMP_PRIVACY_PROTOCOL,
SNMP_PRIVACY_PASSWORD,
SNMP_RETRIES,
SNMP_TIMEOUT,
BasicProperties.SNMP_VERSION,
BasicProperties.SNMP_COMMUNITY,
V3SecurityProperties.SNMP_SECURITY_LEVEL,
V3SecurityProperties.SNMP_SECURITY_NAME,
V3SecurityProperties.SNMP_AUTH_PROTOCOL,
V3SecurityProperties.SNMP_AUTH_PASSWORD,
V3SecurityProperties.SNMP_PRIVACY_PROTOCOL,
V3SecurityProperties.SNMP_PRIVACY_PASSWORD,
BasicProperties.SNMP_RETRIES,
BasicProperties.SNMP_TIMEOUT,
OID,
TEXTUAL_OID,
SNMP_STRATEGY
@ -134,54 +143,100 @@ public class GetSNMP extends AbstractSNMPProcessor {
REL_FAILURE
)));
private volatile GetSNMPHandler snmpHandler;
@OnScheduled
public void init(final ProcessContext context) {
initSnmpManager(context);
snmpHandler = new GetSNMPHandler(snmpResourceHandler);
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession processSession) {
final SNMPStrategy snmpStrategy = SNMPStrategy.valueOf(context.getProperty(SNMP_STRATEGY).getValue());
final String oid = context.getProperty(OID).getValue();
final FlowFile flowfile = processSession.get();
if (SNMPStrategy.GET == snmpStrategy) {
performSnmpGet(context, processSession, oid);
performSnmpGet(context, processSession, oid, flowfile);
} else if (SNMPStrategy.WALK == snmpStrategy) {
performSnmpWalk(context, processSession, oid);
performSnmpWalk(context, processSession, oid, flowfile);
}
}
private void performSnmpWalk(final ProcessContext context, final ProcessSession processSession, final String oid) {
void performSnmpWalk(final ProcessContext context, final ProcessSession processSession, final String oid,
final FlowFile flowFile) {
try {
final SNMPTreeResponse response = snmpRequestHandler.walk(oid);
response.logErrors(getLogger());
FlowFile flowFile = createFlowFileWithTreeEventProperties(response, processSession);
processSession.getProvenanceReporter().receive(flowFile, response.getTargetAddress() + "/" + oid);
processSession.transfer(flowFile, REL_SUCCESS);
if (flowFile != null) {
performSnmpWalkWithFlowFile(processSession, flowFile);
} else {
performSnmpWalkWithoutFlowFile(processSession, oid);
}
} catch (SNMPWalkException e) {
getLogger().error(e.getMessage());
context.yield();
processSession.rollback();
}
}
private void performSnmpGet(final ProcessContext context, final ProcessSession processSession, final String oid) {
final SNMPSingleResponse response;
private void performSnmpWalkWithFlowFile(ProcessSession processSession, FlowFile flowFile) {
final Optional<SNMPTreeResponse> optionalResponse = snmpHandler.walk(flowFile.getAttributes());
if (optionalResponse.isPresent()) {
final SNMPTreeResponse response = optionalResponse.get();
response.logErrors(getLogger());
processSession.putAllAttributes(flowFile, response.getAttributes());
processSession.getProvenanceReporter().modifyAttributes(flowFile, response.getTargetAddress() + "/walk");
processSession.transfer(flowFile, response.isError() ? REL_FAILURE : REL_SUCCESS);
} else {
getLogger().warn("No SNMP specific attributes found in flowfile.");
processSession.getProvenanceReporter().receive(flowFile, "/walk");
processSession.transfer(flowFile, REL_FAILURE);
}
}
private void performSnmpWalkWithoutFlowFile(ProcessSession processSession, String oid) {
final SNMPTreeResponse response = snmpHandler.walk(oid);
response.logErrors(getLogger());
final FlowFile outgoingFlowFile = processSession.create();
processSession.putAllAttributes(outgoingFlowFile, response.getAttributes());
processSession.getProvenanceReporter().create(outgoingFlowFile, response.getTargetAddress() + "/walk");
processSession.transfer(outgoingFlowFile, REL_SUCCESS);
}
void performSnmpGet(final ProcessContext context, final ProcessSession processSession, final String oid,
final FlowFile flowFile) {
final String textualOidKey = SNMPUtils.SNMP_PROP_PREFIX + "textualOid";
final Map<String, String> textualOidMap = Collections.singletonMap(textualOidKey, context.getProperty(TEXTUAL_OID).getValue());
try {
response = snmpRequestHandler.get(oid);
final FlowFile flowFile = processSession.create();
addAttribute(SNMPUtils.SNMP_PROP_PREFIX + "textualOid", context.getProperty(TEXTUAL_OID).getValue(), flowFile, processSession);
final String provenanceAddress = response.getTargetAddress() + "/" + oid;
processResponse(processSession, flowFile, response, provenanceAddress, REL_SUCCESS);
} catch (SNMPException e) {
getLogger().error(e.getMessage());
context.yield();
processSession.rollback();
if (flowFile != null) {
performSnmpGetWithFlowFile(context, processSession, flowFile, textualOidMap);
} else {
performSnmpGetWithoutFlowFile(context, processSession, oid, textualOidMap);
}
} catch (IOException e) {
getLogger().error("Failed to send request to the agent. Check if the agent supports the used version.");
getLogger().error("Failed to send request to the agent. Check if the agent supports the used version.", e);
context.yield();
processSession.rollback();
}
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return PROPERTY_DESCRIPTORS;
private void performSnmpGetWithoutFlowFile(ProcessContext context, ProcessSession processSession, String oid, Map<String, String> textualOidMap) throws IOException {
final SNMPSingleResponse response = snmpHandler.get(oid);
final FlowFile outgoingFlowFile = processSession.create();
processSession.putAllAttributes(outgoingFlowFile, textualOidMap);
processSession.getProvenanceReporter().receive(outgoingFlowFile, response.getTargetAddress() + "/get");
handleResponse(context, processSession, outgoingFlowFile, response, REL_SUCCESS, REL_FAILURE, "/get");
}
private void performSnmpGetWithFlowFile(ProcessContext context, ProcessSession processSession, FlowFile flowFile, Map<String, String> textualOidMap) throws IOException {
final Optional<SNMPSingleResponse> optionalResponse = snmpHandler.get(flowFile.getAttributes());
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
processSession.putAllAttributes(flowFile, textualOidMap);
handleResponse(context, processSession, flowFile, response, REL_SUCCESS, REL_FAILURE, "/get");
} else {
getLogger().warn("No SNMP specific attributes found in flowfile.");
processSession.transfer(flowFile, REL_FAILURE);
context.yield();
}
}
@Override
@ -189,10 +244,18 @@ public class GetSNMP extends AbstractSNMPProcessor {
return RELATIONSHIPS;
}
private FlowFile createFlowFileWithTreeEventProperties(final SNMPTreeResponse response, final ProcessSession processSession) {
FlowFile flowFile = processSession.create();
flowFile = processSession.putAllAttributes(flowFile, response.getAttributes());
return flowFile;
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return PROPERTY_DESCRIPTORS;
}
protected String getTargetHost(ProcessContext processContext) {
return processContext.getProperty(AGENT_HOST).getValue();
}
@Override
protected String getTargetPort(ProcessContext processContext) {
return processContext.getProperty(AGENT_PORT).getValue();
}
private enum SNMPStrategy {

View File

@ -0,0 +1,143 @@
/*
* 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.processors;
import org.apache.nifi.annotation.behavior.InputRequirement;
import org.apache.nifi.annotation.behavior.RequiresInstanceClassLoading;
import org.apache.nifi.annotation.behavior.WritesAttribute;
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.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
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.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.SNMPUtils;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Receiving data from a configured SNMP agent which, upon each invocation of
* {@link #onTrigger(ProcessContext, ProcessSessionFactory)} method, will construct a
* {@link FlowFile} containing in its properties the information retrieved.
* The output {@link FlowFile} won't have any content.
*/
@Tags({"snmp", "listen", "trap"})
@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
@CapabilityDescription("Receives information from SNMP Agent and outputs a FlowFile with information in attributes and without any content")
@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 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()
.name("snmp-usm-users-file-path")
.displayName("SNMP Users File Path")
.description("The path of the json file containing the user credentials for SNMPv3. Check Usage for more details.")
.required(true)
.defaultValue("")
.dependsOn(BasicProperties.SNMP_VERSION, BasicProperties.SNMP_V3)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final Relationship REL_SUCCESS = new Relationship.Builder()
.name("success")
.description("All FlowFiles that are received from the SNMP agent are routed to this relationship")
.build();
public static final Relationship REL_FAILURE = new Relationship.Builder()
.name("failure")
.description("All FlowFiles that cannot received from the SNMP agent are routed to this relationship")
.build();
protected static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
SNMP_MANAGER_PORT,
BasicProperties.SNMP_VERSION,
BasicProperties.SNMP_COMMUNITY,
V3SecurityProperties.SNMP_SECURITY_LEVEL,
SNMP_USM_USERS_FILE_PATH
));
private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
REL_SUCCESS,
REL_FAILURE
)));
private volatile SNMPTrapReceiverHandler snmpTrapReceiverHandler;
@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();
SNMPConfiguration configuration;
configuration = SNMPConfiguration.builder()
.setManagerPort(managerPort)
.setVersion(version)
.setSecurityLevel(context.getProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL).getValue())
.setCommunityString(context.getProperty(BasicProperties.SNMP_COMMUNITY).getValue())
.build();
snmpTrapReceiverHandler = new SNMPTrapReceiverHandler(configuration, usmUsersFilePath);
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSessionFactory processSessionFactory) {
if (!snmpTrapReceiverHandler.isStarted()) {
snmpTrapReceiverHandler.createTrapReceiver(processSessionFactory, getLogger());
}
}
@OnStopped
public void close() {
if (snmpTrapReceiverHandler != null) {
snmpTrapReceiverHandler.close();
}
}
@Override
public Set<Relationship> getRelationships() {
return RELATIONSHIPS;
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return PROPERTY_DESCRIPTORS;
}
}

View File

@ -0,0 +1,170 @@
/*
* 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.processors;
import org.apache.nifi.annotation.behavior.InputRequirement;
import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
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.components.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.operations.SendTrapSNMPHandler;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V1TrapProperties;
import org.apache.nifi.snmp.processors.properties.V2TrapProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.snmp4j.mp.SnmpConstants;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Sends data to an SNMP manager which, upon each invocation of
* {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
* {@link FlowFile} containing in its properties the information retrieved.
* The output {@link FlowFile} won't have any content.
*/
@Tags({"snmp", "send", "trap"})
@InputRequirement(Requirement.INPUT_ALLOWED)
@CapabilityDescription("Sends information to SNMP Manager.")
public class SendTrapSNMP extends AbstractSNMPProcessor {
public static final PropertyDescriptor SNMP_MANAGER_HOST = new PropertyDescriptor.Builder()
.name("snmp-trap-manager-host")
.displayName("SNMP Manager Host")
.description("The host where the SNMP Manager sends the trap.")
.required(true)
.defaultValue("localhost")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final PropertyDescriptor SNMP_MANAGER_PORT = new PropertyDescriptor.Builder()
.name("snmp-trap-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 Relationship REL_SUCCESS = new Relationship.Builder()
.name("success")
.description("All FlowFiles that have been successfully used to perform SNMP Set are routed to this relationship")
.build();
public static final Relationship REL_FAILURE = new Relationship.Builder()
.name("failure")
.description("All FlowFiles that cannot received from the SNMP agent are routed to this relationship")
.build();
protected static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
SNMP_MANAGER_HOST,
SNMP_MANAGER_PORT,
BasicProperties.SNMP_VERSION,
BasicProperties.SNMP_COMMUNITY,
V3SecurityProperties.SNMP_SECURITY_LEVEL,
V3SecurityProperties.SNMP_SECURITY_NAME,
V3SecurityProperties.SNMP_AUTH_PROTOCOL,
V3SecurityProperties.SNMP_AUTH_PASSWORD,
V3SecurityProperties.SNMP_PRIVACY_PROTOCOL,
V3SecurityProperties.SNMP_PRIVACY_PASSWORD,
BasicProperties.SNMP_RETRIES,
BasicProperties.SNMP_TIMEOUT,
V1TrapProperties.ENTERPRISE_OID,
V1TrapProperties.AGENT_ADDRESS,
V1TrapProperties.GENERIC_TRAP_TYPE,
V1TrapProperties.SPECIFIC_TRAP_TYPE,
V2TrapProperties.TRAP_OID_VALUE
));
private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
REL_SUCCESS, REL_FAILURE
)));
private volatile SendTrapSNMPHandler snmpHandler;
@OnScheduled
public void init(ProcessContext context) {
Instant startTime = Instant.now();
initSnmpManager(context);
snmpHandler = new SendTrapSNMPHandler(snmpResourceHandler, startTime, getLogger());
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession processSession) {
final FlowFile flowFile = processSession.get();
if (flowFile != null) {
try {
final int snmpVersion = SNMPUtils.getVersion(context.getProperty(BasicProperties.SNMP_VERSION).getValue());
if (SnmpConstants.version1 == snmpVersion) {
V1TrapConfiguration v1TrapConfiguration = V1TrapConfiguration.builder()
.enterpriseOid(context.getProperty(V1TrapProperties.ENTERPRISE_OID).evaluateAttributeExpressions(flowFile).getValue())
.agentAddress(context.getProperty(V1TrapProperties.AGENT_ADDRESS).evaluateAttributeExpressions(flowFile).getValue())
.genericTrapType(context.getProperty(V1TrapProperties.GENERIC_TRAP_TYPE).evaluateAttributeExpressions(flowFile).getValue())
.specificTrapType(context.getProperty(V1TrapProperties.SPECIFIC_TRAP_TYPE).evaluateAttributeExpressions(flowFile).getValue())
.build();
snmpHandler.sendTrap(flowFile.getAttributes(), v1TrapConfiguration);
} else {
V2TrapConfiguration v2TrapConfiguration = new V2TrapConfiguration(
context.getProperty(V2TrapProperties.TRAP_OID_VALUE).evaluateAttributeExpressions(flowFile).getValue()
);
snmpHandler.sendTrap(flowFile.getAttributes(), v2TrapConfiguration);
}
processSession.transfer(flowFile, REL_SUCCESS);
} catch (IOException e) {
getLogger().error("Failed to send request to the agent. Check if the agent supports the used version.", e);
processSession.transfer(processSession.penalize(flowFile), REL_FAILURE);
} catch (IllegalArgumentException e) {
getLogger().error("Invalid trap configuration.", e);
processSession.transfer(processSession.penalize(flowFile), REL_FAILURE);
}
}
}
@Override
public Set<Relationship> getRelationships() {
return RELATIONSHIPS;
}
@Override
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
return PROPERTY_DESCRIPTORS;
}
@Override
protected String getTargetHost(ProcessContext processContext) {
return processContext.getProperty(SNMP_MANAGER_HOST).getValue();
}
@Override
protected String getTargetPort(ProcessContext processContext) {
return processContext.getProperty(SNMP_MANAGER_PORT).getValue();
}
}

View File

@ -22,13 +22,16 @@ import org.apache.nifi.annotation.behavior.WritesAttribute;
import org.apache.nifi.annotation.behavior.WritesAttributes;
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.components.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.exception.SNMPException;
import org.apache.nifi.snmp.operations.SetSNMPHandler;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
import org.apache.nifi.snmp.utils.SNMPUtils;
import java.io.IOException;
@ -36,19 +39,21 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* Performs a SNMP Set operation based on attributes of incoming FlowFile.
* Performs an SNMP Set operation based on attributes of incoming FlowFile.
* Upon each invocation of {@link #onTrigger(ProcessContext, ProcessSession)}
* method, it will inspect attributes of FlowFile and look for attributes with
* name formatted as "snmp$OID" to set the attribute value to this OID.
* The output {@link FlowFile} won't have any content.
*/
@Tags({"snmp", "set", "oid"})
@InputRequirement(Requirement.INPUT_REQUIRED)
@CapabilityDescription("Based on incoming FlowFile attributes, the processor will execute SNMP Set requests." +
" When finding attributes with the name snmp$<OID>, the processor will attempt to set the value of" +
" the attribute to the corresponding OID given in the attribute name")
" the attribute to the corresponding OID given in the attribute name.")
@WritesAttributes({
@WritesAttribute(attribute = SNMPUtils.SNMP_PROP_PREFIX + "<OID>", description = "Response variable binding: OID (e.g. 1.3.6.1.4.1.343) and its value."),
@WritesAttribute(attribute = SNMPUtils.SNMP_PROP_PREFIX + "errorIndex", description = "Denotes the variable binding in which the error occured."),
@ -74,16 +79,16 @@ public class SetSNMP extends AbstractSNMPProcessor {
private static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
AGENT_HOST,
AGENT_PORT,
SNMP_VERSION,
SNMP_COMMUNITY,
SNMP_SECURITY_LEVEL,
SNMP_SECURITY_NAME,
SNMP_AUTH_PROTOCOL,
SNMP_AUTH_PASSWORD,
SNMP_PRIVACY_PROTOCOL,
SNMP_PRIVACY_PASSWORD,
SNMP_RETRIES,
SNMP_TIMEOUT
BasicProperties.SNMP_VERSION,
BasicProperties.SNMP_COMMUNITY,
V3SecurityProperties.SNMP_SECURITY_LEVEL,
V3SecurityProperties.SNMP_SECURITY_NAME,
V3SecurityProperties.SNMP_AUTH_PROTOCOL,
V3SecurityProperties.SNMP_AUTH_PASSWORD,
V3SecurityProperties.SNMP_PRIVACY_PROTOCOL,
V3SecurityProperties.SNMP_PRIVACY_PASSWORD,
BasicProperties.SNMP_RETRIES,
BasicProperties.SNMP_TIMEOUT
));
private static final Set<Relationship> RELATIONSHIPS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
@ -91,19 +96,34 @@ public class SetSNMP extends AbstractSNMPProcessor {
REL_FAILURE
)));
private volatile SetSNMPHandler snmpHandler;
@OnScheduled
public void init(final ProcessContext context) {
initSnmpManager(context);
snmpHandler = new SetSNMPHandler(snmpResourceHandler);
}
@Override
public void onTrigger(final ProcessContext context, final ProcessSession processSession) {
final FlowFile flowFile = processSession.get();
if (flowFile != null) {
try {
final SNMPSingleResponse response = snmpRequestHandler.set(flowFile);
processResponse(processSession, flowFile, response, response.getTargetAddress(), REL_SUCCESS);
} catch (SNMPException e) {
getLogger().error(e.getMessage());
processError(context, processSession, flowFile);
final Optional<SNMPSingleResponse> optionalResponse = snmpHandler.set(flowFile.getAttributes());
if (optionalResponse.isPresent()) {
processSession.remove(flowFile);
final FlowFile outgoingFlowFile = processSession.create();
final SNMPSingleResponse response = optionalResponse.get();
processSession.getProvenanceReporter().receive(outgoingFlowFile, "/set");
handleResponse(context, processSession, outgoingFlowFile, response, REL_SUCCESS, REL_FAILURE, "/set");
} else {
getLogger().warn("No SNMP specific attributes found in flowfile.");
processSession.transfer(flowFile, REL_FAILURE);
}
} catch (IOException e) {
getLogger().error("Failed to send request to the agent. Check if the agent supports the used version.");
processError(context, processSession, flowFile);
processSession.transfer(processSession.penalize(flowFile), REL_FAILURE);
context.yield();
}
}
}
@ -118,9 +138,13 @@ public class SetSNMP extends AbstractSNMPProcessor {
return RELATIONSHIPS;
}
@Override
protected String getTargetHost(ProcessContext processContext) {
return processContext.getProperty(AGENT_HOST).getValue();
}
private void processError(final ProcessContext context, final ProcessSession processSession, final FlowFile flowFile) {
processSession.transfer(processSession.penalize(flowFile), REL_FAILURE);
context.yield();
@Override
protected String getTargetPort(ProcessContext processContext) {
return processContext.getProperty(AGENT_PORT).getValue();
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.processors.properties;
import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.processor.util.StandardValidators;
public class BasicProperties {
private BasicProperties() {
// Utility class, not needed to instantiate.
}
public static final AllowableValue SNMP_V1 = new AllowableValue("SNMPv1", "v1", "SNMP version 1");
public static final AllowableValue SNMP_V2C = new AllowableValue("SNMPv2c", "v2c", "SNMP version 2c");
public static final AllowableValue SNMP_V3 = new AllowableValue("SNMPv3", "v3", "SNMP version 3 with improved security");
public static final PropertyDescriptor SNMP_VERSION = new PropertyDescriptor.Builder()
.name("snmp-version")
.displayName("SNMP Version")
.description("Three significant versions of SNMP have been developed and deployed. " +
"SNMPv1 is the original version of the protocol. More recent versions, " +
"SNMPv2c and SNMPv3, feature improvements in performance, flexibility and security.")
.required(true)
.allowableValues(SNMP_V1, SNMP_V2C, SNMP_V3)
.defaultValue(SNMP_V1.getValue())
.build();
public static final PropertyDescriptor SNMP_COMMUNITY = new PropertyDescriptor.Builder()
.name("snmp-community")
.displayName("SNMP Community")
.description("SNMPv1 and SNMPv2 use communities to establish trust between managers and agents." +
" Most agents support three community names, one each for read-only, read-write and trap." +
" These three community strings control different types of activities. The read-only community" +
" applies to get requests. The read-write community string applies to set requests. The trap" +
" community string applies to receipt of traps.")
.required(true)
.sensitive(true)
.defaultValue("public")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V1, SNMP_V2C)
.build();
public static final PropertyDescriptor SNMP_RETRIES = new PropertyDescriptor.Builder()
.name("snmp-retries")
.displayName("Number of Retries")
.description("Set the number of retries when requesting the SNMP Agent.")
.required(false)
.defaultValue("0")
.addValidator(StandardValidators.NON_NEGATIVE_INTEGER_VALIDATOR)
.build();
public static final PropertyDescriptor SNMP_TIMEOUT = new PropertyDescriptor.Builder()
.name("snmp-timeout")
.displayName("Timeout (ms)")
.description("Set the timeout in ms when requesting the SNMP Agent.")
.required(false)
.defaultValue("5000")
.addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
.build();
}

View File

@ -0,0 +1,80 @@
/*
* 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.processors.properties;
import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.util.StandardValidators;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_V1;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_VERSION;
public class V1TrapProperties {
private V1TrapProperties() {
// Utility class, not needed to instantiate.
}
private static final AllowableValue GENERIC_TRAP_TYPE_ENTERPRISE_SPECIFIC = new AllowableValue("6", "Enterprise Specific",
"An enterpriseSpecific trap signifies that a particular enterprise-specific trap has occurred which " +
"can be defined in the Specific Trap Type field.");
public static final PropertyDescriptor ENTERPRISE_OID = new PropertyDescriptor.Builder()
.name("snmp-trap-enterprise-oid")
.displayName("Enterprise OID")
.description("Enterprise is the vendor identification (OID) for the network management sub-system that generated the trap.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V1)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
public static final PropertyDescriptor AGENT_ADDRESS = new PropertyDescriptor.Builder()
.name("snmp-trap-agent-address")
.displayName("SNMP Trap Agent Address")
.description("The address where the SNMP Manager sends the trap.")
.required(true)
.defaultValue("0")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V1)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
public static final PropertyDescriptor GENERIC_TRAP_TYPE = new PropertyDescriptor.Builder()
.name("snmp-trap-generic-type")
.displayName("Generic Trap Type")
.description("Generic trap type is an integer in the range of 0 to 6. See processor usage for details.")
.required(false)
.addValidator(StandardValidators.createLongValidator(0, 6, true))
.dependsOn(SNMP_VERSION, SNMP_V1)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
public static final PropertyDescriptor SPECIFIC_TRAP_TYPE = new PropertyDescriptor.Builder()
.name("snmp-trap-specific-type")
.displayName("Specific Trap Type")
.description("Specific trap type is a number that further specifies the nature of the event that generated " +
"the trap in the case of traps of generic type 6 (enterpriseSpecific). The interpretation of this " +
"code is vendor-specific.")
.required(true)
.addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V1)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
}

View File

@ -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.processors.properties;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.util.StandardValidators;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_V2C;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_V3;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_VERSION;
public class V2TrapProperties {
private V2TrapProperties() {
// Utility class, not needed to instantiate.
}
public static final PropertyDescriptor TRAP_OID_VALUE = new PropertyDescriptor.Builder()
.name("snmp-trap-oid-value")
.displayName("Trap OID Value")
.description("The value of the trap OID.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V2C, SNMP_V3)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
}

View File

@ -0,0 +1,130 @@
/*
* 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.processors.properties;
import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.processor.util.StandardValidators;
import org.snmp4j.security.SecurityLevel;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_V3;
import static org.apache.nifi.snmp.processors.properties.BasicProperties.SNMP_VERSION;
public class V3SecurityProperties {
private V3SecurityProperties() {
// Utility class, not needed to instantiate.
}
private static final String SHA_2_ALGORITHM = "Provides authentication based on the HMAC-SHA-2 algorithm.";
private static final String AES_DESCRIPTION = "AES is a symmetric algorithm which uses the same 128, 192, or 256 bit" +
" key for both encryption and decryption (the security of an AES system increases exponentially with key length).";
// SNMPv3 security levels
public static final AllowableValue NO_AUTH_NO_PRIV = new AllowableValue(SecurityLevel.noAuthNoPriv.name(), SecurityLevel.noAuthNoPriv.name(),
"No authentication or encryption.");
public static final AllowableValue AUTH_NO_PRIV = new AllowableValue(SecurityLevel.authNoPriv.name(), SecurityLevel.authNoPriv.name(),
"Authentication without encryption.");
public static final AllowableValue AUTH_PRIV = new AllowableValue(SecurityLevel.authPriv.name(), SecurityLevel.authPriv.name(),
"Authentication and encryption.");
// SNMPv3 authentication protocols
public static final AllowableValue MD5 = new AllowableValue("MD5", "MD5",
"Provides authentication based on the HMAC-MD5 algorithm.");
public static final AllowableValue SHA = new AllowableValue("SHA", "SHA",
"Provides authentication based on the HMAC-SHA algorithm.");
public static final AllowableValue HMAC128SHA224 = new AllowableValue("HMAC128SHA224", "SHA224",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC192SHA256 = new AllowableValue("HMAC192SHA256", "SHA256",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC256SHA384 = new AllowableValue("HMAC256SHA384", "SHA384",
SHA_2_ALGORITHM);
public static final AllowableValue HMAC384SHA512 = new AllowableValue("HMAC384SHA512", "SHA512",
SHA_2_ALGORITHM);
// SNMPv3 encryption
public static final AllowableValue DES = new AllowableValue("DES", "DES",
"Symmetric-key algorithm for the encryption of digital data. DES has been considered insecure" +
"because of the feasilibity of brute-force attacks. We recommend using the AES encryption protocol.");
public static final AllowableValue DES3 = new AllowableValue("3DES", "3DES",
"Symmetric-key block cipher, which applies the DES cipher algorithm three times to each data block." +
" 3DES has been considered insecure has been deprecated by NIST in 2017. We recommend using the AES encryption protocol.");
public static final AllowableValue AES128 = new AllowableValue("AES128", "AES128", AES_DESCRIPTION);
public static final AllowableValue AES192 = new AllowableValue("AES192", "AES192", AES_DESCRIPTION);
public static final AllowableValue AES256 = new AllowableValue("AES256", "AES256", AES_DESCRIPTION);
public static final PropertyDescriptor SNMP_SECURITY_LEVEL = new PropertyDescriptor.Builder()
.name("snmp-security-level")
.displayName("SNMP Security Level")
.description("SNMP version 3 provides extra security with User Based Security Model (USM). The three levels of security is " +
"1. Communication without authentication and encryption (NoAuthNoPriv). " +
"2. Communication with authentication and without encryption (AuthNoPriv). " +
"3. Communication with authentication and encryption (AuthPriv).")
.required(true)
.allowableValues(NO_AUTH_NO_PRIV, AUTH_NO_PRIV, AUTH_PRIV)
.defaultValue(NO_AUTH_NO_PRIV.getValue())
.dependsOn(SNMP_VERSION, SNMP_V3)
.build();
public static final PropertyDescriptor SNMP_SECURITY_NAME = new PropertyDescriptor.Builder()
.name("snmp-security-name")
.displayName("SNMP Security Name")
.description("User name used for SNMP v3 Authentication.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.dependsOn(SNMP_VERSION, SNMP_V3)
.build();
public static final PropertyDescriptor SNMP_AUTH_PROTOCOL = new PropertyDescriptor.Builder()
.name("snmp-authentication-protocol")
.displayName("SNMP Authentication Protocol")
.description("Hash based authentication protocol for secure authentication.")
.required(true)
.allowableValues(MD5, SHA, HMAC128SHA224, HMAC192SHA256, HMAC256SHA384, HMAC384SHA512)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_NO_PRIV, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_AUTH_PASSWORD = new PropertyDescriptor.Builder()
.name("snmp-authentication-passphrase")
.displayName("SNMP Authentication Passphrase")
.description("Passphrase used for SNMP authentication protocol.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_NO_PRIV, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_PRIVACY_PROTOCOL = new PropertyDescriptor.Builder()
.name("snmp-private-protocol")
.displayName("SNMP Privacy Protocol")
.description("Privacy allows for encryption of SNMP v3 messages to ensure confidentiality of data.")
.required(true)
.allowableValues(DES, DES3, AES128, AES192, AES256)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_PRIV)
.build();
public static final PropertyDescriptor SNMP_PRIVACY_PASSWORD = new PropertyDescriptor.Builder()
.name("snmp-private-protocol-passphrase")
.displayName("SNMP Privacy Passphrase")
.description("Passphrase used for SNMP privacy protocol.")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(true)
.dependsOn(SNMP_SECURITY_LEVEL, AUTH_PRIV)
.build();
}

View File

@ -16,13 +16,13 @@
*/
package org.apache.nifi.snmp.utils;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.snmp.exception.InvalidAuthProtocolException;
import org.apache.nifi.snmp.exception.InvalidPrivProtocolException;
import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthHMAC128SHA224;
import org.snmp4j.security.AuthHMAC192SHA256;
@ -44,6 +44,7 @@ import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -67,8 +68,8 @@ public final class SNMPUtils {
private static final Map<String, OID> AUTH_MAP;
private static final Map<String, OID> PRIV_MAP;
private static final Map<String, Integer> VERSION_MAP;
private static final Map<String, String> REPORT_MAP;
private static final Map<String, Integer> VERSION_MAP;
private SNMPUtils() {
// hide implicit constructor
@ -132,12 +133,18 @@ public final class SNMPUtils {
return attributes;
}
/**
* Method to construct {@link FlowFile} attributes from a vector of {@link VariableBinding}
*
* @param variableBindings list of {@link VariableBinding}
* @return the attributes map
*/
public static Map<String, String> getV1TrapPduAttributeMap(final PDUv1 v1TrapPdu) {
final Map<String, String> trapAttributes = getPduAttributeMap(v1TrapPdu);
trapAttributes.computeIfAbsent(SNMP_PROP_PREFIX + "enterprise", v -> String.valueOf(v1TrapPdu.getEnterprise()));
trapAttributes.computeIfAbsent(SNMP_PROP_PREFIX + "agentAddress", v -> String.valueOf(v1TrapPdu.getAgentAddress()));
trapAttributes.computeIfAbsent(SNMP_PROP_PREFIX + "genericTrapType", v -> String.valueOf(v1TrapPdu.getGenericTrap()));
trapAttributes.computeIfAbsent(SNMP_PROP_PREFIX + "specificTrapType", v -> String.valueOf(v1TrapPdu.getSpecificTrap()));
trapAttributes.computeIfAbsent(SNMP_PROP_PREFIX + "timestamp", v -> String.valueOf(v1TrapPdu.getTimestamp()));
return trapAttributes;
}
public static Map<String, String> createWalkOidValuesMap(final List<VariableBinding> variableBindings) {
final Map<String, String> attributes = new HashMap<>();
variableBindings.forEach(vb -> addAttributeFromVariable(vb, attributes));
@ -159,46 +166,72 @@ public final class SNMPUtils {
throw new InvalidAuthProtocolException("Invalid authentication protocol provided.");
}
public static int getVersion(final String snmpVersion) {
return Optional.ofNullable(VERSION_MAP.get(snmpVersion))
.orElseThrow(() -> new InvalidSnmpVersionException("Invalid SNMP version provided."));
}
/**
* Method to construct {@link VariableBinding} based on {@link FlowFile}
* attributes in order to update the {@link PDU} that is going to be sent to
* the SNMP Agent.
*
* @param pdu {@link PDU} to be sent
* @param attributes {@link FlowFile} attributes
* @return true if at least one {@link VariableBinding} has been created, false otherwise
*/
public static boolean addVariables(final PDU pdu, final Map<String, String> attributes) {
boolean result = false;
for (Map.Entry<String, String> attributeEntry : attributes.entrySet()) {
if (attributeEntry.getKey().startsWith(SNMPUtils.SNMP_PROP_PREFIX)) {
final String[] splits = attributeEntry.getKey().split("\\" + SNMPUtils.SNMP_PROP_DELIMITER);
final String snmpPropName = splits[1];
final String snmpPropValue = attributeEntry.getValue();
if (SNMPUtils.OID_PATTERN.matcher(snmpPropName).matches()) {
final Optional<Variable> var;
if (splits.length == 2) { // no SMI syntax defined
var = Optional.of(new OctetString(snmpPropValue));
} else {
final int smiSyntax = Integer.parseInt(splits[2]);
var = SNMPUtils.stringToVariable(snmpPropValue, smiSyntax);
}
if (var.isPresent()) {
final VariableBinding varBind = new VariableBinding(new OID(snmpPropName), var.get());
pdu.add(varBind);
result = true;
try {
for (Map.Entry<String, String> attributeEntry : attributes.entrySet()) {
if (attributeEntry.getKey().startsWith(SNMPUtils.SNMP_PROP_PREFIX)) {
final String[] splits = attributeEntry.getKey().split("\\" + SNMPUtils.SNMP_PROP_DELIMITER);
final String snmpPropName = splits[1];
final String snmpPropValue = attributeEntry.getValue();
if (SNMPUtils.OID_PATTERN.matcher(snmpPropName).matches()) {
final Optional<Variable> var;
if (splits.length == 2) { // no SMI syntax defined
var = Optional.of(new OctetString(snmpPropValue));
} else {
final int smiSyntax = Integer.parseInt(splits[2]);
var = SNMPUtils.stringToVariable(snmpPropValue, smiSyntax);
}
if (var.isPresent()) {
final VariableBinding varBind = new VariableBinding(new OID(snmpPropName), var.get());
pdu.add(varBind);
result = true;
}
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
return false;
}
return result;
}
public static VariableBinding[] addGetVariables(final Map<String, String> attributes) {
List<VariableBinding> variableBindings = new ArrayList<>();
try {
for (Map.Entry<String, String> attributeEntry : attributes.entrySet()) {
if (attributeEntry.getKey().startsWith(SNMPUtils.SNMP_PROP_PREFIX)) {
final String[] splits = attributeEntry.getKey().split("\\" + SNMPUtils.SNMP_PROP_DELIMITER);
final String snmpPropName = splits[1];
if (SNMPUtils.OID_PATTERN.matcher(snmpPropName).matches()) {
variableBindings.add(new VariableBinding(new OID(snmpPropName)));
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
return new VariableBinding[0];
}
return variableBindings.toArray(new VariableBinding[0]);
}
public static OID[] addWalkVariables(final Map<String, String> attributes) {
List<OID> oids = new ArrayList<>();
try {
for (Map.Entry<String, String> attributeEntry : attributes.entrySet()) {
if (attributeEntry.getKey().startsWith(SNMPUtils.SNMP_PROP_PREFIX)) {
final String[] splits = attributeEntry.getKey().split("\\" + SNMPUtils.SNMP_PROP_DELIMITER);
final String snmpPropName = splits[1];
if (SNMPUtils.OID_PATTERN.matcher(snmpPropName).matches()) {
oids.add(new OID(snmpPropName));
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
return new OID[0];
}
return oids.toArray(new OID[0]);
}
private static void addAttributeFromVariable(final VariableBinding variableBinding, final Map<String, String> attributes) {
attributes.put(SNMP_PROP_PREFIX + variableBinding.getOid() + SNMP_PROP_DELIMITER + variableBinding.getVariable().getSyntax(), variableBinding.getVariable().toString());
}
@ -231,4 +264,9 @@ public final class SNMPUtils {
}
return errorMessage.map(s -> oid + ": " + s);
}
public static int getVersion(final String snmpVersion) {
return Optional.ofNullable(VERSION_MAP.get(snmpVersion))
.orElseThrow(() -> new InvalidSnmpVersionException("Invalid SNMP version provided."));
}
}

View File

@ -14,3 +14,5 @@
# limitations under the License.
org.apache.nifi.snmp.processors.GetSNMP
org.apache.nifi.snmp.processors.SetSNMP
org.apache.nifi.snmp.processors.SendTrapSNMP
org.apache.nifi.snmp.processors.ListenTrapSNMP

View File

@ -23,12 +23,19 @@
<body>
<h2>Summary</h2>
<p>
This processor polls a SNMP agent to get information for a given OID (Strategy = GET) or for all the sub-tree
associated to a given OID
This processor polls a SNMP agent to get information for a given OID or OIDs (Strategy = GET) or for all the sub-tree
associated to a given OID or OIDs
(Strategy = WALK). This processors supports SNMPv1, SNMPv2c and SNMPv3. The component is based on <a
href="http://www.snmp4j.org/">SNMP4J</a>.
</p>
<p>
The processor can compile the SNMP Get PDU from the attributes of an input flowfile (multiple OIDs can be specified)
or from a single OID specified in the processor property. In the former case, the processor will only consider the
OIDs specified in the flowfile.
The processor is looking for attributes prefixed with <i>snmp$</i>. If such an attribute is found, the attribute name is split using
the $ character. The second element must respect the OID format to be considered as a valid OID. The flowfile attribute
value can be empty (it will be later filled with the retrieved value and written into the outgoing flowfile).
When the processor is triggered, it sends the SNMP request and gets the information associated to request OID(s).
Once response is received
from the SNMP agent, a FlowFile is constructed. The FlowFile content is empty, all the information is written in the

View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">
<!--
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.
-->
<head>
<meta charset="utf-8"/>
<title>ListenTrapSNMP</title>
<link rel="stylesheet" href="../../../../../css/component-usage.css" type="text/css"/>
</head>
<body>
<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>.
</p>
<p>
In case of SNMPv3, users can be specified in a json file. E.g.:
<pre>
<code>
[
{
"securityName":"user1",
"authProtocol":"MD5",
"authPassphrase":"abc12345",
"privProtocol":"DES",
"privPassphrase":"abc12345"
},
{
"securityName":"newUser2",
"authProtocol":"MD5",
"authPassphrase":"abc12345",
"privProtocol":"AES256",
"privPassphrase":"abc12345"
}
]
</code>
</pre>
</p>
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<!--
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.
-->
<head>
<meta charset="utf-8"/>
<title>SendTrapSNMP</title>
<link rel="stylesheet" href="../../../../../css/component-usage.css" type="text/css"/>
</head>
<body>
<h2>Summary</h2>
<p>
This processor generates and transmits SNMP Traps to the specified SNMP manager. Attributes can be given
as processor properties, either predefined or dynamically using Expression Language from flowfiles.
Flowfile properties with snmp prefix (e.g. snmp$1.2.3.4.5 - OID) value can be used to define additional PDU variables.
</p>
<p>
The allowable Generic Trap Types are:
<ol start="0">
<li>Cold Start</li>
<li>Warm Start</li>
<li>Link Down</li>
<li>Link Up</li>
<li>Authentication Failure</li>
<li>EGP Neighbor Loss</li>
<li>Enterprise Specific</li>
</ol>
Specific trap type can set in case of Enterprise Specific generic trap type is chosen.
</p>
</body>
</html>

View File

@ -0,0 +1,75 @@
/*
* 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.configuration;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.junit.Test;
import org.snmp4j.mp.SnmpConstants;
import static org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory.COMMUNITY_STRING;
import static org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory.DEFAULT_HOST;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.AUTH_PASSPHRASE;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.AUTH_PROTOCOL;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.PRIV_PASSPHRASE;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.PRIV_PROTOCOL;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.SECURITY_LEVEL;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.SECURITY_NAME;
import static org.junit.Assert.assertEquals;
public class SNMPConfigurationTest {
private static final int MANAGER_PORT = NetworkUtils.availablePort();
private static final String TARGET_PORT = "55556";
private static final int RETRIES = 3;
private static final int VERSION = SnmpConstants.version3;
private static final int TIMEOUT_IN_MS = 3000;
@Test
public void testMembersAreSetCorrectly() {
final SNMPConfiguration snmpConfiguration = SNMPConfiguration.builder()
.setManagerPort(MANAGER_PORT)
.setTargetHost(DEFAULT_HOST)
.setTargetPort(TARGET_PORT)
.setRetries(RETRIES)
.setTimeoutInMs(TIMEOUT_IN_MS)
.setVersion(VERSION)
.setCommunityString(COMMUNITY_STRING)
.setSecurityLevel(SECURITY_LEVEL)
.setSecurityName(SECURITY_NAME)
.setAuthProtocol(AUTH_PROTOCOL)
.setAuthPassphrase(AUTH_PASSPHRASE)
.setPrivacyProtocol(PRIV_PROTOCOL)
.setPrivacyPassphrase(PRIV_PASSPHRASE)
.build();
assertEquals(MANAGER_PORT, snmpConfiguration.getManagerPort());
assertEquals(DEFAULT_HOST, snmpConfiguration.getTargetHost());
assertEquals(TARGET_PORT, snmpConfiguration.getTargetPort());
assertEquals(RETRIES, snmpConfiguration.getRetries());
assertEquals(TIMEOUT_IN_MS, snmpConfiguration.getTimeoutInMs());
assertEquals(VERSION, snmpConfiguration.getVersion());
assertEquals(COMMUNITY_STRING, snmpConfiguration.getCommunityString());
assertEquals(SECURITY_LEVEL, snmpConfiguration.getSecurityLevel());
assertEquals(SECURITY_NAME, snmpConfiguration.getSecurityName());
assertEquals(AUTH_PROTOCOL, snmpConfiguration.getAuthProtocol());
assertEquals(AUTH_PASSPHRASE, snmpConfiguration.getAuthPassphrase());
assertEquals(PRIV_PROTOCOL, snmpConfiguration.getPrivacyProtocol());
assertEquals(PRIV_PASSPHRASE, snmpConfiguration.getPrivacyPassphrase());
}
}

View File

@ -0,0 +1,141 @@
/*
* 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.configuration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
public class V1TrapConfigurationTest {
private static final String AGENT_ADDRESS = "127.0.0.1";
private static final String ENTERPRISE_OID = "1.3.6.1.4.1.8072.2.3.0.1";
private static final int GENERIC_TRAP_TYPE = 6;
private static final Integer SPECIFIC_TRAP_TYPE = 2;
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
@Test
public void testMembersAreSetCorrectly() {
final V1TrapConfiguration v1TrapConfiguration = V1TrapConfiguration.builder()
.enterpriseOid(ENTERPRISE_OID)
.agentAddress(AGENT_ADDRESS)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.specificTrapType(String.valueOf(SPECIFIC_TRAP_TYPE))
.build();
assertEquals(ENTERPRISE_OID, v1TrapConfiguration.getEnterpriseOid());
assertEquals(AGENT_ADDRESS, v1TrapConfiguration.getAgentAddress());
assertEquals(GENERIC_TRAP_TYPE, v1TrapConfiguration.getGenericTrapType());
assertEquals(SPECIFIC_TRAP_TYPE, v1TrapConfiguration.getSpecificTrapType());
}
@Test
public void testRequireNonNullEnterpriseOid() {
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Enterprise OID must be specified.");
V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.specificTrapType(String.valueOf(SPECIFIC_TRAP_TYPE))
.build();
}
@Test
public void testRequireNonNullAgentAddress() {
exceptionRule.expect(IllegalArgumentException.class);
exceptionRule.expectMessage("Agent address must be specified.");
V1TrapConfiguration.builder()
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.specificTrapType(String.valueOf(SPECIFIC_TRAP_TYPE))
.build();
}
@Test
public void testGenericTypeIsNegative() {
final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType("-1")
.build()
);
assertEquals("Generic Trap Type must be between 0 and 6.", exception.getMessage());
}
@Test
public void testGenericTypeIsGreaterThan6() {
final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType("7")
.build()
);
assertEquals("Generic Trap Type must be between 0 and 6.", exception.getMessage());
}
@Test
public void testGenericTypeIsNotANumber() {
final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType("invalid")
.build()
);
assertEquals("Generic Trap Type is not a number.", exception.getMessage());
}
@Test
public void testSpecificTrapTypeIsNegative() {
final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.enterpriseOid(ENTERPRISE_OID)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.specificTrapType("-1")
.build()
);
assertEquals("Specific Trap Type must be between 0 and 2147483647.", exception.getMessage());
}
@Test
public void testGenericTrapTypeIsEnterpriseSpecificButSpecificTrapTypeIsNotSet() {
final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> V1TrapConfiguration.builder()
.agentAddress(AGENT_ADDRESS)
.enterpriseOid(ENTERPRISE_OID)
.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());
}
@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());
}
}

View File

@ -0,0 +1,165 @@
/*
* 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;
import org.apache.nifi.util.LogMessage;
import org.apache.nifi.util.MockComponentLog;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Target;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.TreeEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SNMPTreeResponseTest {
private static final String SNMP_SEPARATOR = "$";
private static final String SNMP_PREFIX = "snmp" + SNMP_SEPARATOR;
private static final String VB_SYNTAX = "4";
private static final String OID_1 = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
private static final String OID_2 = "1.3.6.1.4.1.32437.1.5.1.4.3.0";
private static final String OID_3 = "1.3.6.1.4.1.32437.1.5.1.4.4.0";
private static final String OID_1_VALUE = "OID_1_VALUE";
private static final String OID_2_VALUE = "OID_2_VALUE";
private static final String OID_3_VALUE = "OID_3_VALUE";
private static final String TARGET_ADDRESS = "127.0.0.1/50555";
private static VariableBinding[] vbs1;
private static VariableBinding[] vbs2;
private static VariableBinding[] vbs3;
private static Map<String, String> vbMap;
@Mock
private static Target target;
@BeforeClass
public static void setUp() {
vbMap = new HashMap<>();
vbMap.put(SNMP_PREFIX + OID_1 + SNMP_SEPARATOR + VB_SYNTAX, OID_1_VALUE);
vbMap.put(SNMP_PREFIX + OID_2 + SNMP_SEPARATOR + VB_SYNTAX, OID_2_VALUE);
vbMap.put(SNMP_PREFIX + OID_3 + SNMP_SEPARATOR + VB_SYNTAX, OID_3_VALUE);
target = new CommunityTarget();
target.setAddress(new UdpAddress(TARGET_ADDRESS));
vbs1 = new VariableBinding[]{
new VariableBinding(new OID(OID_1), new OctetString(OID_1_VALUE)),
};
vbs2 = new VariableBinding[]{
new VariableBinding(new OID(OID_2), new OctetString(OID_2_VALUE)),
};
vbs3 = new VariableBinding[]{
new VariableBinding(new OID(OID_3), new OctetString(OID_3_VALUE))
};
}
@Test
public void testGetAttributes() {
final TreeEvent treeEvent1 = mock(TreeEvent.class);
when(treeEvent1.getVariableBindings()).thenReturn(vbs1);
final TreeEvent treeEvent2 = mock(TreeEvent.class);
when(treeEvent2.getVariableBindings()).thenReturn(vbs2);
final TreeEvent treeEvent3 = mock(TreeEvent.class);
when(treeEvent3.getVariableBindings()).thenReturn(vbs3);
final List<TreeEvent> treeEvents = new ArrayList<>();
Collections.addAll(treeEvents, treeEvent1, treeEvent2, treeEvent3);
final SNMPTreeResponse snmpTreeResponse = new SNMPTreeResponse(target, treeEvents);
final Map<String, String> attributes = snmpTreeResponse.getAttributes();
assertEquals(3, attributes.size());
assertEquals(vbMap, attributes);
}
@Test
public void testGetAttributesFlattensEmptyVariableBindingArrays() {
final TreeEvent emptyTreeEvent = mock(TreeEvent.class);
when(emptyTreeEvent.getVariableBindings()).thenReturn(new VariableBinding[0]);
final TreeEvent normalTreeEvent = mock(TreeEvent.class);
when(normalTreeEvent.getVariableBindings()).thenReturn(vbs1);
final List<TreeEvent> treeEvents = new ArrayList<>();
Collections.addAll(treeEvents, emptyTreeEvent, normalTreeEvent);
final SNMPTreeResponse snmpTreeResponse = new SNMPTreeResponse(target, treeEvents);
final Map<String, String> attributes = snmpTreeResponse.getAttributes();
assertEquals(1, attributes.size());
assertEquals(OID_1_VALUE, attributes.get(SNMP_PREFIX + OID_1 + SNMP_SEPARATOR + VB_SYNTAX));
}
@Test
public void testGetAttributesFiltersNullVariableBindings() {
final TreeEvent nullTreeEvent = mock(TreeEvent.class);
when(nullTreeEvent.getVariableBindings()).thenReturn(null);
final TreeEvent normalTreeEvent = mock(TreeEvent.class);
when(normalTreeEvent.getVariableBindings()).thenReturn(vbs1);
final List<TreeEvent> treeEvents = new ArrayList<>();
Collections.addAll(treeEvents, nullTreeEvent, normalTreeEvent);
final SNMPTreeResponse snmpTreeResponse = new SNMPTreeResponse(target, treeEvents);
final Map<String, String> attributes = snmpTreeResponse.getAttributes();
assertEquals(1, attributes.size());
assertEquals(OID_1_VALUE, attributes.get(SNMP_PREFIX + OID_1 + SNMP_SEPARATOR + VB_SYNTAX));
}
@Test
public void testGetTargetAddress() {
final TreeEvent treeEvent = mock(TreeEvent.class);
final List<TreeEvent> treeEvents = new ArrayList<>();
treeEvents.add(treeEvent);
final SNMPTreeResponse snmpTreeResponse = new SNMPTreeResponse(target, treeEvents);
final String actualTargetAddress = snmpTreeResponse.getTargetAddress();
assertEquals(TARGET_ADDRESS, actualTargetAddress);
}
@Test
public void testLogErrors() {
final MockComponentLog logger = new MockComponentLog("id1", new Object());
final List<TreeEvent> treeEvents = new ArrayList<>();
final TreeEvent treeEvent = mock(TreeEvent.class);
when(treeEvent.isError()).thenReturn(true);
when(treeEvent.getErrorMessage()).thenReturn("ERROR MESSAGE");
treeEvents.add(treeEvent);
final SNMPTreeResponse snmpTreeResponse = new SNMPTreeResponse(target, treeEvents);
snmpTreeResponse.logErrors(logger);
final List<LogMessage> errorMessages = logger.getErrorMessages();
System.out.println("asd");
}
}

View File

@ -1,68 +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.factory;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.configuration.SNMPConfigurationBuilder;
import org.junit.jupiter.api.Test;
import org.snmp4j.Snmp;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class SNMPClientFactoryTest {
private final SNMPConfigurationBuilder configurationBuilder = new SNMPConfigurationBuilder()
.setAgentHost("127.0.0.1")
.setAgentPort("12345")
.setRetries(1)
.setTimeout(1000)
.setSecurityLevel("noAuthNoPriv")
.setSecurityName("userName")
.setAuthProtocol("SHA")
.setAuthPassphrase("authPassword")
.setPrivacyProtocol("DES")
.setPrivacyPassphrase("privacyPassword")
.setCommunityString("public");
@Test
public void testSnmpV3ClientWithoutCorrespondingAgentDoesNotHaveUSM() {
final SNMPConfiguration configuration = configurationBuilder
.setVersion(SnmpConstants.version3)
.build();
final SNMPFactory snmpFactory = new CompositeSNMPFactory();
final Snmp snmpManager = snmpFactory.createSnmpManagerInstance(configuration);
final UsmUser user = snmpManager.getUSM().getUserTable().getUser(new OctetString("userName")).getUsmUser();
final OID usmHMACSHAAuthProtocol = new OID("1.3.6.1.6.3.10.1.1.3");
final OID usmDESPrivProtocol = new OID("1.3.6.1.6.3.10.1.2.2");
assertThat("userName", is(equalTo(user.getSecurityName().toString())));
assertThat(usmHMACSHAAuthProtocol, is(equalTo(user.getAuthenticationProtocol())));
assertThat("authPassword", is(equalTo(user.getAuthenticationPassphrase().toString())));
assertThat(usmDESPrivProtocol, is(equalTo(user.getPrivacyProtocol())));
assertThat("privacyPassword", is(equalTo(user.getPrivacyPassphrase().toString())));
assertThat(3, is(equalTo(user.getSecurityModel())));
}
}

View File

@ -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.factory.core;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.junit.Test;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class SNMPContextTest {
@Test
public void testCreateSNMPContext() {
final SNMPContext snmpContext = spy(SNMPContext.class);
final Snmp mockSnmpManager = mock(Snmp.class);
final Target mockTarget = mock(Target.class);
final SNMPConfiguration snmpConfiguration = mock(SNMPConfiguration.class);
when(snmpContext.createSnmpManagerInstance(snmpConfiguration)).thenReturn(mockSnmpManager);
when(snmpContext.createTargetInstance(snmpConfiguration)).thenReturn(mockTarget);
snmpContext.createSNMPResourceHandler(snmpConfiguration);
verify(snmpContext).createSnmpManagerInstance(snmpConfiguration);
verify(snmpContext).createTargetInstance(snmpConfiguration);
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.factory.core;
import org.junit.Test;
import org.snmp4j.mp.SnmpConstants;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
public class SNMPFactoryProviderTest {
@Test
public void testCreateFactoryByVersion() {
final SNMPContext snmpV1V2cFactoryFromVersion1 = SNMPFactoryProvider.getFactory(SnmpConstants.version1);
final SNMPContext snmpV1V2cFactoryFromVersion2c = SNMPFactoryProvider.getFactory(SnmpConstants.version2c);
final SNMPContext snmpV3Factory = SNMPFactoryProvider.getFactory(SnmpConstants.version3);
assertThat(snmpV1V2cFactoryFromVersion1, instanceOf(V1V2cSNMPFactory.class));
assertThat(snmpV1V2cFactoryFromVersion2c, instanceOf(V1V2cSNMPFactory.class));
assertThat(snmpV3Factory, instanceOf(V3SNMPFactory.class));
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.factory.core;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.util.StringUtils;
import org.junit.Test;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.security.SecurityLevel;
import static org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory.DEFAULT_HOST;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
public class V1V2cSNMPFactoryTest {
private static final int RETRIES = 3;
@Test
public void testFactoryCreatesV1V2Configuration() {
final V1V2cSNMPFactory snmpFactory = new V1V2cSNMPFactory();
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
final Target target = snmpFactory.createTargetInstance(snmpConfiguration);
assertThat(target, instanceOf(CommunityTarget.class));
assertEquals(DEFAULT_HOST + "/" + targetPort, target.getAddress().toString());
assertEquals(RETRIES, target.getRetries());
assertEquals(1, target.getSecurityLevel());
assertEquals(StringUtils.EMPTY, target.getSecurityName().toString());
}
@Test
public void testFactoryCreatesSnmpManager() {
final V1V2cSNMPFactory snmpFactory = new V1V2cSNMPFactory();
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
final Snmp snmpManager = snmpFactory.createSnmpManagerInstance(snmpConfiguration);
final String address = snmpManager.getMessageDispatcher().getTransportMappings().iterator().next().getListenAddress().toString();
assertEquals(DEFAULT_HOST + "/" + managerPort, address);
}
@Test
public void testFactoryCreatesResourceHandler() {
final V1V2cSNMPFactory snmpFactory = spy(V1V2cSNMPFactory.class);
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
snmpFactory.createSNMPResourceHandler(snmpConfiguration);
verify(snmpFactory).createTargetInstance(snmpConfiguration);
verify(snmpFactory).createSnmpManagerInstance(snmpConfiguration);
}
private SNMPConfiguration getSnmpConfiguration(int managerPort, String targetPort) {
return new SNMPConfiguration.Builder()
.setRetries(RETRIES)
.setManagerPort(managerPort)
.setTargetHost(DEFAULT_HOST)
.setTargetPort(targetPort)
.setSecurityLevel(SecurityLevel.noAuthNoPriv.name())
.build();
}
}

View File

@ -0,0 +1,107 @@
/*
* 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.factory.core;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.junit.Test;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OctetString;
import static org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory.DEFAULT_HOST;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.AUTH_PASSPHRASE;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.AUTH_PROTOCOL;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.PRIV_PASSPHRASE;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.PRIV_PROTOCOL;
import static org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory.SECURITY_NAME;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
public class V3SNMPFactoryTest {
private static final int RETRIES = 3;
private static final int EXPECTED_SECURITY_LEVEL = 3;
@Test
public void testFactoryCreatesTarget() {
final V3SNMPFactory snmpFactory = new V3SNMPFactory();
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
final Target target = snmpFactory.createTargetInstance(snmpConfiguration);
assertThat(target, instanceOf(UserTarget.class));
assertEquals(DEFAULT_HOST + "/" + targetPort, target.getAddress().toString());
assertEquals(RETRIES, target.getRetries());
assertEquals(EXPECTED_SECURITY_LEVEL, target.getSecurityLevel());
assertEquals(SECURITY_NAME, target.getSecurityName().toString());
}
@Test
public void testFactoryCreatesSnmpManager() {
final V3SNMPFactory snmpFactory = new V3SNMPFactory();
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
final Snmp snmpManager = snmpFactory.createSnmpManagerInstance(snmpConfiguration);
final String address = snmpManager.getMessageDispatcher().getTransportMappings().iterator().next().getListenAddress().toString();
USM usm = (USM) SecurityModels.getInstance().getSecurityModel(new Integer32(3));
assertEquals(DEFAULT_HOST + "/" + managerPort, address);
assertTrue(usm.hasUser(null, new OctetString("SHAAES128")));
}
@Test
public void testFactoryCreatesResourceHandler() {
final V3SNMPFactory snmpFactory = spy(V3SNMPFactory.class);
final int managerPort = NetworkUtils.availablePort();
final String targetPort = String.valueOf(NetworkUtils.availablePort());
final SNMPConfiguration snmpConfiguration = getSnmpConfiguration(managerPort, targetPort);
snmpFactory.createSNMPResourceHandler(snmpConfiguration);
verify(snmpFactory).createTargetInstance(snmpConfiguration);
verify(snmpFactory).createSnmpManagerInstance(snmpConfiguration);
}
private SNMPConfiguration getSnmpConfiguration(int managerPort, String targetPort) {
return new SNMPConfiguration.Builder()
.setRetries(RETRIES)
.setManagerPort(managerPort)
.setTargetHost(DEFAULT_HOST)
.setTargetPort(targetPort)
.setSecurityLevel(SecurityLevel.authPriv.name())
.setSecurityName(SECURITY_NAME)
.setAuthProtocol(AUTH_PROTOCOL)
.setAuthPassphrase(AUTH_PASSPHRASE)
.setPrivacyProtocol(PRIV_PROTOCOL)
.setPrivacyPassphrase(PRIV_PASSPHRASE)
.build();
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.factory.trap;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.junit.Test;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.Target;
import java.time.Instant;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
public class V1TrapPDUFactoryTest {
private static final String AGENT_ADDRESS = "127.0.0.1";
private static final String ENTERPRISE_OID = "1.3.6.1.4.1.8072.2.3.0.1";
private static final int GENERIC_TRAP_TYPE = 6;
private static final int SPECIFIC_TRAP_TYPE = 2;
@Test
public void testCreateV1TrapPdu() {
final Target mockTarget = mock(Target.class);
final V1TrapConfiguration v1TrapConfiguration = V1TrapConfiguration.builder()
.enterpriseOid(ENTERPRISE_OID)
.agentAddress(AGENT_ADDRESS)
.genericTrapType(String.valueOf(GENERIC_TRAP_TYPE))
.specificTrapType(String.valueOf(SPECIFIC_TRAP_TYPE))
.build();
final V1TrapPDUFactory v1TrapPduFactory = new V1TrapPDUFactory(mockTarget, Instant.now());
final PDU pdu = v1TrapPduFactory.get(v1TrapConfiguration);
assertEquals(PDU.V1TRAP, pdu.getType());
final PDUv1 pduV1 = (PDUv1) pdu;
assertEquals(ENTERPRISE_OID, pduV1.getEnterprise().toString());
assertEquals(AGENT_ADDRESS, pduV1.getAgentAddress().toString());
assertEquals(GENERIC_TRAP_TYPE, pduV1.getGenericTrap());
assertEquals(SPECIFIC_TRAP_TYPE, pduV1.getSpecificTrap());
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.factory.trap;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.junit.Test;
import org.snmp4j.PDU;
import org.snmp4j.Target;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.VariableBinding;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
public class V2TrapPDUFactoryTest {
private static final String TRAP_OID = "1.3.6.1.4.1.8072.2.3.0.1";
@Test
public void testCreateV2TrapPdu() {
final Target mockTarget = mock(Target.class);
final V2TrapConfiguration v2TrapConfiguration = new V2TrapConfiguration(TRAP_OID);
final V2TrapPDUFactory v2TrapPduFactory = new V2TrapPDUFactory(mockTarget, Instant.now());
final PDU pdu = v2TrapPduFactory.get(v2TrapConfiguration);
final Vector<? extends VariableBinding> variableBindings = pdu.getVariableBindings();
Set<String> expected = new HashSet<>(Arrays.asList(SnmpConstants.snmpTrapOID.toString(), TRAP_OID));
Set<String> actual = variableBindings.stream()
.flatMap(c -> Stream.of(c.getOid().toString(), c.getVariable().toString()))
.collect(Collectors.toSet());
assertTrue(actual.containsAll(expected));
}
}

View File

@ -1,68 +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.helper;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.snmp4j.UserTarget;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.IOException;
public class SNMPTestUtils {
public static Snmp createSnmpClient() throws IOException {
final DefaultUdpTransportMapping transportMapping = new DefaultUdpTransportMapping();
transportMapping.listen();
return new Snmp(transportMapping);
}
public static CommunityTarget createCommTarget(final String community, final String address, final int version) {
final CommunityTarget target = new CommunityTarget();
target.setVersion(version);
target.setCommunity(new OctetString(community));
target.setAddress(new UdpAddress(address));
target.setRetries(0);
target.setTimeout(500);
return target;
}
public static UserTarget createUserTarget(final String address, final int securityLevel, final String securityName, final int version) {
final UserTarget target = new UserTarget();
target.setVersion(version);
target.setSecurityLevel(securityLevel);
target.setSecurityName(new OctetString(securityName));
target.setAddress(new UdpAddress(address));
target.setRetries(0);
target.setTimeout(500);
return target;
}
public static UserTarget prepareUser(final Snmp snmp, final int version, final String address, final int securityLevel, final String securityName,
final OID auth, final OID priv, final String authPwd, final String privPwd) {
snmp.getUSM().removeAllUsers();
final OctetString aPwd = authPwd != null ? new OctetString(authPwd) : null;
final OctetString pPwd = privPwd != null ? new OctetString(privPwd) : null;
snmp.getUSM().addUser(new OctetString(securityName), new UsmUser(new OctetString(securityName), auth, aPwd, priv, pPwd));
return createUserTarget(address, securityLevel, securityName, version);
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.helper;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.snmp4j.PDUv1;
public class TrapConfigurationFactory {
// v1 specific
private static final String ENTERPRISE_OID = "1.3.5.7.11";
private static final String AGENT_ADDRESS = "1.2.3.4";
private static final String GENERIC_TRAP_TYPE = String.valueOf(PDUv1.ENTERPRISE_SPECIFIC);
private static final String SPECIFIC_TRAP_TYPE = "2";
// v2c/v3 specific
private static final String TRAP_OID_VALUE = "testTrapOidValue";
public static V1TrapConfiguration getV1TrapConfiguration() {
return V1TrapConfiguration.builder()
.enterpriseOid(ENTERPRISE_OID)
.agentAddress(AGENT_ADDRESS)
.genericTrapType(GENERIC_TRAP_TYPE)
.specificTrapType(SPECIFIC_TRAP_TYPE)
.build();
}
public static V2TrapConfiguration getV2TrapConfiguration() {
return new V2TrapConfiguration(TRAP_OID_VALUE);
}
}

View File

@ -14,17 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.snmp.factory;
package org.apache.nifi.snmp.helper.configurations;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
public interface SNMPFactory {
public interface SNMPConfigurationFactory {
boolean supports(final int version);
String DEFAULT_HOST = "127.0.0.1";
String COMMUNITY_STRING = "public";
Snmp createSnmpManagerInstance(final SNMPConfiguration configuration);
SNMPConfiguration createSnmpGetSetConfiguration(int agentPort);
SNMPConfiguration createSnmpGetSetConfigWithCustomHost(final String host, final int agentPort);
SNMPConfiguration createSnmpListenTrapConfig(final int managerPort);
Target createTargetInstance(final SNMPConfiguration configuration);
}

View File

@ -0,0 +1,57 @@
/*
* 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.helper.configurations;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
public class SNMPV1V2cConfigurationFactory implements SNMPConfigurationFactory {
private int snmpVersion;
public SNMPV1V2cConfigurationFactory(int snmpVersion) {
this.snmpVersion = snmpVersion;
}
@Override
public SNMPConfiguration createSnmpGetSetConfiguration(final int agentPort) {
return SNMPConfiguration.builder()
.setTargetHost(DEFAULT_HOST)
.setTargetPort(String.valueOf(agentPort))
.setCommunityString(COMMUNITY_STRING)
.setVersion(snmpVersion)
.build();
}
@Override
public SNMPConfiguration createSnmpGetSetConfigWithCustomHost(final String host, final int agentPort) {
return SNMPConfiguration.builder()
.setTargetHost(host)
.setTargetPort(String.valueOf(agentPort))
.setCommunityString(COMMUNITY_STRING)
.setVersion(snmpVersion)
.build();
}
@Override
public SNMPConfiguration createSnmpListenTrapConfig(final int managerPort) {
return SNMPConfiguration.builder()
.setManagerPort(managerPort)
.setCommunityString(COMMUNITY_STRING)
.setVersion(snmpVersion)
.build();
}
}

View File

@ -0,0 +1,71 @@
/*
* 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.helper.configurations;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.snmp4j.mp.SnmpConstants;
public class SNMPV3ConfigurationFactory implements SNMPConfigurationFactory {
// V3 security (users are set in test agents)
public static final String SECURITY_LEVEL = "authPriv";
public static final String SECURITY_NAME = "SHAAES128";
public static final String AUTH_PROTOCOL = "SHA";
public static final String AUTH_PASSPHRASE = "SHAAES128AuthPassphrase";
public static final String PRIV_PROTOCOL = "AES128";
public static final String PRIV_PASSPHRASE = "SHAAES128PrivPassphrase";
@Override
public SNMPConfiguration createSnmpGetSetConfiguration(final int agentPort) {
return SNMPConfiguration.builder()
.setTargetHost(DEFAULT_HOST)
.setTargetPort(String.valueOf(agentPort))
.setCommunityString(COMMUNITY_STRING)
.setVersion(SnmpConstants.version3)
.setSecurityLevel(SECURITY_LEVEL)
.setSecurityName(SECURITY_NAME)
.setAuthProtocol(AUTH_PROTOCOL)
.setAuthPassphrase(AUTH_PASSPHRASE)
.setPrivacyProtocol(PRIV_PROTOCOL)
.setPrivacyPassphrase(PRIV_PASSPHRASE)
.build();
}
@Override
public SNMPConfiguration createSnmpGetSetConfigWithCustomHost(final String host, final int agentPort) {
return SNMPConfiguration.builder()
.setTargetHost(host)
.setTargetPort(String.valueOf(agentPort))
.setCommunityString(COMMUNITY_STRING)
.setVersion(SnmpConstants.version3)
.setSecurityLevel(SECURITY_LEVEL)
.setSecurityName(SECURITY_NAME)
.setAuthProtocol(AUTH_PROTOCOL)
.setAuthPassphrase(AUTH_PASSPHRASE)
.setPrivacyProtocol(PRIV_PROTOCOL)
.setPrivacyPassphrase(PRIV_PASSPHRASE)
.build();
}
@Override
public SNMPConfiguration createSnmpListenTrapConfig(final int managerPort) {
return SNMPConfiguration.builder()
.setManagerPort(managerPort)
.setVersion(SnmpConstants.version3)
.build();
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.helper.testrunners;
import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.snmp4j.mp.SnmpConstants;
import java.util.HashMap;
import java.util.Map;
import static org.apache.nifi.snmp.utils.SNMPUtils.SNMP_PROP_PREFIX;
public interface SNMPTestRunnerFactory {
TestRunner createSnmpGetTestRunner(final int agentPort, final String oid, final String strategy);
TestRunner createSnmpSetTestRunner(final int agentPort, final String oid, final String oidValue);
TestRunner createSnmpSendTrapTestRunner(final int managerPort, final String oid, final String oidValue);
TestRunner createSnmpListenTrapTestRunner(final int managerPort);
default MockFlowFile getFlowFile(String oid, String oidValue) {
final MockFlowFile flowFile = new MockFlowFile(1L);
final Map<String, String> attributes = new HashMap<>();
attributes.put(SNMP_PROP_PREFIX + oid, oidValue);
flowFile.putAttributes(attributes);
return flowFile;
}
default String getVersionName(final int version) {
if (version == SnmpConstants.version1) {
return "SNMPv1";
} else if (version == SnmpConstants.version2c) {
return "SNMPv2c";
} else if (version == SnmpConstants.version3) {
return "SNMPv3";
} else {
throw new InvalidSnmpVersionException("Invalid SNMP version");
}
}
}

View File

@ -0,0 +1,93 @@
/*
* 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.helper.testrunners;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.helper.TrapConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPV1V2cConfigurationFactory;
import org.apache.nifi.snmp.processors.GetSNMP;
import org.apache.nifi.snmp.processors.ListenTrapSNMP;
import org.apache.nifi.snmp.processors.SendTrapSNMP;
import org.apache.nifi.snmp.processors.SetSNMP;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V1TrapProperties;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.snmp4j.mp.SnmpConstants;
public class SNMPV1TestRunnerFactory implements SNMPTestRunnerFactory {
private static final SNMPConfigurationFactory snmpV1V2ConfigurationFactory = new SNMPV1V2cConfigurationFactory(SnmpConstants.version1);
@Override
public TestRunner createSnmpGetTestRunner(final int agentPort, final String oid, final String strategy) {
final TestRunner runner = TestRunners.newTestRunner(GetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV1V2ConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(GetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(GetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(GetSNMP.SNMP_STRATEGY, strategy);
runner.setProperty(GetSNMP.OID, oid);
return runner;
}
@Override
public TestRunner createSnmpSetTestRunner(final int agentPort, final String oid, final String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV1V2ConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(SetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpSendTrapTestRunner(final int managerPort, final String oid, final String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SendTrapSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV1V2ConfigurationFactory.createSnmpGetSetConfiguration(managerPort);
final V1TrapConfiguration trapConfiguration = TrapConfigurationFactory.getV1TrapConfiguration();
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(V1TrapProperties.ENTERPRISE_OID, trapConfiguration.getEnterpriseOid());
runner.setProperty(V1TrapProperties.AGENT_ADDRESS, trapConfiguration.getAgentAddress());
runner.setProperty(V1TrapProperties.GENERIC_TRAP_TYPE, String.valueOf(trapConfiguration.getGenericTrapType()));
runner.setProperty(V1TrapProperties.SPECIFIC_TRAP_TYPE, String.valueOf(trapConfiguration.getSpecificTrapType()));
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpListenTrapTestRunner(final int managerPort) {
final TestRunner runner = TestRunners.newTestRunner(ListenTrapSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV1V2ConfigurationFactory.createSnmpListenTrapConfig(managerPort);
runner.setProperty(ListenTrapSNMP.SNMP_MANAGER_PORT, String.valueOf(snmpConfiguration.getManagerPort()));
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
return runner;
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.helper.testrunners;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.helper.TrapConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPV1V2cConfigurationFactory;
import org.apache.nifi.snmp.processors.GetSNMP;
import org.apache.nifi.snmp.processors.ListenTrapSNMP;
import org.apache.nifi.snmp.processors.SendTrapSNMP;
import org.apache.nifi.snmp.processors.SetSNMP;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V2TrapProperties;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.snmp4j.mp.SnmpConstants;
public class SNMPV2cTestRunnerFactory implements SNMPTestRunnerFactory {
private static final SNMPConfigurationFactory snmpV2cConfigurationFactory = new SNMPV1V2cConfigurationFactory(SnmpConstants.version2c);
@Override
public TestRunner createSnmpGetTestRunner(int agentPort, String oid, String strategy) {
final TestRunner runner = TestRunners.newTestRunner(GetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV2cConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(GetSNMP.OID, oid);
runner.setProperty(GetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(GetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(GetSNMP.SNMP_STRATEGY, strategy);
return runner;
}
@Override
public TestRunner createSnmpSetTestRunner(int agentPort, String oid, String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV2cConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(SetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpSendTrapTestRunner(int managerPort, final String oid, final String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SendTrapSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV2cConfigurationFactory.createSnmpGetSetConfiguration(managerPort);
final V2TrapConfiguration trapConfiguration = TrapConfigurationFactory.getV2TrapConfiguration();
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(V2TrapProperties.TRAP_OID_VALUE, trapConfiguration.getTrapOidValue());
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpListenTrapTestRunner(int managerPort) {
final TestRunner runner = TestRunners.newTestRunner(ListenTrapSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV2cConfigurationFactory.createSnmpListenTrapConfig(managerPort);
runner.setProperty(ListenTrapSNMP.SNMP_MANAGER_PORT, String.valueOf(snmpConfiguration.getManagerPort()));
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
return runner;
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.helper.testrunners;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.helper.TrapConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory;
import org.apache.nifi.snmp.processors.GetSNMP;
import org.apache.nifi.snmp.processors.ListenTrapSNMP;
import org.apache.nifi.snmp.processors.SendTrapSNMP;
import org.apache.nifi.snmp.processors.SetSNMP;
import org.apache.nifi.snmp.processors.properties.BasicProperties;
import org.apache.nifi.snmp.processors.properties.V2TrapProperties;
import org.apache.nifi.snmp.processors.properties.V3SecurityProperties;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
public class SNMPV3TestRunnerFactory implements SNMPTestRunnerFactory {
private static final String USM_USERS_FILE_PATH = "src/test/resources/usm.json";
private static final SNMPConfigurationFactory snmpV3ConfigurationFactory = new SNMPV3ConfigurationFactory();
@Override
public TestRunner createSnmpGetTestRunner(int agentPort, String oid, String strategy) {
final TestRunner runner = TestRunners.newTestRunner(GetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV3ConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(GetSNMP.OID, oid);
runner.setProperty(GetSNMP.SNMP_STRATEGY, strategy);
runner.setProperty(GetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(GetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL, snmpConfiguration.getSecurityLevel());
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_NAME, snmpConfiguration.getSecurityName());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PROTOCOL, snmpConfiguration.getAuthProtocol());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PASSWORD, snmpConfiguration.getAuthPassphrase());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PROTOCOL, snmpConfiguration.getPrivacyProtocol());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PASSWORD, snmpConfiguration.getPrivacyPassphrase());
return runner;
}
@Override
public TestRunner createSnmpSetTestRunner(int agentPort, String oid, String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SetSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV3ConfigurationFactory.createSnmpGetSetConfiguration(agentPort);
runner.setProperty(SetSNMP.AGENT_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SetSNMP.AGENT_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL, snmpConfiguration.getSecurityLevel());
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_NAME, snmpConfiguration.getSecurityName());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PROTOCOL, snmpConfiguration.getAuthProtocol());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PASSWORD, snmpConfiguration.getAuthPassphrase());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PROTOCOL, snmpConfiguration.getPrivacyProtocol());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PASSWORD, snmpConfiguration.getPrivacyPassphrase());
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpSendTrapTestRunner(int managerPort, final String oid, final String oidValue) {
final TestRunner runner = TestRunners.newTestRunner(SendTrapSNMP.class);
final SNMPConfiguration snmpConfiguration = snmpV3ConfigurationFactory.createSnmpGetSetConfiguration(managerPort);
final V2TrapConfiguration trapConfiguration = TrapConfigurationFactory.getV2TrapConfiguration();
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_HOST, snmpConfiguration.getTargetHost());
runner.setProperty(SendTrapSNMP.SNMP_MANAGER_PORT, snmpConfiguration.getTargetPort());
runner.setProperty(BasicProperties.SNMP_COMMUNITY, snmpConfiguration.getCommunityString());
runner.setProperty(BasicProperties.SNMP_VERSION, getVersionName(snmpConfiguration.getVersion()));
runner.setProperty(V2TrapProperties.TRAP_OID_VALUE, trapConfiguration.getTrapOidValue());
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_LEVEL, snmpConfiguration.getSecurityLevel());
runner.setProperty(V3SecurityProperties.SNMP_SECURITY_NAME, snmpConfiguration.getSecurityName());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PROTOCOL, snmpConfiguration.getAuthProtocol());
runner.setProperty(V3SecurityProperties.SNMP_AUTH_PASSWORD, snmpConfiguration.getAuthPassphrase());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PROTOCOL, snmpConfiguration.getPrivacyProtocol());
runner.setProperty(V3SecurityProperties.SNMP_PRIVACY_PASSWORD, snmpConfiguration.getPrivacyPassphrase());
final MockFlowFile flowFile = getFlowFile(oid, oidValue);
runner.enqueue(flowFile);
return runner;
}
@Override
public TestRunner createSnmpListenTrapTestRunner(int managerPort) {
final TestRunner runner = TestRunners.newTestRunner(ListenTrapSNMP.class);
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);
return runner;
}
}

View File

@ -0,0 +1,271 @@
/*
* 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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.exception.SNMPWalkException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.util.TreeEvent;
import org.snmp4j.util.TreeUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.apache.nifi.snmp.operations.GetSNMPHandler.EMPTY_SUBTREE_EXCEPTION_MESSAGE;
import static org.apache.nifi.snmp.operations.GetSNMPHandler.LEAF_ELEMENT_EXCEPTION_MESSAGE;
import static org.apache.nifi.snmp.operations.GetSNMPHandler.SNMP_ERROR_EXCEPTION_MESSAGE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class GetSNMPHandlerTest {
private static final String OID = "1.3.6.1.4.1.343";
private Target mockTarget;
private Snmp mockSnmpManager;
private SNMPResourceHandler snmpResourceHandler;
@Before
public void init() {
mockTarget = mock(Target.class);
mockSnmpManager = mock(Snmp.class);
snmpResourceHandler = new SNMPResourceHandler(mockSnmpManager, mockTarget);
}
@Test
public void testGetSnmpWithEmptyFlowFile() throws IOException {
final ResponseEvent mockResponseEvent = mock(ResponseEvent.class);
final PDU mockPdu = mock(PDU.class);
when(mockResponseEvent.getResponse()).thenReturn(mockPdu);
when(mockSnmpManager.get(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.get(OID);
ArgumentCaptor<PDU> captor = ArgumentCaptor.forClass(PDU.class);
Mockito.verify(mockSnmpManager).get(captor.capture(), any(Target.class));
final PDU pdu = captor.getValue();
assertEquals(1, pdu.getVariableBindings().size());
assertEquals(OID, pdu.getVariableBindings().get(0).getOid().toString());
}
@Test
public void testGetSnmpWithInvalidFlowFile() throws IOException {
final Map<String, String> invalidFlowFileAttributes = new HashMap<>();
invalidFlowFileAttributes.put("invalid", "flowfile attribute");
final ResponseEvent mockResponseEvent = mock(ResponseEvent.class);
final PDU mockPdu = mock(PDU.class);
when(mockResponseEvent.getResponse()).thenReturn(mockPdu);
when(mockSnmpManager.get(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = getSNMPHandler.get(invalidFlowFileAttributes);
assertFalse(optionalResponse.isPresent());
}
@Test
public void testGetSnmpWithValidFlowFile() throws IOException {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
final Map<String, String> flowFileAttributes = new HashMap<>();
flowFileAttributes.put("snmp$" + flowFileOid, "OID value");
final ResponseEvent mockResponseEvent = mock(ResponseEvent.class);
final PDU mockPdu = mock(PDU.class);
when(mockResponseEvent.getResponse()).thenReturn(mockPdu);
when(mockSnmpManager.get(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.get(flowFileAttributes);
ArgumentCaptor<PDU> captor = ArgumentCaptor.forClass(PDU.class);
Mockito.verify(mockSnmpManager).get(captor.capture(), any(Target.class));
final PDU pdu = captor.getValue();
assertEquals(1, pdu.getVariableBindings().size());
assertEquals(flowFileOid, pdu.getVariableBindings().get(0).getOid().toString());
assertEquals("Null", pdu.getVariableBindings().get(0).getVariable().toString());
}
@Test
public void testGetSnmpWhenTimeout() throws IOException {
final ResponseEvent mockResponseEvent = mock(ResponseEvent.class);
when(mockResponseEvent.getResponse()).thenReturn(null);
when(mockSnmpManager.get(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final RequestTimeoutException requestTimeoutException = Assert.assertThrows(
RequestTimeoutException.class,
() -> getSNMPHandler.get(OID)
);
assertEquals(String.format(SNMPResourceHandler.REQUEST_TIMEOUT_EXCEPTION_TEMPLATE, "read"),
requestTimeoutException.getMessage());
}
@SuppressWarnings("unchecked")
@Test
public void testWalkSnmpWithEmptyFlowFile() {
final TreeUtils mockTreeUtils = mock(TreeUtils.class);
final TreeEvent mockTreeEvent = mock(TreeEvent.class);
final List<TreeEvent> mockSubtree = (List<TreeEvent>) mock(List.class);
final VariableBinding[] variableBindings = new VariableBinding[1];
variableBindings[0] = new VariableBinding(new OID(OID), new OctetString("OID value"));
when(mockTreeEvent.getVariableBindings()).thenReturn(variableBindings);
when(mockSubtree.get(0)).thenReturn(mockTreeEvent);
when(mockTreeUtils.getSubtree(mockTarget, new OID(OID))).thenReturn(mockSubtree);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.setTreeUtils(mockTreeUtils);
getSNMPHandler.walk(OID);
ArgumentCaptor<OID> captor = ArgumentCaptor.forClass(OID.class);
Mockito.verify(mockTreeUtils).getSubtree(any(Target.class), captor.capture());
assertEquals(OID, captor.getValue().toString());
}
@Test
public void testWalkSnmpWithInvalidFlowFile() {
final Map<String, String> invalidFlowFileAttributes = new HashMap<>();
invalidFlowFileAttributes.put("invalid", "flowfile attribute");
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final Optional<SNMPTreeResponse> optionalResponse = getSNMPHandler.walk(invalidFlowFileAttributes);
assertFalse(optionalResponse.isPresent());
}
@SuppressWarnings("unchecked")
@Test
public void testWalkSnmpWithValidFlowFile() {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
final Map<String, String> flowFileAttributes = new HashMap<>();
flowFileAttributes.put("snmp$" + flowFileOid, "OID value");
final TreeUtils mockTreeUtils = mock(TreeUtils.class);
final TreeEvent mockTreeEvent = mock(TreeEvent.class);
final List<TreeEvent> mockSubtree = (List<TreeEvent>) mock(List.class);
final VariableBinding[] variableBindings = new VariableBinding[1];
variableBindings[0] = new VariableBinding(new OID(OID), new OctetString("OID value"));
when(mockTreeEvent.getVariableBindings()).thenReturn(variableBindings);
when(mockSubtree.get(0)).thenReturn(mockTreeEvent);
when(mockSubtree.isEmpty()).thenReturn(false);
when(mockTreeUtils.walk(any(Target.class), any(OID[].class))).thenReturn(mockSubtree);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.setTreeUtils(mockTreeUtils);
getSNMPHandler.walk(flowFileAttributes);
ArgumentCaptor<OID[]> captor = ArgumentCaptor.forClass(OID[].class);
Mockito.verify(mockTreeUtils).walk(any(Target.class), captor.capture());
assertEquals(flowFileOid, captor.getValue()[0].toString());
}
@SuppressWarnings("unchecked")
@Test
public void testWalkSnmpWithEmptySubtreeThrowsException() {
final TreeUtils mockTreeUtils = mock(TreeUtils.class);
final List<TreeEvent> mockSubtree = (List<TreeEvent>) mock(List.class);
when(mockSubtree.isEmpty()).thenReturn(true);
when(mockTreeUtils.getSubtree(any(Target.class), any(org.snmp4j.smi.OID.class))).thenReturn(mockSubtree);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.setTreeUtils(mockTreeUtils);
final SNMPWalkException snmpWalkException = Assert.assertThrows(
SNMPWalkException.class,
() -> getSNMPHandler.walk(OID)
);
assertEquals(String.format(EMPTY_SUBTREE_EXCEPTION_MESSAGE, OID), snmpWalkException.getMessage());
}
@SuppressWarnings("unchecked")
@Test
public void testWalkSnmpWithSubtreeErrorThrowsException() {
final TreeUtils mockTreeUtils = mock(TreeUtils.class);
final TreeEvent mockTreeEvent = mock(TreeEvent.class);
final List<TreeEvent> mockSubtree = (List<TreeEvent>) mock(List.class);
when(mockSubtree.get(0)).thenReturn(mockTreeEvent);
when(mockSubtree.isEmpty()).thenReturn(false);
when(mockSubtree.size()).thenReturn(1);
when(mockTreeUtils.getSubtree(any(Target.class), any(org.snmp4j.smi.OID.class))).thenReturn(mockSubtree);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.setTreeUtils(mockTreeUtils);
final SNMPWalkException snmpWalkException = Assert.assertThrows(
SNMPWalkException.class,
() -> getSNMPHandler.walk(OID)
);
assertEquals(SNMP_ERROR_EXCEPTION_MESSAGE, snmpWalkException.getMessage());
}
@SuppressWarnings("unchecked")
@Test
public void testWalkSnmpWithLeafElementSubtreeThrowsException() {
final TreeUtils mockTreeUtils = mock(TreeUtils.class);
final TreeEvent mockTreeEvent = mock(TreeEvent.class);
final List<TreeEvent> mockSubtree = (List<TreeEvent>) mock(List.class);
final VariableBinding[] variableBindings = new VariableBinding[0];
when(mockTreeEvent.getVariableBindings()).thenReturn(variableBindings);
when(mockSubtree.get(0)).thenReturn(mockTreeEvent);
when(mockSubtree.isEmpty()).thenReturn(false);
when(mockSubtree.size()).thenReturn(1);
when(mockTreeUtils.getSubtree(any(Target.class), any(org.snmp4j.smi.OID.class))).thenReturn(mockSubtree);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.setTreeUtils(mockTreeUtils);
final SNMPWalkException snmpWalkException = Assert.assertThrows(
SNMPWalkException.class,
() -> getSNMPHandler.walk(OID)
);
assertEquals(String.format(LEAF_ELEMENT_EXCEPTION_MESSAGE, OID), snmpWalkException.getMessage());
}
}

View File

@ -16,45 +16,67 @@
*/
package org.apache.nifi.snmp.operations;
import org.apache.nifi.snmp.configuration.SNMPConfiguration;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.helper.SNMPTestUtils;
import org.apache.nifi.snmp.dto.SNMPValue;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.factory.core.SNMPFactoryProvider;
import org.apache.nifi.snmp.helper.configurations.SNMPConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPV1V2cConfigurationFactory;
import org.apache.nifi.snmp.helper.configurations.SNMPV3ConfigurationFactory;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.util.MockFlowFile;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.snmp4j.CommunityTarget;
import org.snmp4j.Snmp;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.apache.nifi.snmp.testagents.TestSNMPV2cAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV3Agent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public abstract class SNMPRequestTest {
@RunWith(Parameterized.class)
public class SNMPRequestTest {
protected static final String LOCALHOST = "127.0.0.1";
protected static final String INVALID_HOST = "127.0.0.2";
protected static final String READ_ONLY_OID_1 = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
protected static final String READ_ONLY_OID_2 = "1.3.6.1.4.1.32437.1.5.1.4.3.0";
protected static final String WRITE_ONLY_OID = "1.3.6.1.4.1.32437.1.5.1.4.4.0";
protected static final String READ_ONLY_OID_VALUE_1 = "TestOID1";
protected static final String READ_ONLY_OID_VALUE_2 = "TestOID2";
protected static final String WRITE_ONLY_OID_VALUE = "writeOnlyOID";
protected static final String SNMP_PROP_DELIMITER = "$";
protected static final String SNMP_PROP_PREFIX = "snmp" + SNMP_PROP_DELIMITER;
protected static final String NOT_WRITABLE = "Not writable";
protected static final String NO_ACCESS = "No access";
protected static final String SUCCESS = "Success";
protected static final String EXPECTED_OID_VALUE = "testValue";
private static final String LOCALHOST = "127.0.0.1";
private static final String INVALID_HOST = "127.0.0.2";
private static final String READ_ONLY_OID_1 = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
private static final String READ_ONLY_OID_2 = "1.3.6.1.4.1.32437.1.5.1.4.3.0";
private static final String WRITE_ONLY_OID = "1.3.6.1.4.1.32437.1.5.1.4.4.0";
private static final String WALK_OID = "1.3.6.1.4.1.32437";
private static final String INVALID_OID = "1.3.6.1.4.1.32437.0";
private static final String READ_ONLY_OID_VALUE_1 = "TestOID1";
private static final String READ_ONLY_OID_VALUE_2 = "TestOID2";
private static final String WRITE_ONLY_OID_VALUE = "writeOnlyOID";
private static final String SNMP_PROP_DELIMITER = "$";
private static final String SNMP_PROP_PREFIX = "snmp" + SNMP_PROP_DELIMITER;
private static final String NOT_WRITABLE = "Not writable";
private static final String NO_ACCESS = "No access";
private static final String SUCCESS = "Success";
private static final String NO_SUCH_OBJECT = "noSuchObject";
private static final String UNABLE_TO_CREATE_OBJECT = "Unable to create object";
private static final String TEST_OID_VALUE = "testValue";
private static final String NO_SUCH_NAME = "No such name";
protected static final Map<String, String> WALK_OID_MAP;
static {
@ -64,53 +86,217 @@ public abstract class SNMPRequestTest {
WALK_OID_MAP = Collections.unmodifiableMap(oidMap);
}
protected final TestAgent agent = getAgentInstance();
private static final SNMPConfigurationFactory snmpV1ConfigurationFactory = new SNMPV1V2cConfigurationFactory(SnmpConstants.version1);
private static final SNMPConfigurationFactory snmpv2cConfigurationFactory = new SNMPV1V2cConfigurationFactory(SnmpConstants.version2c);
private static final SNMPConfigurationFactory snmpv3ConfigurationFactory = new SNMPV3ConfigurationFactory();
protected abstract TestAgent getAgentInstance();
private static final TestAgent v1TestAgent = new TestSNMPV1Agent(LOCALHOST);
private static final TestAgent v2cTestAgent = new TestSNMPV2cAgent(LOCALHOST);
private static final TestAgent v3TestAgent = new TestSNMPV3Agent(LOCALHOST);
@BeforeEach
private SNMPResourceHandler snmpResourceHandler;
static {
registerManagedObjects(v1TestAgent);
registerManagedObjects(v2cTestAgent);
registerManagedObjects(v3TestAgent);
}
@Before
public void initAgent() throws IOException {
agent.start();
agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_1), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_1)),
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_2), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_2)),
DefaultMOFactory.getInstance().createScalar(new OID(WRITE_ONLY_OID), MOAccessImpl.ACCESS_WRITE_ONLY, new OctetString(WRITE_ONLY_OID_VALUE))
);
}
@AfterEach
@After
public void tearDown() {
agent.stop();
agent.unregister();
snmpResourceHandler.close();
}
protected SNMPTreeResponse getTreeEvents(final int port, final int version) throws IOException {
final Snmp snmp = SNMPTestUtils.createSnmpClient();
final CommunityTarget target = SNMPTestUtils.createCommTarget("public", LOCALHOST + "/" + port, version);
final StandardSNMPRequestHandler standardSnmpRequestHandler = new StandardSNMPRequestHandler(snmp, target);
return standardSnmpRequestHandler.walk("1.3.6.1.4.1.32437");
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{SnmpConstants.version1, snmpV1ConfigurationFactory, v1TestAgent, NO_SUCH_NAME, NO_SUCH_NAME, NO_SUCH_NAME, NO_SUCH_NAME},
{SnmpConstants.version2c, snmpv2cConfigurationFactory, v2cTestAgent, NOT_WRITABLE, NO_ACCESS, NO_SUCH_OBJECT, UNABLE_TO_CREATE_OBJECT},
{SnmpConstants.version3, snmpv3ConfigurationFactory, v3TestAgent, NOT_WRITABLE, NO_ACCESS, NO_SUCH_OBJECT, UNABLE_TO_CREATE_OBJECT}
});
}
protected SNMPSingleResponse getResponseEvent(final String address, final int port, final int version, final String oid) throws IOException {
final Snmp snmp = SNMPTestUtils.createSnmpClient();
final CommunityTarget target = SNMPTestUtils.createCommTarget("public", address + "/" + port, version);
final StandardSNMPRequestHandler standardSnmpRequestHandler = new StandardSNMPRequestHandler(snmp, target);
return standardSnmpRequestHandler.get(oid);
private final int version;
private final SNMPConfigurationFactory snmpConfigurationFactory;
private final TestAgent agent;
private final String cannotSetReadOnlyOidStatusMessage;
private final String cannotModifyOidStatusMessage;
private final String getInvalidOidStatusMessage;
private final String setInvalidOidStatusMessage;
public SNMPRequestTest(final int version, final SNMPConfigurationFactory snmpConfigurationFactory, final TestAgent agent,
final String cannotSetReadOnlyOidStatusMessage, final String cannotModifyOidStatusMessage,
final String getInvalidOidStatusMessage, final String setInvalidOidStatusMessage) {
this.version = version;
this.snmpConfigurationFactory = snmpConfigurationFactory;
this.agent = agent;
this.cannotSetReadOnlyOidStatusMessage = cannotSetReadOnlyOidStatusMessage;
this.cannotModifyOidStatusMessage = cannotModifyOidStatusMessage;
this.getInvalidOidStatusMessage = getInvalidOidStatusMessage;
this.setInvalidOidStatusMessage = setInvalidOidStatusMessage;
}
protected SNMPSingleResponse getSetResponse(final int port, final int version, final String oid, final String expectedOid) throws IOException {
final Snmp snmp = SNMPTestUtils.createSnmpClient();
final CommunityTarget target = SNMPTestUtils.createCommTarget("public", LOCALHOST + "/" + port, version);
final StandardSNMPRequestHandler standardSnmpRequestHandler = new StandardSNMPRequestHandler(snmp, target);
@Test
public void testSuccessfulSnmpGet() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final SNMPSingleResponse response = getSNMPHandler.get(READ_ONLY_OID_1);
assertEquals(READ_ONLY_OID_VALUE_1, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
final MockFlowFile flowFile = new MockFlowFile(1L);
}
@Test
public void testSuccessfulSnmpGetWithFlowFileInput() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = getSNMPHandler.get(getFlowFileAttributesForSnmpGet(READ_ONLY_OID_1, READ_ONLY_OID_2));
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
Set<String> expectedVariables = new HashSet<>(Arrays.asList(READ_ONLY_OID_VALUE_1, READ_ONLY_OID_VALUE_2));
Set<String> actualVariables = response.getVariableBindings().stream().map(SNMPValue::getVariable).collect(Collectors.toSet());
assertEquals(expectedVariables, actualVariables);
assertEquals(SUCCESS, response.getErrorStatusText());
} else {
fail("Response is not present.");
}
}
@Test
public void testSuccessfulSnmpWalk() {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final SNMPTreeResponse response = getSNMPHandler.walk(WALK_OID);
assertSubTreeContainsOids(response);
}
@Test(expected = RequestTimeoutException.class)
public void testSnmpGetTimeoutReturnsNull() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfigWithCustomHost(INVALID_HOST, agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
getSNMPHandler.get(READ_ONLY_OID_1);
}
@Test
public void testSnmpGetInvalidOidWithFlowFileInput() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = getSNMPHandler.get(getFlowFileAttributesForSnmpGet(INVALID_OID, READ_ONLY_OID_2));
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
if (version == SnmpConstants.version1) {
assertEquals("Null", response.getVariableBindings().get(1).getVariable());
assertEquals(READ_ONLY_OID_VALUE_2, response.getVariableBindings().get(0).getVariable());
assertEquals(NO_SUCH_NAME, response.getErrorStatusText());
} else {
assertEquals(NO_SUCH_OBJECT, response.getVariableBindings().get(1).getVariable());
assertEquals(READ_ONLY_OID_VALUE_2, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
} else {
fail("Response is not present.");
}
}
@Test
public void testSuccessfulSnmpSet() throws IOException {
final Map<String, String> flowFileAttributes = getFlowFileAttributes(WRITE_ONLY_OID);
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final SetSNMPHandler setSNMPHandler = new SetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = setSNMPHandler.set(flowFileAttributes);
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
assertEquals(TEST_OID_VALUE, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
} else {
fail("Response is not present.");
}
}
@Test
public void testCannotSetReadOnlyObject() throws IOException {
final Map<String, String> flowFileAttributes = getFlowFileAttributes(READ_ONLY_OID_1);
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final SetSNMPHandler setSNMPHandler = new SetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = setSNMPHandler.set(flowFileAttributes);
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
assertEquals(cannotSetReadOnlyOidStatusMessage, response.getErrorStatusText());
} else {
fail("Response is not present.");
}
}
@Test
public void testCannotGetWriteOnlyObject() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final SNMPSingleResponse response = getSNMPHandler.get(WRITE_ONLY_OID);
assertEquals(cannotModifyOidStatusMessage, response.getErrorStatusText());
}
@Test
public void testCannotGetInvalidOid() throws IOException {
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final GetSNMPHandler getSNMPHandler = new GetSNMPHandler(snmpResourceHandler);
final SNMPSingleResponse response = getSNMPHandler.get(INVALID_OID);
if (version == SnmpConstants.version1) {
assertEquals(getInvalidOidStatusMessage, response.getErrorStatusText());
} else {
assertEquals(getInvalidOidStatusMessage, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
}
@Test
public void testCannotSetInvalidOid() throws IOException {
final Map<String, String> flowFileAttributes = getFlowFileAttributes(INVALID_OID);
final SNMPConfiguration snmpConfiguration = snmpConfigurationFactory.createSnmpGetSetConfiguration(agent.getPort());
snmpResourceHandler = SNMPFactoryProvider.getFactory(version).createSNMPResourceHandler(snmpConfiguration);
final SetSNMPHandler setSNMPHandler = new SetSNMPHandler(snmpResourceHandler);
final Optional<SNMPSingleResponse> optionalResponse = setSNMPHandler.set(flowFileAttributes);
if (optionalResponse.isPresent()) {
final SNMPSingleResponse response = optionalResponse.get();
assertEquals(setInvalidOidStatusMessage, response.getErrorStatusText());
} else {
fail("Response is not present.");
}
}
private Map<String, String> getFlowFileAttributes(String oid) {
final Map<String, String> attributes = new HashMap<>();
attributes.put(SNMP_PROP_PREFIX + oid, expectedOid);
flowFile.putAttributes(attributes);
return standardSnmpRequestHandler.set(flowFile);
attributes.put(SNMP_PROP_PREFIX + oid, TEST_OID_VALUE);
return attributes;
}
protected void assertSubTreeContainsOids(SNMPTreeResponse response) {
private Map<String, String> getFlowFileAttributesForSnmpGet(String... oids) {
final Map<String, String> attributes = new HashMap<>();
Arrays.stream(oids).forEach(oid -> attributes.put(SNMP_PROP_PREFIX + oid, null));
return attributes;
}
private void assertSubTreeContainsOids(SNMPTreeResponse response) {
final Map<String, String> attributes = response.getAttributes();
attributes.entrySet().forEach(this::checkEntryContainsSubString);
}
@ -124,7 +310,15 @@ public abstract class SNMPRequestTest {
}
});
if (!isMatch.get()) {
fail("Expected OID did not found in subtree.");
fail("Expected OID is not found in subtree.");
}
}
private static void registerManagedObjects(final TestAgent agent) {
agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_1), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_1)),
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_2), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_2)),
DefaultMOFactory.getInstance().createScalar(new OID(WRITE_ONLY_OID), MOAccessImpl.ACCESS_WRITE_ONLY, new OctetString(WRITE_ONLY_OID_VALUE))
);
}
}

View File

@ -0,0 +1,146 @@
/*
* 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.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.util.MockComponentLog;
import org.junit.Test;
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.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class SNMPTrapReceiverHandlerTest {
public static final String USERS_JSON = "src/test/resources/users.json";
@Test
public void testTrapReceiverCreatesCommandResponder() {
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);
when(snmpConfiguration.getManagerPort()).thenReturn(NetworkUtils.availablePort());
when(snmpConfiguration.getVersion()).thenReturn(SnmpConstants.version1);
final SNMPTrapReceiverHandler trapReceiverHandler = new SNMPTrapReceiverHandler(snmpConfiguration, null);
trapReceiverHandler.setSnmpManager(mockSnmpManager);
trapReceiverHandler.createTrapReceiver(mockProcessSessionFactory, mockComponentLog);
verify(mockSnmpManager).addCommandResponder(any(SNMPTrapReceiver.class));
assertTrue(trapReceiverHandler.isStarted());
}
@Test
public void testCloseTrapReceiverCleansUpResources() throws IOException {
final SNMPConfiguration snmpConfiguration = mock(SNMPConfiguration.class);
final ProcessSessionFactory mockProcessSessionFactory = mock(ProcessSessionFactory.class);
final MockComponentLog mockComponentLog = new MockComponentLog("componentId", new Object());
final USM mockUsm = mock(USM.class);
final Snmp mockSnmpManager = mock(Snmp.class);
when(mockSnmpManager.getUSM()).thenReturn(mockUsm);
when(snmpConfiguration.getManagerPort()).thenReturn(NetworkUtils.availablePort());
when(snmpConfiguration.getVersion()).thenReturn(SnmpConstants.version1);
final SNMPTrapReceiverHandler trapReceiverHandler = new SNMPTrapReceiverHandler(snmpConfiguration, null);
trapReceiverHandler.setSnmpManager(mockSnmpManager);
trapReceiverHandler.createTrapReceiver(mockProcessSessionFactory, mockComponentLog);
trapReceiverHandler.close();
verify(mockUsm).removeAllUsers();
verify(mockSnmpManager).close();
assertFalse(trapReceiverHandler.isStarted());
}
@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);
when(snmpConfiguration.getManagerPort()).thenReturn(NetworkUtils.availablePort());
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 SNMPTrapReceiverHandler trapReceiverHandler = new SNMPTrapReceiverHandler(snmpConfiguration, USERS_JSON);
trapReceiverHandler.setSnmpManager(mockSnmpManager);
trapReceiverHandler.createTrapReceiver(mockProcessSessionFactory, mockComponentLog);
verify(mockSnmpManager).addCommandResponder(any(SNMPTrapReceiver.class));
assertTrue(trapReceiverHandler.isStarted());
assertEquals(expectedUserAttributes, usmAttributes);
}
}

View File

@ -0,0 +1,153 @@
/*
* 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.operations;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.snmp.processors.ListenTrapSNMP;
import org.apache.nifi.util.LogMessage;
import org.apache.nifi.util.MockComponentLog;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.MockProcessSession;
import org.apache.nifi.util.SharedSessionState;
import org.junit.Before;
import org.junit.Test;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SNMPTrapReceiverTest {
private static final Object MOCK_COMPONENT_ID = new Object();
private ProcessSessionFactory mockProcessSessionFactory;
private MockProcessSession mockProcessSession;
private MockComponentLog mockComponentLog;
private PDU mockPdu;
private SNMPTrapReceiver snmpTrapReceiver;
@Before
public void init() {
mockProcessSessionFactory = mock(ProcessSessionFactory.class);
mockComponentLog = new MockComponentLog("componentId", MOCK_COMPONENT_ID);
mockPdu = mock(PDU.class);
snmpTrapReceiver = new SNMPTrapReceiver(mockProcessSessionFactory, mockComponentLog);
final ListenTrapSNMP listenTrapSNMP = new ListenTrapSNMP();
mockProcessSession = new MockProcessSession(new SharedSessionState(listenTrapSNMP, new AtomicLong(0L)), listenTrapSNMP);
}
@Test
public void testReceiveTrapWithNullPduLogsError() {
CommandResponderEvent mockEvent = mock(CommandResponderEvent.class);
snmpTrapReceiver.processPdu(mockEvent);
final LogMessage logMessage = mockComponentLog.getErrorMessages().get(0);
assertEquals(String.format("%s Request timed out or parameters are incorrect.", MOCK_COMPONENT_ID), logMessage.getMsg());
}
@Test
public void testReceiveTrapWithInvalidPduTypeLogsError() {
final CommandResponderEvent mockEvent = mock(CommandResponderEvent.class);
when(mockPdu.getType()).thenReturn(PDU.REPORT);
when(mockEvent.getPDU()).thenReturn(mockPdu);
snmpTrapReceiver.processPdu(mockEvent);
final LogMessage logMessage = mockComponentLog.getErrorMessages().get(0);
assertEquals(String.format("%s Request timed out or parameters are incorrect.", MOCK_COMPONENT_ID), logMessage.getMsg());
}
@Test
public void testTrapReceiverCreatesTrapPduV1FlowFile() {
final CommandResponderEvent mockEvent = mock(CommandResponderEvent.class);
final PDUv1 mockV1Pdu = mock(PDUv1.class);
when(mockV1Pdu.getType()).thenReturn(PDU.V1TRAP);
when(mockV1Pdu.getEnterprise()).thenReturn(new OID("1.3.6.1.2.1.1.1.0"));
when(mockV1Pdu.getSpecificTrap()).thenReturn(4);
final Vector<VariableBinding> vbs = new Vector<>();
doReturn(vbs).when(mockV1Pdu).getVariableBindings();
when(mockEvent.getPDU()).thenReturn(mockV1Pdu);
when(mockProcessSessionFactory.createSession()).thenReturn(mockProcessSession);
snmpTrapReceiver.processPdu(mockEvent);
final List<MockFlowFile> flowFiles = mockProcessSession.getFlowFilesForRelationship(ListenTrapSNMP.REL_SUCCESS);
final FlowFile flowFile = flowFiles.get(0);
assertEquals("1.3.6.1.2.1.1.1.0", flowFile.getAttribute("snmp$enterprise"));
assertEquals(String.valueOf(4), flowFile.getAttribute("snmp$specificTrapType"));
}
@Test
public void testTrapReceiverCreatesTrapPduV2FlowFile() {
final CommandResponderEvent mockEvent = mock(CommandResponderEvent.class);
when(mockPdu.getType()).thenReturn(PDU.TRAP);
when(mockPdu.getErrorIndex()).thenReturn(123);
when(mockPdu.getErrorStatusText()).thenReturn("test error status text");
final Vector<VariableBinding> vbs = new Vector<>();
doReturn(vbs).when(mockPdu).getVariableBindings();
when(mockEvent.getPDU()).thenReturn(mockPdu);
when(mockProcessSessionFactory.createSession()).thenReturn(mockProcessSession);
snmpTrapReceiver.processPdu(mockEvent);
final List<MockFlowFile> flowFiles = mockProcessSession.getFlowFilesForRelationship(ListenTrapSNMP.REL_SUCCESS);
final FlowFile flowFile = flowFiles.get(0);
assertEquals(String.valueOf(123), flowFile.getAttribute("snmp$errorIndex"));
assertEquals("test error status text", flowFile.getAttribute("snmp$errorStatusText"));
}
@Test
public void testReceiveTrapWithErrorGetsTransferredToFailure() {
final CommandResponderEvent mockEvent = mock(CommandResponderEvent.class);
when(mockPdu.getType()).thenReturn(PDU.TRAP);
when(mockPdu.getErrorStatus()).thenReturn(PDU.badValue);
final Vector<VariableBinding> vbs = new Vector<>();
doReturn(vbs).when(mockPdu).getVariableBindings();
when(mockEvent.getPDU()).thenReturn(mockPdu);
when(mockProcessSessionFactory.createSession()).thenReturn(mockProcessSession);
snmpTrapReceiver.processPdu(mockEvent);
final List<MockFlowFile> flowFiles = mockProcessSession.getFlowFilesForRelationship(ListenTrapSNMP.REL_FAILURE);
assertFalse(flowFiles.isEmpty());
final FlowFile flowFile = flowFiles.get(0);
assertEquals(String.valueOf(PDU.badValue), flowFile.getAttribute("snmp$errorStatus"));
}
}

View File

@ -1,86 +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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.junit.jupiter.api.Test;
import org.snmp4j.MessageException;
import org.snmp4j.mp.SnmpConstants;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class SNMPV1RequestTest extends SNMPRequestTest {
private static final String NO_SUCH_NAME = "No such name";
@Override
protected TestAgent getAgentInstance() {
return new TestSNMPV1Agent(LOCALHOST);
}
@Test
public void testSuccessfulSnmpGet() throws IOException {
final SNMPSingleResponse response = getResponseEvent(LOCALHOST, agent.getPort(), SnmpConstants.version1, READ_ONLY_OID_1);
assertEquals(READ_ONLY_OID_VALUE_1, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
@Test
public void testSuccessfulSnmpWalk() throws IOException {
final SNMPTreeResponse response = getTreeEvents(agent.getPort(), SnmpConstants.version1);
assertSubTreeContainsOids(response);
}
@Test
public void testSnmpGetTimeoutReturnsNull() {
assertThrows(RequestTimeoutException.class, () -> getResponseEvent(INVALID_HOST, agent.getPort(), SnmpConstants.version1, READ_ONLY_OID_1));
}
@Test
public void testSnmpGetWithInvalidTargetThrowsException() {
assertThrows(MessageException.class, () -> getResponseEvent(LOCALHOST, agent.getPort(), -1, READ_ONLY_OID_1));
}
@Test
public void testSuccessfulSnmpSet() throws IOException {
final SNMPSingleResponse response = getSetResponse(agent.getPort(), SnmpConstants.version1, WRITE_ONLY_OID, EXPECTED_OID_VALUE);
assertEquals(EXPECTED_OID_VALUE, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
@Test
public void testCannotSetReadOnlyObject() throws IOException {
final SNMPSingleResponse response = getSetResponse(agent.getPort(), SnmpConstants.version1, READ_ONLY_OID_1, EXPECTED_OID_VALUE);
assertEquals(NO_SUCH_NAME, response.getErrorStatusText());
}
@Test
public void testCannotGetWriteOnlyObject() throws IOException {
final SNMPSingleResponse response = getResponseEvent(LOCALHOST, agent.getPort(), SnmpConstants.version1, WRITE_ONLY_OID);
assertEquals(NO_SUCH_NAME, response.getErrorStatusText());
}
}

View File

@ -1,86 +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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV2cAgent;
import org.junit.jupiter.api.Test;
import org.snmp4j.MessageException;
import org.snmp4j.mp.SnmpConstants;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class SNMPV2CRequestTest extends SNMPRequestTest {
@Override
protected TestAgent getAgentInstance() {
return new TestSNMPV2cAgent(LOCALHOST);
}
@Test
public void testSuccessfulSnmpGet() throws IOException {
final SNMPSingleResponse response = getResponseEvent(LOCALHOST, agent.getPort(), SnmpConstants.version2c, READ_ONLY_OID_1);
assertEquals(READ_ONLY_OID_VALUE_1, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
@Test
public void testSuccessfulSnmpWalk() throws IOException {
final SNMPTreeResponse response = getTreeEvents(agent.getPort(), SnmpConstants.version2c);
assertSubTreeContainsOids(response);
}
@Test
public void testSnmpGetTimeoutReturnsNull() {
assertThrows(RequestTimeoutException.class, () -> getResponseEvent(INVALID_HOST, agent.getPort(), SnmpConstants.version2c, READ_ONLY_OID_1));
}
@Test
public void testSnmpGetWithInvalidTargetThrowsException() {
assertThrows(MessageException.class, () -> getResponseEvent(LOCALHOST, agent.getPort(), -1, READ_ONLY_OID_1));
}
@Test
public void testSuccessfulSnmpSet() throws IOException {
final SNMPSingleResponse response = getSetResponse(agent.getPort(), SnmpConstants.version2c, WRITE_ONLY_OID, EXPECTED_OID_VALUE);
assertEquals(EXPECTED_OID_VALUE, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
@Test
public void testCannotSetReadOnlyObject() throws IOException {
final SNMPSingleResponse response = getSetResponse(agent.getPort(), SnmpConstants.version2c, READ_ONLY_OID_1, EXPECTED_OID_VALUE);
assertEquals(NOT_WRITABLE, response.getErrorStatusText());
}
@Test
public void testCannotGetWriteOnlyObject() throws IOException {
final SNMPSingleResponse response = getResponseEvent(LOCALHOST, agent.getPort(), SnmpConstants.version2c, WRITE_ONLY_OID);
assertEquals(NO_ACCESS, response.getErrorStatusText());
}
}

View File

@ -1,135 +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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPTreeResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.apache.nifi.snmp.helper.SNMPTestUtils;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV3Agent;
import org.apache.nifi.util.MockFlowFile;
import org.junit.jupiter.api.Test;
import org.snmp4j.MessageException;
import org.snmp4j.SNMP4JSettings;
import org.snmp4j.Snmp;
import org.snmp4j.UserTarget;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.SecurityLevel;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class SNMPV3RequestTest extends SNMPRequestTest {
@Override
protected TestAgent getAgentInstance() {
return new TestSNMPV3Agent(LOCALHOST);
}
@Test
public void testSuccessfulSnmpGet() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3,
"SHA", "SHAAuthPassword");
final SNMPSingleResponse response = standardSnmpRequestHandler.get(READ_ONLY_OID_1);
assertEquals(READ_ONLY_OID_VALUE_1, response.getVariableBindings().get(0).getVariable());
assertEquals(SUCCESS, response.getErrorStatusText());
}
@Test
public void testSuccessfulSnmpWalk() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3,
"SHA", "SHAAuthPassword");
final SNMPTreeResponse response = standardSnmpRequestHandler.walk("1.3.6.1.4.1.32437");
assertSubTreeContainsOids(response);
}
@Test
public void testSnmpGetTimeoutReturnsNull() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(INVALID_HOST, SnmpConstants.version3,
"SHA", "SHAAuthPassword");
assertThrows(RequestTimeoutException.class, () -> standardSnmpRequestHandler.get(READ_ONLY_OID_1));
}
@Test
public void testSnmpGetWithInvalidTargetThrowsException() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, -1, "SHA", "SHAAuthPassword");
assertThrows(MessageException.class, () -> standardSnmpRequestHandler.get(READ_ONLY_OID_1));
}
@Test
public void testSuccessfulSnmpSet() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3,
"SHA", "SHAAuthPassword");
final MockFlowFile flowFile = new MockFlowFile(1L);
final Map<String, String> attributes = new HashMap<>();
attributes.put(SNMP_PROP_PREFIX + WRITE_ONLY_OID, EXPECTED_OID_VALUE);
flowFile.putAttributes(attributes);
final SNMPSingleResponse response = standardSnmpRequestHandler.set(flowFile);
assertEquals(EXPECTED_OID_VALUE, response.getVariableBindings().get(0).getVariable());
}
@Test
public void testCannotSetReadOnlyObject() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3,
"SHA", "SHAAuthPassword");
final MockFlowFile flowFile = new MockFlowFile(1L);
final Map<String, String> attributes = new HashMap<>();
attributes.put(SNMP_PROP_PREFIX + READ_ONLY_OID_1, EXPECTED_OID_VALUE);
flowFile.putAttributes(attributes);
final SNMPSingleResponse response = standardSnmpRequestHandler.set(flowFile);
assertEquals(NOT_WRITABLE, response.getErrorStatusText());
}
@Test
public void testCannotGetWriteOnlyObject() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3, "SHA", "SHAAuthPassword");
final SNMPSingleResponse response = standardSnmpRequestHandler.get(WRITE_ONLY_OID);
assertEquals(NO_ACCESS, response.getErrorStatusText());
}
@Test
public void testUnauthorizedUserSnmpGetReturnsNull() throws IOException {
final StandardSNMPRequestHandler standardSnmpRequestHandler = getSnmpV3Getter(LOCALHOST, SnmpConstants.version3,
"FakeUserName", "FakeAuthPassword");
final SNMPSingleResponse response = standardSnmpRequestHandler.get(READ_ONLY_OID_1);
assertEquals("Null", response.getVariableBindings().get(0).getVariable());
}
private StandardSNMPRequestHandler getSnmpV3Getter(final String host, final int version, final String sha, final String shaAuthPassword) throws IOException {
SNMP4JSettings.setForwardRuntimeExceptions(true);
final Snmp snmp = SNMPTestUtils.createSnmpClient();
final UserTarget userTarget = SNMPTestUtils.prepareUser(snmp, version, host + "/" + agent.getPort(), SecurityLevel.AUTH_NOPRIV,
sha, AuthSHA.ID, null, shaAuthPassword, null);
return new StandardSNMPRequestHandler(snmp, userTarget);
}
}

View File

@ -0,0 +1,109 @@
/*
* 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.operations;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.factory.trap.V1TrapPDUFactory;
import org.apache.nifi.snmp.factory.trap.V2TrapPDUFactory;
import org.apache.nifi.util.MockComponentLog;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import java.io.IOException;
import java.time.Instant;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class SendTrapSNMPHandlerTest {
private Target mockTarget;
private Snmp mockSnmpManager;
private PDU mockPdu;
private MockComponentLog mockComponentLog;
private V1TrapConfiguration mockV1TrapConfiguration;
private V2TrapConfiguration mockV2TrapConfiguration;
private SNMPResourceHandler snmpResourceHandler;
private SendTrapSNMPHandler sendTrapSNMPHandler;
@Before
public void init() {
mockTarget = mock(Target.class);
mockSnmpManager = mock(Snmp.class);
mockPdu = mock(PDU.class);
mockComponentLog = new MockComponentLog("id", new Object());
mockV1TrapConfiguration = mock(V1TrapConfiguration.class);
mockV2TrapConfiguration = mock(V2TrapConfiguration.class);
V1TrapPDUFactory mockV1TrapPDUFactory = mock(V1TrapPDUFactory.class);
when(mockV1TrapPDUFactory.get(mockV1TrapConfiguration)).thenReturn(mockPdu);
V2TrapPDUFactory mockV2TrapPDUFactory = mock(V2TrapPDUFactory.class);
when(mockV2TrapPDUFactory.get(mockV2TrapConfiguration)).thenReturn(mockPdu);
snmpResourceHandler = new SNMPResourceHandler(mockSnmpManager, mockTarget);
sendTrapSNMPHandler = new SendTrapSNMPHandler(snmpResourceHandler, Instant.now(), mockComponentLog) {
@Override
V1TrapPDUFactory createV1TrapPduFactory(final Instant startTime) {
return mockV1TrapPDUFactory;
}
@Override
V2TrapPDUFactory createV2TrapPduFactory(final Instant startTime) {
return mockV2TrapPDUFactory;
}
};
}
@After
public void tearDown() {
snmpResourceHandler.close();
}
@Test
public void testSendV1TrapWithValidFlowfile() throws IOException {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
sendTrapSNMPHandler.sendTrap(Collections.singletonMap("snmp$" + flowFileOid, "OID value"), mockV1TrapConfiguration);
verify(mockSnmpManager).send(mockPdu, mockTarget);
}
@Test
public void testSendV2TrapWithValidFlowfile() throws IOException {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
sendTrapSNMPHandler.sendTrap(Collections.singletonMap("snmp$" + flowFileOid, "OID value"), mockV2TrapConfiguration);
verify(mockSnmpManager).send(mockPdu, mockTarget);
}
@Test
public void testSendV1TrapWithFlowfileWithoutOptionalSnmpAttributes() throws IOException {
sendTrapSNMPHandler.sendTrap(Collections.singletonMap("invalid key", "invalid value"), mockV1TrapConfiguration);
verify(mockSnmpManager).send(mockPdu, mockTarget);
final String expectedDebugLog = "{} No optional SNMP specific variables found in flowfile.";
assertEquals(expectedDebugLog, mockComponentLog.getDebugMessages().get(0).getMsg());
}
}

View File

@ -0,0 +1,119 @@
/*
* 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.operations;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.exception.RequestTimeoutException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.PDUFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static org.apache.nifi.snmp.operations.SNMPResourceHandler.REQUEST_TIMEOUT_EXCEPTION_TEMPLATE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class SetSNMPHandlerTest {
private static final PDUFactory defaultSetPduFactory = new DefaultPDUFactory(PDU.SET);
private Target mockTarget;
private Snmp mockSnmpManager;
private PDU mockPdu;
private PDU mockResponsePdu;
private ResponseEvent mockResponseEvent;
private SetSNMPHandler setSNMPHandler;
@Before
public void init() {
mockTarget = mock(Target.class);
mockSnmpManager = mock(Snmp.class);
PDUFactory mockPduFactory = mock(PDUFactory.class);
mockPdu = mock(PDU.class);
mockResponsePdu = mock(PDU.class);
mockResponseEvent = mock(ResponseEvent.class);
when(mockPduFactory.createPDU(mockTarget)).thenReturn(mockPdu);
SNMPResourceHandler snmpResourceHandler = new SNMPResourceHandler(mockSnmpManager, mockTarget);
setSNMPHandler = new SetSNMPHandler(snmpResourceHandler);
SetSNMPHandler.setSetPduFactory(mockPduFactory);
}
@After
public void tearDown() {
SetSNMPHandler.setSetPduFactory(defaultSetPduFactory);
}
@Test
public void testSetSnmpValidResponse() throws IOException {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
final Map<String, String> flowFileAttributes = new HashMap<>();
flowFileAttributes.put("snmp$" + flowFileOid, "OID value");
when(mockResponseEvent.getResponse()).thenReturn(mockResponsePdu);
when(mockSnmpManager.set(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
setSNMPHandler.set(flowFileAttributes);
verify(mockSnmpManager).set(mockPdu, mockTarget);
}
@Test
public void testSetSnmpTimeoutThrowsException() throws IOException {
final String flowFileOid = "1.3.6.1.2.1.1.1.0";
final Map<String, String> flowFileAttributes = new HashMap<>();
flowFileAttributes.put("snmp$" + flowFileOid, "OID value");
when(mockSnmpManager.set(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final RequestTimeoutException requestTimeoutException = Assert.assertThrows(
RequestTimeoutException.class,
() -> setSNMPHandler.set(flowFileAttributes)
);
assertEquals(String.format(REQUEST_TIMEOUT_EXCEPTION_TEMPLATE, "write"), requestTimeoutException.getMessage());
}
@Test
public void testSetSnmpWithInvalidPduThrowsException() throws IOException {
final Map<String, String> flowFileAttributes = new HashMap<>();
flowFileAttributes.put("invalid key", "invalid value");
when(mockSnmpManager.set(any(PDU.class), any(Target.class))).thenReturn(mockResponseEvent);
final Optional<SNMPSingleResponse> optionalResponse = setSNMPHandler.set(flowFileAttributes);
assertFalse(optionalResponse.isPresent());
}
}

View File

@ -0,0 +1,162 @@
/*
* 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.processors;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.dto.SNMPSingleResponse;
import org.apache.nifi.snmp.dto.SNMPValue;
import org.apache.nifi.snmp.helper.testrunners.SNMPV1TestRunnerFactory;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.MockProcessContext;
import org.apache.nifi.util.MockProcessSession;
import org.apache.nifi.util.SharedSessionState;
import org.apache.nifi.util.TestRunner;
import org.junit.Before;
import org.junit.Test;
import org.snmp4j.mp.SnmpConstants;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class AbstractSNMPProcessorTest {
private static final String TEST_OID = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
private static final String UNSUPPORTED_SECURITY_LEVEL = "1.3.6.1.6.3.15.1.1.1";
private GetSNMP getSNMP;
private MockProcessContext mockProcessContext;
private MockProcessSession mockProcessSession;
private MockFlowFile mockFlowFile;
private SNMPSingleResponse mockResponse;
private TestRunner getTestRunner;
@Before
public void init() {
getTestRunner = new SNMPV1TestRunnerFactory().createSnmpGetTestRunner(NetworkUtils.availablePort(), TEST_OID, "GET");
getSNMP = (GetSNMP) getTestRunner.getProcessor();
mockProcessContext = new MockProcessContext(getSNMP);
mockProcessSession = new MockProcessSession(new SharedSessionState(getSNMP, new AtomicLong(0L)), getSNMP);
mockFlowFile = mockProcessSession.create();
mockResponse = mock(SNMPSingleResponse.class);
}
@Test
public void testProcessResponseWithInvalidResponseThrowsException() {
final String errorStatus = "Test error status text";
when(mockResponse.getErrorStatusText()).thenReturn(errorStatus);
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final String actualLogMessage = getTestRunner.getLogger().getErrorMessages().get(0).getMsg();
final String expectedLogMessage = String.format("SNMP request failed, response error: %s", errorStatus);
assertTrue(actualLogMessage.contains(expectedLogMessage));
}
@Test
public void testProcessResponseWithNoSuchObjectThrowsException() {
when(mockResponse.isValid()).thenReturn(true);
when(mockResponse.getVersion()).thenReturn(SnmpConstants.version2c);
List<SNMPValue> vbs = Collections.singletonList(new SNMPValue(TEST_OID, "noSuchObject"));
when(mockResponse.getVariableBindings()).thenReturn(vbs);
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final String actualLogMessage = getTestRunner.getLogger().getErrorMessages().get(0).getMsg();
final String expectedLogMessage = "SNMP request failed, response error: OID not found.";
assertTrue(actualLogMessage.contains(expectedLogMessage));
}
@Test
public void testValidProcessResponseWithoutVariableBindingThrowsException() {
when(mockResponse.isValid()).thenReturn(true);
when(mockResponse.getVersion()).thenReturn(SnmpConstants.version2c);
when(mockResponse.getVariableBindings()).thenReturn(Collections.emptyList());
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final String actualLogMessage = getTestRunner.getLogger().getErrorMessages().get(0).getMsg();
final String expectedLogMessage = "Empty SNMP response: no variable binding found.";
assertTrue(actualLogMessage.contains(expectedLogMessage));
}
@Test
public void testValidProcessResponse() {
when(mockResponse.isValid()).thenReturn(true);
when(mockResponse.getVersion()).thenReturn(SnmpConstants.version2c);
final List<SNMPValue> vbs = Collections.singletonList(new SNMPValue(TEST_OID, "testOIDValue"));
when(mockResponse.getVariableBindings()).thenReturn(vbs);
final Map<String, String> attributes = Collections.singletonMap(TEST_OID, "testOIDValue");
when(mockResponse.getAttributes()).thenReturn(attributes);
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final List<MockFlowFile> flowFilesForRelationship = mockProcessSession.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS);
assertEquals("testOIDValue", flowFilesForRelationship.get(0).getAttribute(TEST_OID));
}
@Test
public void testProcessResponseWithReportPduWithoutErrorMessage() {
when(mockResponse.isValid()).thenReturn(true);
when(mockResponse.isReportPdu()).thenReturn(true);
final List<SNMPValue> vbs = Collections.singletonList(new SNMPValue(TEST_OID, "testOIDValue"));
when(mockResponse.getVariableBindings()).thenReturn(vbs);
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final String actualLogMessage = getTestRunner.getLogger().getErrorMessages().get(0).getMsg();
final String expectedLogMessage = String.format("SNMP request failed, response error: Report-PDU returned, but no error message found. " +
"Please, check the OID %s in an online OID repository.", TEST_OID);
assertTrue(actualLogMessage.contains(expectedLogMessage));
}
@Test
public void testProcessResponseWithReportPdu() {
when(mockResponse.isValid()).thenReturn(true);
when(mockResponse.isReportPdu()).thenReturn(true);
final List<SNMPValue> vbs = Collections.singletonList(new SNMPValue(UNSUPPORTED_SECURITY_LEVEL, "testOIDValue"));
when(mockResponse.getVariableBindings()).thenReturn(vbs);
getSNMP.handleResponse(mockProcessContext, mockProcessSession, mockFlowFile, mockResponse, GetSNMP.REL_SUCCESS, GetSNMP.REL_FAILURE, "provenanceAddress");
final String actualLogMessage = getTestRunner.getLogger().getErrorMessages().get(0).getMsg();
final String expectedLogMessage = String.format("SNMP request failed, response error: Report-PDU returned. %s: usmStatsUnsupportedSecLevels", UNSUPPORTED_SECURITY_LEVEL);
assertTrue(actualLogMessage.contains(expectedLogMessage));
}
}

View File

@ -0,0 +1,154 @@
/*
* 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.processors;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.snmp.helper.testrunners.SNMPTestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV1TestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV2cTestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV3TestRunnerFactory;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.apache.nifi.snmp.testagents.TestSNMPV2cAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV3Agent;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@RunWith(Parameterized.class)
public class GetSNMPIntegrationTest {
private static final String LOCALHOST = "127.0.0.1";
private static final String READ_ONLY_OID_1 = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
private static final String READ_ONLY_OID_2 = "1.3.6.1.4.1.32437.1.5.1.4.3.0";
private static final String NOT_FOUND_OID = "1.3.4.1.2.1.343";
private static final String WALK_OID = "1.3.6.1.4.1.32437";
private static final String READ_ONLY_OID_VALUE_1 = "TestOID1";
private static final String READ_ONLY_OID_VALUE_2 = "TestOID2";
private static final String GET = "GET";
private static final String WALK = "WALK";
private static final SNMPTestRunnerFactory v1TestRunnerFactory = new SNMPV1TestRunnerFactory();
private static final SNMPTestRunnerFactory v2cTestRunnerFactory = new SNMPV2cTestRunnerFactory();
private static final SNMPTestRunnerFactory v3TestRunnerFactory = new SNMPV3TestRunnerFactory();
private static final TestAgent v1TestAgent = new TestSNMPV1Agent(LOCALHOST);
private static final TestAgent v2cTestAgent = new TestSNMPV2cAgent(LOCALHOST);
private static final TestAgent v3TestAgent = new TestSNMPV3Agent(LOCALHOST);
static {
registerManagedObjects(v1TestAgent);
registerManagedObjects(v2cTestAgent);
registerManagedObjects(v3TestAgent);
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{v1TestAgent, v1TestRunnerFactory},
{v2cTestAgent, v2cTestRunnerFactory},
{v3TestAgent, v3TestRunnerFactory}
});
}
private final TestAgent testAgent;
private final SNMPTestRunnerFactory testRunnerFactory;
public GetSNMPIntegrationTest(final TestAgent testAgent, final SNMPTestRunnerFactory testRunnerFactory) {
this.testAgent = testAgent;
this.testRunnerFactory = testRunnerFactory;
}
@Before
public void setUp() throws IOException {
testAgent.start();
}
@After
public void tearDown() {
testAgent.stop();
testAgent.unregister();
}
@Test
public void testSnmpGet() {
final TestRunner runner = testRunnerFactory.createSnmpGetTestRunner(testAgent.getPort(), READ_ONLY_OID_1, GET);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(READ_ONLY_OID_VALUE_1, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + READ_ONLY_OID_1 + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
@Test
public void testSnmpWalk() {
final TestRunner runner = testRunnerFactory.createSnmpGetTestRunner(testAgent.getPort(), WALK_OID, WALK);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(READ_ONLY_OID_VALUE_1, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + READ_ONLY_OID_1 + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
assertEquals(READ_ONLY_OID_VALUE_2, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + READ_ONLY_OID_2 + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
@Test
public void testSnmpGetWithEmptyResponse() {
final MockFlowFile mockFlowFile = new MockFlowFile(0L);
mockFlowFile.putAttributes(Collections.singletonMap("snmp$" + NOT_FOUND_OID, StringUtils.EMPTY));
final TestRunner runner = testRunnerFactory.createSnmpGetTestRunner(testAgent.getPort(), NOT_FOUND_OID, GET);
runner.enqueue(mockFlowFile);
runner.run();
if (testAgent == v1TestAgent) {
final MockFlowFile failureFF = runner.getFlowFilesForRelationship(GetSNMP.REL_FAILURE).get(0);
assertNotNull(failureFF);
assertEquals(StringUtils.EMPTY, failureFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + NOT_FOUND_OID));
assertEquals("No such name", failureFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "errorStatusText"));
} else {
final MockFlowFile failureFF = runner.getFlowFilesForRelationship(GetSNMP.REL_FAILURE).get(0);
assertNotNull(failureFF);
assertEquals("noSuchObject", failureFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + NOT_FOUND_OID + SNMPUtils.SNMP_PROP_DELIMITER + "128"));
assertEquals("Success", failureFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "errorStatusText"));
}
}
private static void registerManagedObjects(final TestAgent agent) {
agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_1), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_1)),
DefaultMOFactory.getInstance().createScalar(new OID(READ_ONLY_OID_2), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(READ_ONLY_OID_VALUE_2))
);
}
}

View File

@ -16,77 +16,47 @@
*/
package org.apache.nifi.snmp.processors;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.helper.testrunners.SNMPV1TestRunnerFactory;
import org.apache.nifi.util.MockProcessSession;
import org.apache.nifi.util.SharedSessionState;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
public class GetSNMPTest {
private static TestSNMPV1Agent snmpV1Agent;
private static final OID readOnlyOID1 = new OID("1.3.6.1.4.1.32437.1.5.1.4.2.0");
private static final OID readOnlyOID2 = new OID("1.3.6.1.4.1.32437.1.5.1.4.3.0");
private static final String OIDValue1 = "TestOID1";
private static final String OIDValue2 = "TestOID2";
private static final String GET = "GET";
private static final String WALK = "WALK";
private static final String OID = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
@BeforeAll
public static void setUp() throws IOException {
snmpV1Agent = new TestSNMPV1Agent("127.0.0.1");
snmpV1Agent.start();
snmpV1Agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(readOnlyOID1), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(OIDValue1)),
DefaultMOFactory.getInstance().createScalar(new OID(readOnlyOID2), MOAccessImpl.ACCESS_READ_ONLY, new OctetString(OIDValue2))
);
}
@Test
public void testOnTriggerWithGetStrategyPerformsSnmpGet() {
final TestRunner getSnmpTestRunner = new SNMPV1TestRunnerFactory().createSnmpGetTestRunner(NetworkUtils.availablePort(), OID, "GET");
final GetSNMP spyGetSNMP = spy((GetSNMP) getSnmpTestRunner.getProcessor());
final MockProcessSession mockProcessSession = new MockProcessSession(new SharedSessionState(spyGetSNMP, new AtomicLong(0L)), spyGetSNMP);
@AfterAll
public static void tearDown() {
snmpV1Agent.stop();
doNothing().when(spyGetSNMP).performSnmpGet(any(), any(), any(), any());
spyGetSNMP.onTrigger(getSnmpTestRunner.getProcessContext(), mockProcessSession);
verify(spyGetSNMP).performSnmpGet(any(), any(), any(), any());
}
@Test
public void testSnmpV1Get() {
final TestRunner runner = getTestRunner(readOnlyOID1.toString(), String.valueOf(snmpV1Agent.getPort()), GET);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(OIDValue1, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + readOnlyOID1.toString() + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
public void testOnTriggerWithWalkStrategyPerformsSnmpWalk() {
final TestRunner getSnmpTestRunner = new SNMPV1TestRunnerFactory().createSnmpGetTestRunner(NetworkUtils.availablePort(), OID, "WALK");
final GetSNMP spyGetSNMP = spy((GetSNMP) getSnmpTestRunner.getProcessor());
final MockProcessSession mockProcessSession = new MockProcessSession(new SharedSessionState(spyGetSNMP, new AtomicLong(0L)), spyGetSNMP);
@Test
public void testSnmpV1Walk() {
final TestRunner runner = getTestRunner("1.3.6.1.4.1.32437", String.valueOf(snmpV1Agent.getPort()), WALK);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(OIDValue1, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + readOnlyOID1.toString() + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
assertEquals(OIDValue2, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + readOnlyOID2.toString() + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
doNothing().when(spyGetSNMP).performSnmpWalk(any(), any(), any(), any());
private TestRunner getTestRunner(final String oid, final String port, final String strategy) {
final TestRunner runner = TestRunners.newTestRunner(GetSNMP.class);
runner.setProperty(GetSNMP.OID, oid);
runner.setProperty(GetSNMP.AGENT_HOST, "127.0.0.1");
runner.setProperty(GetSNMP.AGENT_PORT, port);
runner.setProperty(GetSNMP.SNMP_COMMUNITY, "public");
runner.setProperty(GetSNMP.SNMP_VERSION, "SNMPv1");
runner.setProperty(GetSNMP.SNMP_STRATEGY, strategy);
runner.setProperty(GetSNMP.SNMP_SECURITY_LEVEL, "noAuthNoPriv");
return runner;
spyGetSNMP.onTrigger(getSnmpTestRunner.getProcessContext(), mockProcessSession);
verify(spyGetSNMP).performSnmpWalk(any(), any(), any(), any());
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.processors;
import org.apache.nifi.snmp.helper.testrunners.SNMPTestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV1TestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV2cTestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV3TestRunnerFactory;
import org.apache.nifi.snmp.testagents.TestAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.apache.nifi.snmp.testagents.TestSNMPV2cAgent;
import org.apache.nifi.snmp.testagents.TestSNMPV3Agent;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@RunWith(Parameterized.class)
public class SetSNMPIntegrationTest {
private static final String LOCALHOST = "127.0.0.1";
private static final String TEST_OID = "1.3.6.1.4.1.32437.1.5.1.4.2.0";
private static final String TEST_OID_VALUE = "TestOID";
private static final SNMPTestRunnerFactory v1TestRunnerFactory = new SNMPV1TestRunnerFactory();
private static final SNMPTestRunnerFactory v2cTestRunnerFactory = new SNMPV2cTestRunnerFactory();
private static final SNMPTestRunnerFactory v3TestRunnerFactory = new SNMPV3TestRunnerFactory();
private static final TestAgent v1TestAgent = new TestSNMPV1Agent(LOCALHOST);
private static final TestAgent v2cTestAgent = new TestSNMPV2cAgent(LOCALHOST);
private static final TestAgent v3TestAgent = new TestSNMPV3Agent(LOCALHOST);
static {
registerManagedObjects(v1TestAgent);
registerManagedObjects(v2cTestAgent);
registerManagedObjects(v3TestAgent);
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{v1TestAgent, v1TestRunnerFactory},
{v2cTestAgent, v2cTestRunnerFactory},
{v3TestAgent, v3TestRunnerFactory}
});
}
private final TestAgent testAgent;
private final SNMPTestRunnerFactory testRunnerFactory;
public SetSNMPIntegrationTest(final TestAgent testAgent, final SNMPTestRunnerFactory testRunnerFactory) {
this.testAgent = testAgent;
this.testRunnerFactory = testRunnerFactory;
}
@Before
public void setUp() throws IOException {
testAgent.start();
}
@After
public void tearDown() {
testAgent.stop();
testAgent.unregister();
}
@Test
public void testSnmpSet() {
final TestRunner runner = testRunnerFactory.createSnmpSetTestRunner(testAgent.getPort(), TEST_OID, TEST_OID_VALUE);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(SetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(TEST_OID_VALUE, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + TEST_OID + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
private static void registerManagedObjects(final TestAgent agent) {
agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(TEST_OID), MOAccessImpl.ACCESS_READ_WRITE, new OctetString(TEST_OID_VALUE))
);
}
}

View File

@ -1,88 +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.processors;
import org.apache.nifi.snmp.testagents.TestSNMPV1Agent;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.snmp4j.agent.mo.DefaultMOFactory;
import org.snmp4j.agent.mo.MOAccessImpl;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class SetSNMPTest {
private static TestSNMPV1Agent snmpV1Agent;
private static final OID TEST_OID = new OID("1.3.6.1.4.1.32437.1.5.1.4.2.0");
private static final String TEST_OID_VALUE = "TestOID";
private static final String LOCALHOST = "127.0.0.1";
private static final String VALID_OID_FF_ATTRIBUTE = "snmp$1.3.6.1.4.1.32437.1.5.1.4.2.0$4";
private static final String INVALID_OID_FF_ATTRIBUTE = "snmp$1.3.6.1.4.1.32437.1.5.1.4.213.0$4";
@BeforeAll
public static void setUp() throws IOException {
snmpV1Agent = new TestSNMPV1Agent("127.0.0.1");
snmpV1Agent.start();
snmpV1Agent.registerManagedObjects(
DefaultMOFactory.getInstance().createScalar(new OID(TEST_OID), MOAccessImpl.ACCESS_READ_WRITE, new OctetString(TEST_OID_VALUE))
);
}
@AfterAll
public static void tearDown() {
snmpV1Agent.stop();
}
@Test
public void testSnmpV1Set() {
final TestRunner runner = getTestRunner(LOCALHOST, String.valueOf(snmpV1Agent.getPort()), VALID_OID_FF_ATTRIBUTE, true);
runner.run();
final MockFlowFile successFF = runner.getFlowFilesForRelationship(SetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals(TEST_OID_VALUE, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + TEST_OID.toString() + SNMPUtils.SNMP_PROP_DELIMITER + "4"));
}
private TestRunner getTestRunner(final String host, final String port, final String oid, final boolean withAttributes) {
final SetSNMP processor = new SetSNMP();
final TestRunner runner = TestRunners.newTestRunner(processor);
final MockFlowFile ff = new MockFlowFile(123);
if (withAttributes) {
final Map<String, String> attributes = ff.getAttributes();
final Map<String, String> newAttributes = new HashMap<>(attributes);
newAttributes.put(oid, TEST_OID_VALUE);
ff.putAttributes(newAttributes);
}
runner.enqueue(ff);
runner.setProperty(GetSNMP.AGENT_HOST, host);
runner.setProperty(GetSNMP.AGENT_PORT, port);
runner.setProperty(GetSNMP.SNMP_COMMUNITY, "public");
runner.setProperty(GetSNMP.SNMP_VERSION, "SNMPv1");
return runner;
}
}

View File

@ -0,0 +1,108 @@
/*
* 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.processors;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
import org.apache.nifi.snmp.helper.TrapConfigurationFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPTestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV1TestRunnerFactory;
import org.apache.nifi.snmp.helper.testrunners.SNMPV2cTestRunnerFactory;
import org.apache.nifi.snmp.utils.SNMPUtils;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.junit.Ignore;
import org.junit.Test;
import org.snmp4j.mp.SnmpConstants;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class TrapSNMPIntegrationTest {
protected static final String SYSTEM_DESCRIPTION_OID = "1.3.6.1.2.1.1.1.0";
protected static final String SYSTEM_DESCRIPTION_OID_VALUE = "optionalTrapOidTestValue";
@Test
public void testSendReceiveV1Trap() throws InterruptedException {
final int listenPort = NetworkUtils.availablePort();
final V1TrapConfiguration v1TrapConfiguration = TrapConfigurationFactory.getV1TrapConfiguration();
final SNMPTestRunnerFactory v1TestRunnerFactory = new SNMPV1TestRunnerFactory();
final TestRunner sendTrapTestRunner = v1TestRunnerFactory.createSnmpSendTrapTestRunner(listenPort, SYSTEM_DESCRIPTION_OID, SYSTEM_DESCRIPTION_OID_VALUE);
final TestRunner listenTrapTestRunner = v1TestRunnerFactory.createSnmpListenTrapTestRunner(listenPort);
listenTrapTestRunner.run(1, false);
sendTrapTestRunner.run(1);
Thread.sleep(50);
final MockFlowFile successFF = listenTrapTestRunner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals("Success", successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "errorStatusText"));
assertEquals(v1TrapConfiguration.getEnterpriseOid(), successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "enterprise"));
assertEquals(v1TrapConfiguration.getAgentAddress(), successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "agentAddress"));
assertEquals(String.valueOf(v1TrapConfiguration.getGenericTrapType()), successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "genericTrapType"));
assertEquals(String.valueOf(v1TrapConfiguration.getSpecificTrapType()), successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "specificTrapType"));
assertEquals(SYSTEM_DESCRIPTION_OID_VALUE, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + SYSTEM_DESCRIPTION_OID
+ SNMPUtils.SNMP_PROP_DELIMITER + "4"));
listenTrapTestRunner.shutdown();
}
@Test
public void testSendReceiveV2Trap() throws InterruptedException {
final int listenPort = NetworkUtils.availablePort();
final V2TrapConfiguration v2TrapConfiguration = TrapConfigurationFactory.getV2TrapConfiguration();
final SNMPTestRunnerFactory v2cTestRunnerFactory = new SNMPV2cTestRunnerFactory();
final TestRunner sendTrapTestRunner = v2cTestRunnerFactory.createSnmpSendTrapTestRunner(listenPort, SYSTEM_DESCRIPTION_OID, SYSTEM_DESCRIPTION_OID_VALUE);
final TestRunner listenTrapTestRunner = v2cTestRunnerFactory.createSnmpListenTrapTestRunner(listenPort);
listenTrapTestRunner.run(1, false);
sendTrapTestRunner.run(1);
Thread.sleep(50);
final MockFlowFile successFF = listenTrapTestRunner.getFlowFilesForRelationship(GetSNMP.REL_SUCCESS).get(0);
assertNotNull(successFF);
assertEquals("Success", successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + "errorStatusText"));
assertEquals(v2TrapConfiguration.getTrapOidValue(), successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + SnmpConstants.snmpTrapOID
+ SNMPUtils.SNMP_PROP_DELIMITER + "4"));
assertEquals(SYSTEM_DESCRIPTION_OID_VALUE, successFF.getAttribute(SNMPUtils.SNMP_PROP_PREFIX + SYSTEM_DESCRIPTION_OID
+ SNMPUtils.SNMP_PROP_DELIMITER + "4"));
listenTrapTestRunner.shutdown();
}
@Ignore("The ListenTrapSNMP and SendTrapSNMP processors use the same SecurityProtocols instance" +
" and same USM (the USM is stored in a map by version), hence this case shall be manually tested." +
" Check assertByVersion() to see what the trap payload must contain.")
@Test
public void testReceiveV3Trap() {
}
}

View File

@ -53,6 +53,11 @@ public abstract class TestAgent extends BaseAgent {
this.address = String.format("udp:%s/%d", host, port);
}
public void unregister() {
unregisterSnmpMIBs();
snmpMpdMib.unregisterMOs(server, getContext(snmpMpdMib));
}
@Override
protected void initTransportMappings() {
transportMappings = new TransportMapping[1];

View File

@ -0,0 +1,16 @@
[
{
"securityName":"user1",
"authProtocol":"MD5",
"authPassphrase":"abc12345",
"privProtocol":"DES",
"privPassphrase":"abc12345"
},
{
"securityName":"newUser2",
"authProtocol":"MD5",
"authPassphrase":"abc12345",
"privProtocol":"AES256",
"privPassphrase":"abc12345"
}
]