The app works by leveraging the Meraki Dashboard API and Webhooks.

Dashboard API for CMDB Sync

A scheduled job is run to import Meraki data via the API. Once imported, the data is then mapped to the related CMDB tables.

Scheduled Job

SG-Meraki Devices

Runs according to the user defined schedule

Data Source

The job uses a script to obtain the Meraki data.

Use this Postman Collection to easily test the following API endpoints.

Authentication

The app will use the provided read-only Meraki API key to pull all related records associated with it.

API Docs

Organizations

GET /organizations

API Docs

API Response Data

[
    {
        "id": "2930418",
        "name": "Customer 1",
        "url": "https://dashboard.meraki.com/o/sdfAd/manage/organization/overview"
    },
     {
        "id": "8768683",
        "name": "Customer 2",
        "url": "https://dashboard.meraki.com/o/VjjsAd/manage/organization/overview"
    }
]

Networks

GET /organizations/{organizationId}/networks

API Docs

API Response Data

[
    {
        "id": "L_123456",
        "organizationId": "2930418",
        "name": "Long Island Office",
        "timeZone": "America/Los_Angeles",
        "tags": [ "tag1", "tag2" ],
        "productTypes": [
            "appliance",
            "switch",
            "wireless"
        ],
        "enrollmentString": "long-island-office"
    }
]

Devices

GET /organizations/{organizationId}/devices

API Docs

API Response Data

[
    {
        "name": "My AP",
        "lat": 37.4180951010362,
        "lng": -122.098531723022,
        "address": "1600 Pennsylvania Ave",
        "notes": "My AP's note",
        "tags": " recently-added ",
        "networkId": "N_24329156",
        "serial": "Q234-ABCD-5678",
        "model": "MR34",
        "mac": "00:11:22:33:44:55",
        "lanIp": "1.2.3.4",
        "firmware": "wireless-25-14"
    }
]

Device Statuses

GET /organizations/{organizationId}/devices/availabilities

API Docs

API Response Data

[
    {
        "mac": "00:11:22:33:44:55",
        "name": "My AP",
        "network": { "id": "N_24329156" },
        "productType": "switch",
        "serial": "Q234-ABCD-5678",
        "status": "online",
        "tags": [ "tag1", "tag2" ]
    }
]

Default Device family to CI Class Mapping List

CI classes are the database tables for ServiceNow (for example, cmdb_ci_wap_network, cmdb_ci_ip_router, and cmdb_ci_ip_switch) This table displays the Cisco Meraki default CI classes for each device family. The default CI classes can be modified by the user (Please refer to the troubleshooting guide for instructions on how to edit the mappings). In case of other device families not listed below, the ServiceNow application user needs to either manually create the corresponding CI Classes and attributes/references mapping or use a pre-existing CI class a 'parent' CI class.

Device Family Corresponding CI Class
Wireless Access Points (MR, CW) cmdb_ci_wap_network
MG, MX, Z3, Z4, C8 cmdb_ci_netgear
MS, C9 cmdb_ci_ip_switch
MV cmdb_ci_ip_camera
MT cmdb_ci_ot_industrial_sensor
Default class if no existing Model to CI Class mapping exist cmdb_ci_hardware

Webhooks Alerts for Incident Creation

A scripted service will provide a REST endpoint exposing a URL based upon your instance and configured user account.

Priority of incidents can be defined by adding/modifying records in the Device Alerts lookup table found in the System Policy application menu.

Webhook Docs

API Resource

API ID: sgmeraki_device_alerts

Path: /api/x_caci_sg_meraki/sgmeraki_device_alerts

Method: POST

API Script Details

SGMerakiSNAlerts
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    // Parse Meraki Alerts Webhook Data
    var requestBody = request.body.dataString;
    var requestParsed = {};
    gs.info('SNAlerts-' + requestBody);
    requestParsed = JSON.parse(requestBody);
    var merakiAlert = requestParsed;

    var grp = gs.getProperty('x_caci_sg_meraki.meraki_alert_group');
    var ciId = '';

    var ci = new GlideRecord('cmdb_ci');
    ci.addQuery('serial_number', requestParsed.deviceSerial);
    ci.query();
    if (ci.next()) {
        ciId = ci.getUniqueValue();
    }
    var inc = new GlideRecord('incident');
    inc.newRecord();
    inc.contact_type = 'monitoring';
    inc.category = 'Alert';
    if (grp != '')
        inc.assignment_group = grp;
    inc.short_description = requestParsed.alertType;
    inc.x_caci_sg_meraki_device_alert = requestParsed.alertType;
    inc.description = 'Alert ' + requestParsed.alertType + ' received for device: ' + requestParsed.deviceName + ' SN: ' + requestParsed.deviceSerial + '\n';
    var level = 0;
    var myString = '';
    
    for (var name in requestParsed) {
        if (typeof requestParsed[name] == 'object') {
            myString += "\n" + " ".repeat(level * 4) + name + ": ";
            var stuff = new SGConnectorMerakiUtils().parseLevel1(requestParsed[name], 1);
            myString += stuff;
        } else {
            myString += "\n" + " ".repeat(level * 4) + name + ": " + requestParsed[name];
        }
    }

    inc.description += myString;

    if (ciId != '')
        inc.cmdb_ci = ciId;
    inc.insert();

})(request, response);