File size: 7,320 Bytes
7c89ed7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2017 Mozilla Corporation
import json
from mozdef_util.utilities.key_exists import key_exists
class message(object):
def __init__(self):
'''
Plugin used to fix object type discretions with cloudtrail messages
'''
self.registration = ['cloudtrail']
self.priority = 10
# Just add new entry to this dict to
# automatically convert key mappings
# which are mixed string and dict
# into a dict with a raw_value key as the string value
self.modify_keys = [
'details.additionaleventdata',
'details.apiversion',
'details.serviceeventdetails',
'details.requestparameters.attribute',
'details.requestparameters.authparameters',
'details.requestparameters.bucketpolicy.statement.principal.service',
'details.requestparameters.bucketpolicy.statement.principal.aws',
'details.requestparameters.callerreference',
'details.requestparameters.description',
'details.requestparameters.describecapacityreservationsrequest',
'details.requestparameters.describecoippoolsrequest',
'details.requestparameters.describeegressonlyinternetgatewaysrequest',
'details.requestparameters.describefastsnapshotrestoresrequest',
'details.requestparameters.describeflowlogsrequest',
'details.requestparameters.describeflowlogsrequest.filter.value',
'details.requestparameters.describehostsrequest',
'details.requestparameters.describeinstancetypeofferingsrequest',
'details.requestparameters.describeinstancetypesrequest',
'details.requestparameters.describeipv6poolsrequest',
'details.requestparameters.describelaunchtemplatesrequest',
'details.requestparameters.describenatgatewaysrequest',
'details.requestparameters.describepublicipv4poolsrequest',
'details.requestparameters.describescheduledinstancesrequest',
'details.requestparameters.describespotfleetrequestsrequest',
'details.requestparameters.describevpcendpointconnectionnotificationsrequest',
'details.requestparameters.describevpcendpointsrequest',
'details.requestparameters.describevpcendpointsrequest.filter',
'details.requestparameters.describevpcendpointsrequest.filter.value',
'details.requestparameters.describevpcendpointsrequest.vpcendpointid',
'details.requestparameters.describevpcendpointserviceconfigurationsrequest',
'details.requestparameters.describevpcendpointservicesrequest',
'details.requestparameters.disableapitermination',
'details.requestparameters.distributionconfig.callerreference',
'details.requestparameters.domainname',
'details.requestparameters.domainnames',
'details.requestparameters.ebsoptimized',
'details.requestparameters.filter',
'details.requestparameters.groupdescription',
'details.requestparameters.iaminstanceprofile',
'details.requestparameters.invalidationbatch.callerreference',
'details.requestparameters.imageid',
'details.requestparameters.instancetype',
'details.requestparameters.logging',
'details.requestparameters.logstreamname',
'details.requestparameters.metrics',
'details.requestparameters.notification',
'details.requestparameters.notificationconfiguration',
'details.requestparameters.rule',
'details.requestparameters.schema',
'details.requestparameters.sort',
'details.requestparameters.source',
'details.requestparameters.tagging',
'details.requestparameters.vpc',
'details.responseelements.availabilityzones',
'details.responseelements.createddate',
'details.responseelements.creationdate',
'details.responseelements.creationtime',
'details.responseelements.credentials',
'details.responseelements.dbsubnetgroup',
'details.responseelements.distribution.distributionconfig.callerreference',
'details.responseelements.endpoint',
'details.responseelements.findings.service.additionalinfo.unusual',
'details.responseelements.invalidation.invalidationbatch.callerreference',
'details.responseelements.lastmodified',
'details.responseelements.lastmodifieddate',
'details.responseelements.policy',
'details.responseelements.responseparameters.method.response.header.access-control-allow-headers',
'details.responseelements.responseparameters.method.response.header.access-control-allow-methods',
'details.responseelements.responseparameters.method.response.header.access-control-allow-origin',
'details.responseelements.role',
'details.responseelements.securitygroups',
'details.responseelements.state',
'details.responseelements.subnets',
]
def convert_key_raw_str(self, needle, haystack):
num_levels = needle.split(".")
if len(num_levels) == 0:
return False
current_pointer = haystack
for updated_key in num_levels:
if updated_key == num_levels[-1]:
current_pointer[updated_key] = {
'raw_value': json.dumps(current_pointer[updated_key])
}
return haystack
if updated_key in current_pointer:
current_pointer = current_pointer[updated_key]
else:
return haystack
def onMessage(self, message, metadata):
'''
Check if source is in the message, if not then add cloudtrail as the source.
'''
if 'source' not in message:
return (message, metadata)
if not message['source'] == 'cloudtrail':
return (message, metadata)
'''
Check if details.requestparameters.htmlpart exists, if it does it's generally longer than 32000 bytes,
so we'll truncate it to 4096 characters using the constant ES_FIELD_VALUE_LIMIT so that ES will ingest it,
leaving us with knowledge of what the field contains without the overkill of storing the entire page.
'''
ES_FIELD_VALUE_LIMIT = 4095
if 'requestparameters' in message['details'] and message['details']['requestparameters']:
if 'htmlpart' in message['details']['requestparameters'] and message['details']['requestparameters']['htmlpart']:
message['details']['requestparameters']['htmlpart'] = message['details']['requestparameters']['htmlpart'][0:ES_FIELD_VALUE_LIMIT]
for modified_key in self.modify_keys:
if key_exists(modified_key, message):
message = self.convert_key_raw_str(modified_key, message)
return (message, metadata)
|