Rules (XIF)
[MODEL: dataset = akamai_waf_raw]
/*
Reference: https://techdocs.akamai.com/siem-integration/reference/get-configid
Swagger: https://github.com/akamai/akamai-apis/blob/main/apis/siem/v1/openapi.json
*/
alter // pre-modeling extractions
client_ip = attackData -> clientIP,
client_platform = httpMessage -> requestHeaders.sec_ch_ua_platform,
host = httpMessage -> host,
http_method = httpMessage -> method,
path = httpMessage -> path,
port = to_integer(httpMessage -> port),
query = httpMessage -> query,
response_code = httpMessage -> status,
rule_actions = if(to_string(attackData) ~= "ruleActions\":\s*\[", replex(arraystring(attackData -> ruleActions[], "|"),"\"",""), to_string(attackData -> ruleActions)),
rule_messages_risk = arraycreate(attackData -> ruleMessages),
rule_messages_desc = coalesce(to_string(arraystring(json_extract_scalar_array(attackData, "$.ruleMessages"), ";")), to_string(attackData -> ruleMessages)),
rules = if(to_string(attackData) ~= "rules\":\s*\[", arraystring(json_extract_scalar_array(attackData, "$.ruleMessages"), ";"), to_string(attackData -> rules)),
as_number = geo -> asn
| alter // initialize the url components
// set url scheme according to protocol which is an enum of either 80 or 443
scheme = if(port = 80, "http://", port = 443, "https://", ""),
// trim trailing / from url path
path = rtrim(coalesce(path, ""), "/"),
// add query separator if required
query = if(query != null and query != "", concat("?", query), "")
// construct url: <scheme>://<host><path>?<query>
| alter url = concat(scheme, host, path, query )
| alter // XDM Mappings
xdm.alert.description = if(rule_messages_desc != "", rule_messages_desc, to_string(rule_messages_risk)), // The message reported by each triggered rule.
xdm.alert.name = rules, // A series of identifiers for rules within the configuration that triggered for this request.
xdm.alert.risks = rule_messages_risk, // The message reported by each triggered rule.
xdm.event.id = httpMessage -> requestId, // A unique identifier for each request.
xdm.network.application_protocol = httpMessage -> protocol,
xdm.network.http.content_type = httpMessage -> responseHeaders.Content_Type,
xdm.network.http.domain = host, // The incoming client request's Host header.
xdm.network.http.method = if(http_method = "GET", XDM_CONST.HTTP_METHOD_GET, http_method = "POST", XDM_CONST.HTTP_METHOD_POST, http_method = "PUT", XDM_CONST.HTTP_METHOD_PUT, http_method = "OPTIONS", XDM_CONST.HTTP_METHOD_OPTIONS, http_method = "CONNECT", XDM_CONST.HTTP_METHOD_CONNECT, http_method = "ACL", XDM_CONST.HTTP_METHOD_ACL, http_method = "BASELINE_CONTROL", XDM_CONST.HTTP_METHOD_BASELINE_CONTROL, http_method = "BIND", XDM_CONST.HTTP_METHOD_BIND, http_method = "CHECKIN", XDM_CONST.HTTP_METHOD_CHECKIN, http_method = "CHECKOUT", XDM_CONST.HTTP_METHOD_CHECKOUT, http_method = "COPY", XDM_CONST.HTTP_METHOD_COPY, http_method = "DELETE", XDM_CONST.HTTP_METHOD_DELETE, http_method = "HEAD", XDM_CONST.HTTP_METHOD_HEAD, http_method = "LABEL", XDM_CONST.HTTP_METHOD_LABEL, http_method = "LINK", XDM_CONST.HTTP_METHOD_LINK, http_method = "LOCK", XDM_CONST.HTTP_METHOD_LOCK, http_method = "MERGE", XDM_CONST.HTTP_METHOD_MERGE, http_method = "MKACTIVITY", XDM_CONST.HTTP_METHOD_MKACTIVITY, http_method = "MKCALENDAR", XDM_CONST.HTTP_METHOD_MKCALENDAR, http_method = "MKCOL", XDM_CONST.HTTP_METHOD_MKCOL, http_method = "MKREDIRECTREF", XDM_CONST.HTTP_METHOD_MKREDIRECTREF, http_method = "MKWORKSPACE", XDM_CONST.HTTP_METHOD_MKWORKSPACE, http_method = "MOVE", XDM_CONST.HTTP_METHOD_MOVE, http_method = "ORDERPATCH", XDM_CONST.HTTP_METHOD_ORDERPATCH, http_method = "PATCH", XDM_CONST.HTTP_METHOD_PATCH, http_method = "PRI", XDM_CONST.HTTP_METHOD_PRI, http_method = "PROPFIND", XDM_CONST.HTTP_METHOD_PROPFIND, http_method = "PROPPATCH", XDM_CONST.HTTP_METHOD_PROPPATCH, http_method = "REBIND", XDM_CONST.HTTP_METHOD_REBIND, http_method = "REPORT", XDM_CONST.HTTP_METHOD_REPORT, http_method = "SEARCH", XDM_CONST.HTTP_METHOD_SEARCH, http_method = "TRACE", XDM_CONST.HTTP_METHOD_TRACE, http_method = "UNBIND", XDM_CONST.HTTP_METHOD_UNBIND, http_method = "UNCHECKOUT", XDM_CONST.HTTP_METHOD_UNCHECKOUT, http_method = "UNLINK", XDM_CONST.HTTP_METHOD_UNLINK, http_method = "UNLOCK", XDM_CONST.HTTP_METHOD_UNLOCK, http_method = "UPDATE", XDM_CONST.HTTP_METHOD_UPDATE, http_method = "UPDATEREDIRECTREF", XDM_CONST.HTTP_METHOD_UPDATEREDIRECTREF, http_method = "VERSION_CONTROL", XDM_CONST.HTTP_METHOD_VERSION_CONTROL, http_method),
xdm.network.http.referrer = httpMessage -> requestHeaders.Referer,
xdm.network.http.response_code = if(response_code = "200", XDM_CONST.HTTP_RSP_CODE_OK, response_code = "201", XDM_CONST.HTTP_RSP_CODE_CREATED, response_code = "302", XDM_CONST.HTTP_RSP_CODE_FOUND, response_code = "401", XDM_CONST.HTTP_RSP_CODE_UNAUTHORIZED, response_code = "403", XDM_CONST.HTTP_RSP_CODE_FORBIDDEN, response_code = "404", XDM_CONST.HTTP_RSP_CODE_NOT_FOUND, response_code = "500", XDM_CONST.HTTP_RSP_CODE_INTERNAL_SERVER_ERROR, response_code = "501", XDM_CONST.HTTP_RSP_CODE_NOT_IMPLEMENTED, response_code = "502", XDM_CONST.HTTP_RSP_CODE_BAD_GATEWAY, response_code = "503", XDM_CONST.HTTP_RSP_CODE_SERVICE_UNAVAILABLE, response_code = "504", XDM_CONST.HTTP_RSP_CODE_GATEWAY_TIMEOUT, response_code = "505", XDM_CONST.HTTP_RSP_CODE_HTTP_VERSION_NOT_SUPPORTED, response_code = "506", XDM_CONST.HTTP_RSP_CODE_VARIANT_ALSO_NEGOTIATES, response_code = "507", XDM_CONST.HTTP_RSP_CODE_INSUFFICIENT_STORAGE, response_code = "508", XDM_CONST.HTTP_RSP_CODE_LOOP_DETECTED, response_code = "511", XDM_CONST.HTTP_RSP_CODE_NETWORK_AUTHENTICATION_REQUIRED, response_code = "100", XDM_CONST.HTTP_RSP_CODE_CONTINUE, response_code = "101", XDM_CONST.HTTP_RSP_CODE_SWITCHING_PROTOCOLS, response_code = "102", XDM_CONST.HTTP_RSP_CODE_PROCESSING, response_code = "103", XDM_CONST.HTTP_RSP_CODE_EARLY_HINTS, response_code = "202", XDM_CONST.HTTP_RSP_CODE_ACCEPTED, response_code = "203", XDM_CONST.HTTP_RSP_CODE_NON__AUTHORITATIVE_INFORMATION, response_code = "204", XDM_CONST.HTTP_RSP_CODE_NO_CONTENT, response_code = "205", XDM_CONST.HTTP_RSP_CODE_RESET_CONTENT, response_code = "206", XDM_CONST.HTTP_RSP_CODE_PARTIAL_CONTENT, response_code = "207", XDM_CONST.HTTP_RSP_CODE_MULTI__STATUS, response_code = "208", XDM_CONST.HTTP_RSP_CODE_ALREADY_REPORTED, response_code = "226", XDM_CONST.HTTP_RSP_CODE_IM_USED, response_code = "300", XDM_CONST.HTTP_RSP_CODE_MULTIPLE_CHOICES, response_code = "301", XDM_CONST.HTTP_RSP_CODE_MOVED_PERMANENTLY, response_code = "303", XDM_CONST.HTTP_RSP_CODE_SEE_OTHER, response_code = "304", XDM_CONST.HTTP_RSP_CODE_NOT_MODIFIED, response_code = "305", XDM_CONST.HTTP_RSP_CODE_USE_PROXY, response_code = "307", XDM_CONST.HTTP_RSP_CODE_TEMPORARY_REDIRECT, response_code = "308", XDM_CONST.HTTP_RSP_CODE_PERMANENT_REDIRECT, response_code = "400", XDM_CONST.HTTP_RSP_CODE_BAD_REQUEST, response_code = "402", XDM_CONST.HTTP_RSP_CODE_PAYMENT_REQUIRED, response_code = "405", XDM_CONST.HTTP_RSP_CODE_METHOD_NOT_ALLOWED, response_code = "406", XDM_CONST.HTTP_RSP_CODE_NOT_ACCEPTABLE, response_code = "407", XDM_CONST.HTTP_RSP_CODE_PROXY_AUTHENTICATION_REQUIRED, response_code = "408", XDM_CONST.HTTP_RSP_CODE_REQUEST_TIMEOUT, response_code = "409", XDM_CONST.HTTP_RSP_CODE_CONFLICT, response_code = "410", XDM_CONST.HTTP_RSP_CODE_GONE, response_code = "411", XDM_CONST.HTTP_RSP_CODE_LENGTH_REQUIRED, response_code = "412", XDM_CONST.HTTP_RSP_CODE_PRECONDITION_FAILED, response_code = "413", XDM_CONST.HTTP_RSP_CODE_CONTENT_TOO_LARGE, response_code = "414", XDM_CONST.HTTP_RSP_CODE_URI_TOO_LONG, response_code = "415", XDM_CONST.HTTP_RSP_CODE_UNSUPPORTED_MEDIA_TYPE, response_code = "416", XDM_CONST.HTTP_RSP_CODE_RANGE_NOT_SATISFIABLE, response_code = "417", XDM_CONST.HTTP_RSP_CODE_EXPECTATION_FAILED, response_code = "421", XDM_CONST.HTTP_RSP_CODE_MISDIRECTED_REQUEST, response_code = "422", XDM_CONST.HTTP_RSP_CODE_UNPROCESSABLE_CONTENT, response_code = "423", XDM_CONST.HTTP_RSP_CODE_LOCKED, response_code = "424", XDM_CONST.HTTP_RSP_CODE_FAILED_DEPENDENCY, response_code = "425", XDM_CONST.HTTP_RSP_CODE_TOO_EARLY, response_code = "426", XDM_CONST.HTTP_RSP_CODE_UPGRADE_REQUIRED, response_code = "428", XDM_CONST.HTTP_RSP_CODE_PRECONDITION_REQUIRED, response_code = "429", XDM_CONST.HTTP_RSP_CODE_TOO_MANY_REQUESTS, response_code = "431", XDM_CONST.HTTP_RSP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE, response_code = "451", XDM_CONST.HTTP_RSP_CODE_UNAVAILABLE_FOR_LEGAL_REASONS, response_code),
xdm.network.http.url = url,
xdm.network.rule = attackData -> policyId, // Unique identifier for the firewall policy applied to this request.
xdm.network.tls.protocol_version = httpMessage -> tls,
xdm.observer.action = rule_actions, // Identifies whether the request was aborted (deny) or allowed to pass with a warning logged (alert).
xdm.observer.name = type, // Characterizes the source of this report data. Value is always "akamai_siem".
xdm.source.application.name = clientData -> appBundleId,
xdm.source.application.version = clientData -> appVersion,
xdm.source.asn.as_number = if(as_number ~= "\D|^\s*$", null, to_integer(as_number)), // The AS number or numbers that the IP belongs to.
xdm.source.host.os_family = if(client_platform contains "WINDOWS", XDM_CONST.OS_FAMILY_WINDOWS, client_platform contains "MAC", XDM_CONST.OS_FAMILY_MACOS, client_platform contains "LINUX", XDM_CONST.OS_FAMILY_LINUX, client_platform contains "ANDROID", XDM_CONST.OS_FAMILY_ANDROID, client_platform contains "IOS", XDM_CONST.OS_FAMILY_IOS, client_platform contains "UBUNTU", XDM_CONST.OS_FAMILY_UBUNTU, client_platform contains "DEBIAN", XDM_CONST.OS_FAMILY_DEBIAN, client_platform contains "FEDORA", XDM_CONST.OS_FAMILY_FEDORA, client_platform contains "CENTOS", XDM_CONST.OS_FAMILY_CENTOS, client_platform contains "CHROME", XDM_CONST.OS_FAMILY_CHROMEOS, client_platform contains "SOLARIS", XDM_CONST.OS_FAMILY_SOLARIS, client_platform contains "SCADA", XDM_CONST.OS_FAMILY_SCADA, client_platform),
xdm.source.ipv4 = if(client_ip ~= "(?:\d{1,3}\.){3}\d{1,3}", client_ip), // // The IPv4 address of the client making the request.
xdm.source.ipv6 = if(client_ip ~= ":", client_ip), // // The IPv6 address of the client making the request.
xdm.source.location.city = geo -> city,
xdm.source.location.continent = geo -> continent,
xdm.source.location.region = geo -> regionCode,
xdm.source.user_agent = httpMessage -> requestHeaders.User_Agent,
xdm.source.user.identifier = userRiskData -> uuid, // Unique identifier for the user whose user risk data is provided here. Available only to Identity Protector customers and only on endpoints configured for identity protection.
xdm.source.user.username = userRiskData -> username, // The unencrypted username, provided at login by the user. Available only to Identity Protector customers and only on endpoints configured for identity protection.
xdm.target.port = port,
xdm.target.resource.id = attackData -> apiId, // For attacks on API services, this is a unique identifier under which the API is protected. It corresponds to the apiEndPointId value in the API Endpoint Definition API.
xdm.target.sent_bytes = to_integer(httpMessage -> bytes), // The number of bytes served in the response.
xdm.target.url = url;