feat: Update SNMP monitor implementation and add net-snmp dependency

This commit is contained in:
Nawaz Dhandala
2026-01-29 08:22:04 +00:00
parent 3a317a8b55
commit d99b20327f
4 changed files with 94 additions and 123 deletions

View File

@@ -133,28 +133,30 @@ export default class SnmpMonitor {
) => {
let session: snmp.Session;
const sessionOptions: snmp.SessionOptions = {
port: config.port || 161,
timeout: options.timeout || config.timeout || 5000,
retries: 0, // We handle retries ourselves
version:
config.snmpVersion === SnmpVersion.V1
? snmp.Version1
: config.snmpVersion === SnmpVersion.V3
? snmp.Version3
: snmp.Version2c,
};
try {
if (config.snmpVersion === SnmpVersion.V3 && config.snmpV3Auth) {
const userOptions: snmp.UserOptions =
SnmpMonitor.buildV3UserOptions(config);
const sessionOptionsV3: snmp.SessionOptionsV3 = {
port: config.port || 161,
timeout: options.timeout || config.timeout || 5000,
retries: 0, // We handle retries ourselves
version: snmp.Version3,
};
const user: snmp.User = SnmpMonitor.buildV3User(config);
session = snmp.createV3Session(
config.hostname,
userOptions,
sessionOptions,
user,
sessionOptionsV3,
);
} else {
const sessionOptions: snmp.SessionOptions = {
port: config.port || 161,
timeout: options.timeout || config.timeout || 5000,
retries: 0, // We handle retries ourselves
version:
config.snmpVersion === SnmpVersion.V1
? snmp.Version1
: snmp.Version2c,
};
session = snmp.createSession(
config.hostname,
config.communityString || "public",
@@ -172,10 +174,10 @@ export default class SnmpMonitor {
return;
}
session.get(oids, (error: Error | null, varbinds: snmp.Varbind[]) => {
if (error) {
session.get(oids, (error, varbinds) => {
if (error || !varbinds) {
session.close();
reject(error);
reject(error || new Error("No varbinds returned"));
return;
}
@@ -212,11 +214,9 @@ export default class SnmpMonitor {
);
}
private static buildV3UserOptions(
config: MonitorStepSnmpMonitor,
): snmp.UserOptions {
private static buildV3User(config: MonitorStepSnmpMonitor): snmp.User {
const v3Auth = config.snmpV3Auth!;
const userOptions: snmp.UserOptions = {
const user: snmp.User = {
name: v3Auth.username,
level: SnmpMonitor.mapSecurityLevel(v3Auth.securityLevel),
};
@@ -225,16 +225,16 @@ export default class SnmpMonitor {
v3Auth.securityLevel === SnmpSecurityLevel.AuthNoPriv ||
v3Auth.securityLevel === SnmpSecurityLevel.AuthPriv
) {
userOptions.authProtocol = SnmpMonitor.mapAuthProtocol(v3Auth.authProtocol);
userOptions.authKey = v3Auth.authKey;
user.authProtocol = SnmpMonitor.mapAuthProtocol(v3Auth.authProtocol);
user.authKey = v3Auth.authKey || "";
}
if (v3Auth.securityLevel === SnmpSecurityLevel.AuthPriv) {
userOptions.privProtocol = SnmpMonitor.mapPrivProtocol(v3Auth.privProtocol);
userOptions.privKey = v3Auth.privKey;
user.privProtocol = SnmpMonitor.mapPrivProtocol(v3Auth.privProtocol);
user.privKey = v3Auth.privKey || "";
}
return userOptions;
return user;
}
private static mapSecurityLevel(
@@ -254,7 +254,7 @@ export default class SnmpMonitor {
private static mapAuthProtocol(
protocol: SnmpAuthProtocol | undefined,
): snmp.AuthProtocol {
): snmp.AuthProtocols {
switch (protocol) {
case SnmpAuthProtocol.MD5:
return snmp.AuthProtocols.md5;
@@ -271,7 +271,7 @@ export default class SnmpMonitor {
private static mapPrivProtocol(
protocol: SnmpPrivProtocol | undefined,
): snmp.PrivProtocol {
): snmp.PrivProtocols {
switch (protocol) {
case SnmpPrivProtocol.DES:
return snmp.PrivProtocols.des;
@@ -303,7 +303,7 @@ export default class SnmpMonitor {
return String(varbind.value);
}
private static mapSnmpDataType(type: number): SnmpDataType {
private static mapSnmpDataType(type: snmp.ObjectType | undefined): SnmpDataType {
switch (type) {
case snmp.ObjectType.Integer:
return SnmpDataType.Integer;
@@ -336,7 +336,7 @@ export default class SnmpMonitor {
}
}
private static mapSnmpErrorType(type: number): SnmpDataType {
private static mapSnmpErrorType(type: snmp.ObjectType | undefined): SnmpDataType {
switch (type) {
case snmp.ObjectType.NoSuchObject:
return SnmpDataType.NoSuchObject;

View File

@@ -15,12 +15,14 @@
"ejs": "^3.1.10",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.5",
"net-snmp": "^3.14.1",
"ping": "^0.4.4",
"playwright": "^1.57.0",
"ts-node": "^10.9.1"
},
"devDependencies": {
"@types/jest": "^27.5.2",
"@types/net-snmp": "^3.23.0",
"@types/node": "^17.0.31",
"jest": "^28.1.0",
"nodemon": "^2.0.20",
@@ -285,6 +287,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz",
"integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
"dev": true,
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.23.5",
@@ -1253,10 +1256,31 @@
"pretty-format": "^27.0.0"
}
},
"node_modules/@types/net-snmp": {
"version": "3.23.0",
"resolved": "https://registry.npmjs.org/@types/net-snmp/-/net-snmp-3.23.0.tgz",
"integrity": "sha512-54Y5NLlQ8isegHTUZdEaIFhR1iz/qlRkQlpkuXfsWjWDVLNfStLmvraaj9ZS7tmcZEltFkb4ZeDBjnSYeFc3+w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "^24.3.0"
}
},
"node_modules/@types/net-snmp/node_modules/@types/node": {
"version": "24.10.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
}
},
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"peer": true
},
"node_modules/@types/ping": {
"version": "0.4.4",
@@ -1389,6 +1413,12 @@
"sprintf-js": "~1.0.2"
}
},
"node_modules/asn1-ber": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/asn1-ber/-/asn1-ber-1.2.2.tgz",
"integrity": "sha512-CbNem/7hxrjSiOAOOTX4iZxu+0m3jiLqlsERQwwPM1IDR/22M8IPpA1VVndCLw5KtjRYyRODbvAEIfuTogNDng==",
"license": "MIT"
},
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
@@ -1558,6 +1588,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001565",
"electron-to-chromium": "^1.4.601",
@@ -2728,6 +2759,7 @@
"resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz",
"integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==",
"dev": true,
"peer": true,
"dependencies": {
"@jest/core": "^28.1.3",
"@jest/types": "^28.1.3",
@@ -3883,6 +3915,16 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/net-snmp": {
"version": "3.26.1",
"resolved": "https://registry.npmjs.org/net-snmp/-/net-snmp-3.26.1.tgz",
"integrity": "sha512-ZWsfchno5Lxj6OOUt4YS+88KLwce4tpnh4pLxiiwUULg3QQsN1n4OYAli4Ch2C+fkjqQXjhoI8rKltQyBVFzxg==",
"license": "MIT",
"dependencies": {
"asn1-ber": "^1.2.1",
"smart-buffer": "^4.1.0"
}
},
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -4427,6 +4469,16 @@
"node": ">=8"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -4710,6 +4762,7 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -4788,6 +4841,13 @@
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"dev": true,
"license": "MIT"
},
"node_modules/update-browserslist-db": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",

View File

@@ -34,6 +34,7 @@
},
"devDependencies": {
"@types/jest": "^27.5.2",
"@types/net-snmp": "^3.23.0",
"@types/node": "^17.0.31",
"jest": "^28.1.0",
"nodemon": "^2.0.20",

View File

@@ -1,90 +0,0 @@
declare module "net-snmp" {
export const Version1: number;
export const Version2c: number;
export const Version3: number;
export enum SecurityLevel {
noAuthNoPriv = 1,
authNoPriv = 2,
authPriv = 3,
}
export const AuthProtocols: {
md5: AuthProtocol;
sha: AuthProtocol;
sha256: AuthProtocol;
sha512: AuthProtocol;
};
export const PrivProtocols: {
des: PrivProtocol;
aes: PrivProtocol;
aes256b: PrivProtocol;
};
export const ObjectType: {
Boolean: number;
Integer: number;
OctetString: number;
Null: number;
OID: number;
IpAddress: number;
Counter: number;
Counter32: number;
Gauge: number;
Gauge32: number;
TimeTicks: number;
Opaque: number;
Counter64: number;
NoSuchObject: number;
NoSuchInstance: number;
EndOfMibView: number;
};
export type AuthProtocol = number;
export type PrivProtocol = number;
export interface SessionOptions {
port?: number;
timeout?: number;
retries?: number;
version?: number;
}
export interface UserOptions {
name: string;
level: SecurityLevel;
authProtocol?: AuthProtocol;
authKey?: string;
privProtocol?: PrivProtocol;
privKey?: string;
}
export interface Varbind {
oid: string;
type: number;
value: unknown;
}
export interface Session {
get(
oids: string[],
callback: (error: Error | null, varbinds: Varbind[]) => void,
): void;
close(): void;
}
export function createSession(
target: string,
community: string,
options?: SessionOptions,
): Session;
export function createV3Session(
target: string,
user: UserOptions,
options?: SessionOptions,
): Session;
export function isVarbindError(varbind: Varbind): boolean;
}