Skip to content

feat(core): add SNMP trap source for UDP trap ingestion#24514

Open
RoseSecurity wants to merge 6 commits intovectordotdev:masterfrom
RoseSecurity:add-snmp-trap-vector-source
Open

feat(core): add SNMP trap source for UDP trap ingestion#24514
RoseSecurity wants to merge 6 commits intovectordotdev:masterfrom
RoseSecurity:add-snmp-trap-vector-source

Conversation

@RoseSecurity
Copy link
Copy Markdown

SNMP Trap Source

Summary

This PR adds a new snmp_trap source that receives SNMP v1 and v2c trap messages over UDP. SNMP traps are commonly used by network devices to report events like failures, threshold violations, or status changes to a management station.

Features

  • Listens for SNMP traps on a configurable UDP address/port
  • Supports both SNMPv1 and SNMPv2c trap formats
  • Parses trap messages into structured log events
  • Extracts all variable bindings (varbinds) as JSON array
  • Configurable host key for source identification

Vector Config Example

# Basic configuration - listen on standard SNMP trap port
sources:
  snmp_traps:
    type: snmp_trap
    address: "0.0.0.0:162"

sinks:
  console:
    type: console
    inputs: ["snmp_traps"]
    encoding:
      codec: json
# Non-privileged port with custom buffer size
sources:
  snmp_traps:
    type: snmp_trap
    address: "0.0.0.0:1162"
    receive_buffer_bytes: 65536
    host_key: "source_host"

transforms:
  enrich_traps:
    type: remap
    inputs: ["snmp_traps"]
    source: |
      # Add severity based on trap type
      if .snmp_version == "1" {
        .severity = if .generic_trap == 4 { "critical" } else { "info" }
      }

sinks:
  console:
    type: console
    inputs: ["enrich_traps"]
    encoding:
      codec: json

Output Schema

SNMPv1 Trap Output

{
  "snmp_version": "1",
  "source_address": "192.168.1.100:161",
  "community": "public",
  "enterprise_oid": "1.3.6.1.4.1.8072.2.3.0.1",
  "agent_address": "192.168.1.100",
  "generic_trap": 6,
  "specific_trap": 1,
  "uptime": 123456,
  "varbinds": [
    {"oid": "1.3.6.1.4.1.8072.2.3.2.1", "value": "123456"}
  ],
  "message": "SNMPv1 trap from 192.168.1.100:161 (1.3.6.1.4.1.8072.2.3.0.1): enterpriseSpecific",
  "timestamp": "2024-01-15T10:30:00Z"
}

SNMPv2c Trap Output

{
  "snmp_version": "2c",
  "source_address": "192.168.1.100:161",
  "community": "public",
  "request_id": 12345,
  "trap_oid": "1.3.6.1.4.1.8072.2.3.0.1",
  "uptime": "123456",
  "varbinds": [
    {"oid": "1.3.6.1.2.1.1.3.0", "value": "123456"},
    {"oid": "1.3.6.1.6.3.1.1.4.1.0", "value": "1.3.6.1.4.1.8072.2.3.0.1"}
  ],
  "message": "SNMPv2c trap from 192.168.1.100:161: 1.3.6.1.4.1.8072.2.3.0.1",
  "timestamp": "2024-01-15T10:30:00Z"
}

Test Plan

Prerequisites

  • snmptrap command (from net-snmp package)
  • Vector built with --features sources-snmp_trap

Manual Testing Steps

  1. Build Vector with SNMP trap support:

    cargo build --features sources-snmp_trap,sinks-console
  2. Create test configuration (test_snmp.yaml):

    sources:
      snmp_traps:
        type: snmp_trap
        address: "127.0.0.1:1162"
    
    sinks:
      console:
        type: console
        inputs: ["snmp_traps"]
        encoding:
          codec: json
  3. Start Vector:

    ./target/debug/vector --config test_snmp.yaml
  4. Send SNMPv2c test trap (in another terminal):

    snmptrap -v 2c -c public 127.0.0.1:1162 '' \
      1.3.6.1.4.1.8072.2.3.0.1 \
      1.3.6.1.4.1.8072.2.3.2.1 i 123456
  5. Send SNMPv1 test trap:

    snmptrap -v 1 -c public 127.0.0.1:1162 \
      1.3.6.1.4.1.8072.2.3.0.1 \
      127.0.0.1 6 1 '' \
      1.3.6.1.4.1.8072.2.3.2.1 i 123456
  6. Verify output: Confirm JSON output appears in Vector's console with all expected fields.

