Redfish: Implement SNMP Trap

Implement SNMPTrap in EventDestination of Redfish. We can use
this Redfish interface to add/get/delete the SNMPTrap port and
destination address. When the error

log is generated, phosphor-snmp
will send SNMPTrap messages to our configured SNMPTrap destination.

The MIB is here:
[1] https://github.com/openbmc/phosphor-snmp/blob/master/mibs/NotificationMIB.txt

Refer:
[1] https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2019.3.pdf

SNMPTrap test: Tested ok on the Witherspoon machine.
Steps are as follows:
1. Use this Redfish interface to configure the port and
   destination address:
   curl -k -H "X-Auth-Token: $token" -X POST
   https://${bmc}/redfish/v1/EventService/Subscriptions
   -d '{"Destination": "snmp://192.168.31.89:162",
   "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c"}'
2. Run the SNMPTrap receiver tool in the destination
   computer(192.168.31.89),I used iReasoning MIB Browser as the
   SNMPTrap receiving tool.
3. Trigger error logs such as power supply AC Lost. We will see
   the error log under /xyz/openbmc_project/logging.
4. The SNMPTrap receiver tool in the destination computer received
   the SNMPTrap sent by OpenBMC.

Tested: Validator passes
1. Add snmp client:
        curl -k -H "X-Auth-Token: $token" -X POST
        https://${bmc}/redfish/v1/EventService/Subscriptions
        -d '{"Destination": "snmp://192.168.31.89:162",
       "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c",
       "Context": "testContext"}'
        {
          "@Message.ExtendedInfo": [
            {
              "@odata.type": "#Message.v1_0_0.Message",
              "Message": "The resource has been created successfully",
              "MessageArgs": [],
              "MessageId": "Base.1.8.1.Created",
              "MessageSeverity": "OK",
              "Resolution": "None"
            }
          ]
        }
2. Get snmp trap client configurations:
curl -k -H "X-Auth-Token: $token" -X GET
https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1
{
  "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1",
  "@odata.type": "#EventDestination.v1_7_0.EventDestination",
  "Context": "testContext",
  "Destination": "snmp://192.168.31.89:162",
  "EventFormatType": "Event",
  "Id": "snmp1",
  "Name": "Event Destination snmp1",
  "Protocol": "SNMPv2c",
  "SubscriptionType": "SNMPTrap"
}

Reboot the BMC, and get the snmp trap client again:
curl -k -H "X-Auth-Token: $token" -X GET
https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1
{
  "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1",
  "@odata.type": "#EventDestination.v1_7_0.EventDestination",
  "Context": "testContext",
  "Destination": "snmp://192.168.31.89:162",
  "EventFormatType": "Event",
  "Id": "snmp1",
  "Name": "Event Destination snmp1",
  "Protocol": "SNMPv2c",
  "SubscriptionType": "SNMPTrap"
}

3. Delete snmp client:
curl -k -H "X-Auth-Token: $token" -X DELETE
https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1
{
  "@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "Successfully Completed Request",
      "MessageArgs": [],
      "MessageId": "Base.1.8.1.Success",
      "MessageSeverity": "OK",
      "Resolution": "None"
    }
  ]
}
4. After we have added some SNMP clients using Redfish, we can see them
   in Dbus:
busctl tree xyz.openbmc_project.Network.SNMP
`-/xyz
  `-/xyz/openbmc_project
    `-/xyz/openbmc_project/network
      `-/xyz/openbmc_project/network/snmp
        `-/xyz/openbmc_project/network/snmp/manager
          |-/xyz/openbmc_project/network/snmp/manager/1

busctl introspect xyz.openbmc_project.Network.SNMP
/xyz/openbmc_project/network/snmp/manager/1
xyz.openbmc_project.Network.Client
NAME       TYPE      SIGNATURE RESULT/VALUE    FLAGS
.Address   property  s         "192.168.31.89" emits-change writable
.Port      property  q         162             emits-change writable

5. Use "busctl call" add client
busctl call xyz.openbmc_project.Network.SNMP
/xyz/openbmc_project/network/snmp/manager
xyz.openbmc_project.Network.Client.Create
Client sq 192.168.31.90 162
s "/xyz/openbmc_project/network/snmp/manager/2"

We will see it use the redfish url:
curl -k -H "X-Auth-Token: $token" -X GET
https://${bmc}/redfish/v1/EventService/Subscriptions/snmp2
{
  "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp2",
  "@odata.type": "#EventDestination.v1_7_0.EventDestination",
  "Context": "",
  "Destination": "snmp://192.168.31.90:162",
  "EventFormatType": "Event",
  "Id": "snmp2",
  "Name": "Event Destination snmp2",
  "Protocol": "SNMPv2c",
  "SubscriptionType": "SNMPTrap"
}

6. Deleting snmp client using "busctl"
First, we use redfish to add some SNMP clients:
 curl -k -H "X-Auth-Token: $token" -X POST
 https://${bmc}/redfish/v1/EventService/Subscriptions
 -d '{"Destination": "snmp://192.168.31.90:162",
 "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c",
 "Context": "testContext0"}'

 curl -k -H "X-Auth-Token: $token" -X POST
 https://${bmc}/redfish/v1/EventService/Subscriptions
 -d '{"Destination": "snmp://192.168.31.91:162",
 "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c",
 "Context": "testContext1"}'

Then we can use redfish to get the subscriptions:
 curl -k -H "X-Auth-Token: $token" -XGET
 https://${bmc}/redfish/v1/EventService/Subscriptions
 {
  "@odata.id": "/redfish/v1/EventService/Subscriptions",
"@odata.type":"#EventDestinationCollection.EventDestinationCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1"
    },
    {
      "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp2"
    }
  ],
  "Members@odata.count": 2,
  "Name": "Event Destination Collections"
 }

Now we use busctl to delete SNMP client 2:
 busctl call xyz.openbmc_project.Network.SNMP
 /xyz/openbmc_project/network/snmp/manager/2
 xyz.openbmc_project.Object.Delete Delete

Then we won't see snmp2 in the subscriptions of redfish:
 curl -k -H "X-Auth-Token: $token" -XGET
 https://${bmc}/redfish/v1/EventService/Subscriptions
 {
  "@odata.id": "/redfish/v1/EventService/Subscriptions",
"@odata.type":"#EventDestinationCollection.EventDestinationCollection",

  "Members": [
    {
      "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1"
    }
  ],
  "Members@odata.count": 1,
  "Name": "Event Destination Collections"
 }

7. Test the generic event subscription to make sure it didn't impacted
Add Redfish subscription:
curl -k -H "X-Auth-Token: $token" -X POST
 https://${bmc}/redfish/v1/EventService/Subscriptions
 -d '{"Destination": "https://192.168.31.189:443",
"SubscriptionType": "RedfishEvent", "Protocol": "Redfish",
"Context": "testContext"}'
{
  "@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The resource has been created successfully.",
      "MessageArgs": [],
      "MessageId": "Base.1.13.0.Created",
      "MessageSeverity": "OK",
      "Resolution": "None."
    }
  ]

Get Redfish subscription:
 curl -k -H "X-Auth-Token: $token" -X GET
 https://${bmc}/redfish/v1/EventService/Subscriptions/1358109191
{
  "@odata.id": "/redfish/v1/EventService/Subscriptions/1358109191",
  "@odata.type": "#EventDestination.v1_8_0.EventDestination",
  "Context": "testContext",
  "DeliveryRetryPolicy": "TerminateAfterRetries",
  "Destination": "https://192.168.31.189:443",
  "EventFormatType": "Event",
  "HttpHeaders": [],
  "Id": "1358109191",
  "MessageIds": [],

  "MetricReportDefinitions": [],
  "Name": "Event Destination 1358109191",
  "Protocol": "Redfish",
  "RegistryPrefixes": [],
  "ResourceTypes": [],
  "SubscriptionType": "RedfishEvent"
}

Signed-off-by: Chicago Duan <duanzhijia01@inspur.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ie589b3934ee749c7e0add35e3ed1b0b7e817c557
3 files changed
tree: 702197e96fcd5f160e1eeed6c14a827f85135621
  1. .github/
  2. config/
  3. http/
  4. include/
  5. redfish-core/
  6. scripts/
  7. src/
  8. static/
  9. subprojects/
  10. test/
  11. .clang-format
  12. .clang-tidy
  13. .dockerignore
  14. .gitignore
  15. .markdownlint.yaml
  16. .openbmc-enforce-gitlint
  17. .prettierignore
  18. .shellcheck
  19. AGGREGATION.md
  20. CLIENTS.md
  21. COMMON_ERRORS.md
  22. DBUS_USAGE.md
  23. DEVELOPING.md
  24. HEADERS.md
  25. LICENSE
  26. meson.build
  27. meson_options.txt
  28. OEM_SCHEMAS.md
  29. OWNERS
  30. README.md
  31. Redfish.md
  32. run-ci
  33. setup.cfg
  34. TESTING.md
README.md

OpenBMC webserver

This component attempts to be a "do everything" embedded webserver for OpenBMC.

Features

The webserver implements a few distinct interfaces:

  • DBus event websocket. Allows registering on changes to specific dbus paths, properties, and will send an event from the websocket if those filters match.
  • OpenBMC DBus REST api. Allows direct, low interference, high fidelity access to dbus and the objects it represents.
  • Serial: A serial websocket for interacting with the host serial console through websockets.
  • Redfish: A protocol compliant, DBus to Redfish translator.
  • KVM: A websocket based implementation of the RFB (VNC) frame buffer protocol intended to mate to webui-vue to provide a complete KVM implementation.

Protocols

bmcweb at a protocol level supports http and https. TLS is supported through OpenSSL.

AuthX

Authentication

Bmcweb supports multiple authentication protocols:

  • Basic authentication per RFC7617
  • Cookie based authentication for authenticating against webui-vue
  • Mutual TLS authentication based on OpenSSL
  • Session authentication through webui-vue
  • XToken based authentication conformant to Redfish DSP0266

Each of these types of authentication is able to be enabled or disabled both via runtime policy changes (through the relevant Redfish APIs) or via configure time options. All authentication mechanisms supporting username/password are routed to libpam, to allow for customization in authentication implementations.

Authorization

All authorization in bmcweb is determined at routing time, and per route, and conform to the Redfish PrivilegeRegistry.

*Note: Non-Redfish functions are mapped to the closest equivalent Redfish privilege level.

Configuration

bmcweb is configured per the meson build files. Available options are documented in meson_options.txt

Compile bmcweb with default options

meson setup builddir
ninja -C builddir

If any of the dependencies are not found on the host system during configuration, meson will automatically download them via its wrap dependencies mentioned in bmcweb/subprojects.

Use of persistent data

bmcweb relies on some on-system data for storage of persistent data that is internal to the process. Details on the exact data stored and when it is read/written can seen from the persistent_data namespace.

TLS certificate generation

When SSL support is enabled and a usable certificate is not found, bmcweb will generate a self-signed a certificate before launching the server. Please see the bmcweb source code for details on the parameters this certificate is built with.

Redfish Aggregation

bmcweb is capable of aggregating resources from satellite BMCs. Refer to AGGREGATION.md for more information on how to enable and use this feature.