McAfeeDAM

McAfee Database Activity Monitoring.

Database · McAfee DAM

Details

IDMcAfeeDAM
ProviderSTG
CategoryDatabase
From Version5.0.0
Supported ModulesAgentix XSIAM

README

Use McAfee Database Activity Monitoring (DAM) Integration to fetch Alerts (incidents) and query Alerts.

This integration was integrated and developed with version 4.6.x of McAfee DAM.

Configure McAfeeDAM in Cortex

Make sure that the XML API interface is enabled on your McAfee DAM server (Settings > Interfaces > XML API), and that the configured user has read permissions to query DAM Alerts and Sensors (XML API).

Important: The user configured in McAfee DAM must have the Use XML API permission as documented here.

Instructions on how to configure and test the XML API for McAfee DAM are available here.

Parameter Description Required
url URL True
credentials Credentials True
batchSize Batch size for incident fetch False
isFetch Fetch incidents False
incidentType Incident type False
secure Validate ceritifacte False
ruleName Rule Name, If fetch incident is checked, this field is mandatory and will be used to get DAM alerts only triggered by this rule False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

Get information for a single alert


Gets a DAM alert from McAfee Database Activity Monitoring by alert ID.

Required Permissions
  • Alerts Read
Base Command

dam-get-alert-by-id

Input
Argument Name Description Required
id The alert ID. Required
Context Output
Path Type Description
AlertId unknown DAM alert ID.
alertAccessedObjects unknown DAM accessed objects.
dbUser unknown DAM Database User.
Account.Username unknown DAM OS user.
database unknown DAM database.
sensor unknown DAM sensor.
rules unknown DAM rules.

Get the latest DAM alerts


Gets the latest DAM alerts by rule name.

Required Permissions
  • Alerts Read
Base Command

dam-get-latest-by-rule

Input
Argument Name Description Required
ruleName Name of the rule that triggered the alert. Required
count Number of alerts to retrieve. The default is 10. Optional
timeBack Filter DAM alerts and import alerts that were created only in the last X minutes. The default is the last 10 minutes. Optional
Context Output
Path Type Description
AlertId unknown DAM alert ID.
alertAccessedObjects unknown DAM accessed objects.
dbUser unknown DAM database user.
Account.Username unknown DAM OS user.
database unknown DAM database.
sensor unknown DAM sensor.
rules unknown DAM rules.

Configuration parameters

  • url — URL (required)
  • credentials — Credentials (required)
  • batchSize — Batch size for incident fetch
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • secure — Validate ceritifacte
  • ruleName — Rule Name, If fetch incident is checked, this field is mandatory and will be used to get DAM alerts only triggered by this rule

Commands (2)

  • dam-get-alert-by-id

    Gets a DAM alert from McAfee Database Activity Monitoring by alert ID.

  • dam-get-latest-by-rule

    Gets the latest DAM alerts by rule name.

var mdAlertFields={
  'Execution Time':'executionTime',
  'Rule':'rules.rule.name',
  'User':'execUser',
  'Database':'database.name',
  'Sensor':'identifyingSensor.name',
  'Command Type':'cmdType'
};

var fixUrl = function(base) {
    res = base;
    if (base && base[base.length - 1] != '/') {
        res = res + '/';
    }
    return res;
};

var sendRequest = function(url, service, param) {

    // handle '/' at the end of the url
    if (url[url.length - 1] === '/') {
        url = url.substring(0, url.length - 1);
    }

    // prepare the request url (make sure to encode the query parameter value)
    var requestUrl = url + 'service=' + service;
    if  (param) {
        requestUrl += '&' +  param;
    }
    var res = http(
        requestUrl,
        {
            Method: 'GET', // Can be POST, PUT, DELETE, HEAD, OPTIONS or CONNECT
            Headers: {
                Accept: ['application/json']
            },
            Username:  params.credentials.identifier,
            Password:  params.credentials.password,

        },
        !params.insecure
    );

    if (res.StatusCode < 200 || res.StatusCode >= 300) {
        throw 'Request Failed.\nStatus code: ' + res.StatusCode + '.\nBody: ' + JSON.stringify(res) + '.';
    }

    return JSON.parse(x2j(res.Body));
};

var finalUrl = fixUrl(params.url) + 'xmlapi.svc?';

var calculateNewLastRun = function(alerts) {
    var res = '';
    var lastAlert = null;
    if (alerts && alerts.length && alerts.length > 0) {
        // transalte yyyy-MM-dd HH:mm:ss.S +Z => yyyy-MM-ddTHH:mm:ss.S+Z => time in millis
        lastAlert = alerts[alerts.length -1];
    } else if (alerts){
        //This is a single element
        lastAlert = alerts;
    }
    if (lastAlert) {
        var createDate = lastAlert.createDate;
        var dateTime = createDate.split(' ');
        var goTime = dateTime[0]+'T'+dateTime[1]+dateTime[2];
        //hack needed, becuase platform problems
        res = new Date(Date.parse(goTime)).getTime() + 1;
    }
    return res;
};

var alertToIncident = function(alert) {
    labels = [];
    var keys = Object.keys(alert);
    for (j = 0 ; j < keys.length; j++) {
        if (keys[j] === 'accessedObjects') {
            if (alert.accessedObjects.object && alert.accessedObjects.object.length > 0) {
                for (k = 0; k < alert.accessedObjects.object.length; k++) {
                    labels.push({type: 'accessedObject', value: alert.accessedObjects.object[k].owner + '.' + alert.accessedObjects.object[k].name + '('+ alert.accessedObjects.object[k].type +')'});
                }
            }
        } else if (keys[j] === 'database') {
            labels.push({type: 'database-host', value: alert.database.host});
            labels.push({type: 'database-ip', value: alert.database.ip});
            labels.push({type: 'database-id', value: alert.database.id});
            labels.push({type: 'database-name', value: alert.database.name});
        } else if (keys[j] === 'identifyingSensor') {
            labels.push({type: 'sensor-host', value: alert.identifyingSensor.host});
            labels.push({type: 'sensor-ip', value: alert.identifyingSensor.ip});
            labels.push({type: 'sensor-id', value: alert.identifyingSensor.id});
            labels.push({type: 'sensor-name', value: alert.identifyingSensor.name});
            labels.push({type: 'sensor-version', value: alert.identifyingSensor.version});
        } else if (keys[j] === 'rules') {
            if (alert.rules.length > 0) {
                for (k = 0; k < alert.rules.length; k++) {
                    labels.push({type: 'rule', value: alert.rules[i].name + '('+ alert.rules[i].sysid +')'});
                }
            } else if (alert.rules) {
                labels.push({type: 'rule', value: alert.rules.name + '('+ alert.rules.sysid +')'});
            }
        } else {
            labels.push({type: keys[j], value: alert[keys[j]]});
        }
    }
    return {
      name: 'DAM Event - ' + alert.id,
      labels: labels,
      details: alert.operation,
      rawJSON: JSON.stringify(alert)
    };
};
var alertsToIncident = function(alerts) {
    var incidents = [];
    for (i = 0; i < alerts.length; i++){
        incidents.push(alertToIncident(alerts[i]));
    }
    return incidents;
};
function alertsToMd(alerts) {
    var md="";
    if (Array.isArray(alerts)) {
        for (var i in alerts) {
            md += alertToMd(alerts[i]) + "\n --- \n";
        }
    } else {
        md += alertToMd(alerts);
    }
    return md;
}
function mdTableHead() {
    var head='|';
    var line='|';
    for (var key in mdAlertFields) {
        head+=key + '|';
        line+= '- |';
    }
    return head+'\n'+line+'\n';
}
function mdTableData(alert) {
    var data='|';
    for (var key in mdAlertFields) {
        data+=resolve(alert,mdAlertFields[key]) + '|';
    }
    return data + '\n';
}
function alertToMd(alert) {
    var md ='';
    md +="### DAM Alert ID " + alert.id + "\n";
    md += mdTableHead();
    md += mdTableData(alert);
    if (alert.operation) {
        md += '#### Statement\n';
        md += '```\n' + alert.operation + '\n```';
    }
    if (alert.accessedObjects && alert.accessedObjects.object) {
        var objects = Array.isArray(alert.accessedObjects.object) ? alert.accessedObjects.object : new Array(alert.accessedObjects.object);
        md += '\n#### Accessed Objects \n';
        md += 'Type|Owner|Name\n-|-|-\n';
        for (var i in objects) {
            md += objects[i].type + '|' + objects[i].owner + '|' + objects[i].name + "\n";
        }
    }

    return md;
}

function resolve(obj,path) {
    if (Array.isArray(obj)) {
        var ret = [];
        for (var i in obj) {
            ret.push(resolve(obj[i],path));
        }
        return ret;
    } else {
        var dot=path.indexOf(".");
        if (dot == -1) {
            return obj[path] ? obj[path] : 'N/A';
        } else {
            var curr = path.substring(0,dot);
            var rest = path.substring(dot+1);
            return obj[curr] ? resolve(obj[curr],rest) : 'N/A';
        }
    }
}

var fetchIncidents = function() {
    var count = params.batchSize || 100;
    //Default time back for first fetch is 10 minutes
    var timeBack = 1000 * 60 * 10;
    var urlParams = 'HH$TimeBackPeriod=' + encodeURIComponent(timeBack +'');
    var lastRun = getLastRun();
    if (lastRun && Object.keys(lastRun).length > 0) {
        urlParams = 'HH$CreateDateFrom=' + encodeURIComponent(lastRun.createDate);
    }
    if (params.ruleName) {
        urlParams +='&HH$RuleName=' + encodeURIComponent(params.ruleName);
    }
    urlParams += '&HH$pageSize='+encodeURIComponent(count);
    var res = sendRequest(finalUrl, 'alert',  urlParams).HedgehogXmlApi;
    var incidents = null;
    var newLastRun = null;
    if (res && res.alert && res.alert.length > 0) {
        //Create incidents
        incidents = alertsToIncident(res.alert);
        //Set last run
        newLastRun = calculateNewLastRun(res.alert);
    } else if (res && res.alert) {
        //This is a sinlge alert
        //Create incidents
        incidents = [alertToIncident(res.alert)];
        //Set last run
        newLastRun = calculateNewLastRun(res.alert);
    }
    if (newLastRun) {
        setLastRun({createDate: newLastRun});
    }
    return incidents;
};

// The command input arg holds the command sent from the user.
switch (command) {
    // This is the call made when pressing the integration test button.
    case 'test-module':
        sendRequest(finalUrl, 'sensor');
        return 'ok';
    case 'fetch-incidents':
        return JSON.stringify(fetchIncidents());
    case 'dam-get-alert-by-id':
        var jsonRes=sendRequest(finalUrl, 'alert', 'HH$Id=' + encodeURIComponent(args.id)).HedgehogXmlApi.alert;
        if (jsonRes) {
            var entryContext = {
            };
            md = alertToMd(jsonRes);
            return {Type: entryTypes.note, Contents: jsonRes, ContentsFormat: formats.json, HumanReadable: md};
        } else {
            md = '### no alerts found\n';
            return {Type: entryTypes.note, Contents: null, ContentsFormat: formats.json, HumanReadable: md};
        }
    case 'dam-get-latest-by-rule':
        var count = args.count || 10;
        var timeBack = 1000 * 60 * (args.timeBack || 10);
        var res = sendRequest(finalUrl, 'alert', 'HH$RuleName=' + encodeURIComponent(args.ruleName) +
            '&HH$TimeBackPeriod='+encodeURIComponent(timeBack +'') + '&HH$pageSize='+encodeURIComponent(count)).HedgehogXmlApi;

        if (res && res.alert) {
            jsonRes = res.alert;
            var entryContext = {};
            md = alertsToMd(jsonRes);
            return {Type: entryTypes.note, Contents: jsonRes, ContentsFormat: formats.json, HumanReadable: md};
        } else {
            md = '### no alerts found\n';
            return {Type: entryTypes.note, Contents: null, ContentsFormat: formats.json, HumanReadable: md};
        }
}