Automated Tests

Run the unit tests:

cargo test --features sources-snmp_trap snmp

Expected: All 7 tests pass:

  • generate_config - Config generation works
  • test_udp_socket_bind - Can bind to UDP socket
  • test_config_default - Default config is correct
  • test_config_with_options - Config with options works
  • test_format_object_value - SNMP value formatting works
  • test_parse_invalid_data - Invalid data is rejected
  • test_parse_empty_data - Empty data is rejected

Checklist

  • Add snmp-parser dependency
  • Implement SNMP trap source
  • Implement SNMPv1 and SNMPv2c parser
  • Add internal events for error tracking
  • Add unit tests
  • Add example configuration
  • Add changelog entry
  • Add CUE documentation
  • Add service and URL definitions

References

Introduce a new `snmp_trap` source to receive SNMP v1 and v2c trap
messages over UDP. The source parses incoming traps, extracts fields
such as community string, version, trap type, OID, and varbinds, and
emits structured log events. Includes documentation, changelog, and
example configuration for easy adoption.
@RoseSecurity RoseSecurity requested review from a team as code owners January 19, 2026 19:42
@github-actions github-actions Bot added domain: sources Anything related to the Vector's sources domain: external docs Anything related to Vector's external, public documentation labels Jan 19, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 19, 2026

Thank you for your contribution! Before we can merge this PR, please sign our Contributor License Agreement.

To sign, copy and post the phrase below as a new comment on this PR.

Note: If the bot says your username was not found, the email used in your git commit may not be linked to your GitHub account. Fix this at github.com/settings/emails, then comment recheck to retry.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@RoseSecurity RoseSecurity changed the title feat(source): add SNMP trap source for UDP trap ingestion feat(core): add SNMP trap source for UDP trap ingestion Jan 19, 2026
@domalessi domalessi self-assigned this Jan 20, 2026
domalessi
domalessi previously approved these changes Jan 20, 2026
Copy link
Copy Markdown
Member

@pront pront left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @RoseSecurity!

Findings from review of PR #24514:

Standalone feature build is broken

sources-snmp_trap uses tokio_util::udp::UdpFramed, but the feature does not enable tokio-util/net.

SNMPv2c parser accepts non-trap PDUs as traps

parse_v2c_trap matches any SnmpPdu::Generic and never checks pdu_type == TrapV2, so GetRequest, Response, InformRequest, etc. can be emitted as trap events.

uptime field type is inconsistent across versions

SNMPv1 writes uptime as integer, SNMPv2c writes it as string.

RoseSecurity and others added 2 commits March 3, 2026 13:29
- Add PduType check to only handle TrapV2 PDU types
- Fix sysUpTime extraction to properly parse TimeTicks value
- Add tokio-util/net feature dependency for snmp_trap source
@RoseSecurity
Copy link
Copy Markdown
Author

Thank you @RoseSecurity!

Findings from review of PR #24514:

Standalone feature build is broken

sources-snmp_trap uses tokio_util::udp::UdpFramed, but the feature does not enable tokio-util/net.

SNMPv2c parser accepts non-trap PDUs as traps

parse_v2c_trap matches any SnmpPdu::Generic and never checks pdu_type == TrapV2, so GetRequest, Response, InformRequest, etc. can be emitted as trap events.

uptime field type is inconsistent across versions

SNMPv1 writes uptime as integer, SNMPv2c writes it as string.

Thanks for the review! Just took a crack at addressing those findings

@tot19
Copy link
Copy Markdown
Contributor

tot19 commented Mar 29, 2026

Hey @RoseSecurity — just checking in on the status of this PR. Are you still actively working on it, or could you use a hand getting it across the finish line?

Also curious about your plans for broader RFC compliance beyond what's here today. The current implementation covers SNMPv1 (RFC 1157) and SNMPv2c (RFC 3416) trap reception — are you planning to address any of the following in this PR or follow-up work?

  • SNMPv3 (RFC 3414/3826) — USM authentication and privacy (HMAC-SHA, AES encryption)
  • INFORM handling (RFC 3416) — InformRequest PDUs that expect an acknowledgment response
  • MIB resolution (RFC 2578) — translating raw OIDs to human-readable names

Happy to help push this forward if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: external docs Anything related to Vector's external, public documentation domain: sources Anything related to the Vector's sources

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants