def get_alert_profile(service_name, service_config): alert_profile = safe_get(service_config, 'alertProfile', str) if not alert_profile: raise BackendError( f'Lacework backend could not determine alert profile for service {service_name}') return alert_profile
def get_query_returns(service_name, service_config): returns = safe_get(service_config, 'returns', list) if not returns: raise BackendError( f'Lacework backend could not determine returns for service {service_name}') return returns
def get_query_source(service_name, service_config): # 4. validate service has a source mapping source = safe_get(service_config, 'source', str) if not source: raise BackendError( f'Lacework backend could not determine source for service {service_name}') return source
def get_evaluator_id(service_name, service_config): # 3. validate service has an evaluatorId mapping evaluator_id = safe_get(service_config, 'evaluatorId', str) if not evaluator_id: raise BackendError( f'Lacework backend could not determine evaluatorId for service {service_name}') return evaluator_id
def generateMapItemNode(self, node): """ Map Expression for Lacework Query Language (LQL) Special handling for contains by inspecting value for wildcards """ fieldname, value = node if self._should_ignore_field(fieldname): return None transformed_fieldname = self.fieldNameMapping(fieldname, value) # is not null if value == '*': if ':' in transformed_fieldname: return f'value_exists({transformed_fieldname})' return f'{transformed_fieldname} is not null' # contains if (isinstance(value, str) and value.startswith('*') and value.endswith('*')): value = self.generateValueNode(value[1:-1]) return f"contains({transformed_fieldname}, {value})" # startswith if (isinstance(value, str) and value.endswith( '*') # a wildcard at the end signifies startswith ): value = self.generateValueNode(value[:-1]) return f"starts_with({transformed_fieldname}, {value})" # endswith if (isinstance(value, str) and value.startswith( '*') # a wildcard at the start signifies endswith ): value = f'%{value[1:]}' new_value = self.generateValueNode(value) if new_value != (self.valueExpression % value): raise BackendError( 'Lacework backend only supports endswith for literal string values' ) return f"{transformed_fieldname} LIKE {new_value}" if isinstance(value, (str, int)): return self.mapExpression % (transformed_fieldname, self.generateNode(value)) # mapListsHandling elif type(value) == list: # if a list contains values with wildcards we can't use standard handling ("in") if any([x for x in value if x.startswith('*') or x.endswith('*')]): node = NodeSubexpression( ConditionOR(None, None, *[(transformed_fieldname, x) for x in value])) return self.generateNode(node) return self.generateMapItemListNode(transformed_fieldname, value) elif value is None: return self.nullExpression % (transformed_fieldname, ) else: raise TypeError( f'Lacework backend does not support map values of type {type(value)}' )
def get_service_config(config, service): config = safe_get(config, 'services', dict) service_config = safe_get(config, service, dict) # 1. validate logsource service if not service_config: raise BackendError( f'Service {service} is not supported by the Lacework backend') return service_config
def get_logsource_config(config, logsource_type, logsource_name): config = safe_get(config, logsource_type, dict) logsource_config = safe_get(config, logsource_name, dict) # 1. validate logsource service if not logsource_config: raise BackendError( f'Log source {logsource_name} is not supported by the Lacework backend' ) return logsource_config
def generateMapItemNode(self, node): """ Map Expression for Lacework Query Language (LQL) Special handling for contains by inspecting value for wildcards """ fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) # is not null if value == '*': return f'{transformed_fieldname} is not null' # contains if ( isinstance(value, str) and value.startswith('*') and value.endswith('*') ): value = self.generateValueNode(value[1:-1]) return f"contains({transformed_fieldname}, {value})" # startswith if ( isinstance(value, str) and value.endswith('*') # a wildcard at the end signifies startswith ): value = self.generateValueNode(value[:-1]) return f"starts_with({transformed_fieldname}, {value})" # endswith if ( isinstance(value, str) and value.startswith('*') # a wildcard at the start signifies endswith ): new_value = self.generateValueNode(value[1:]) if new_value != (self.valueExpression % value[1:]): raise BackendError( 'Lacework backend only supports endswith for literal string values') return f"{transformed_fieldname} <> {new_value}" if ( self.mapListsSpecialHandling is False and isinstance(value, (str, int, list)) or self.mapListsSpecialHandling is True and isinstance(value, (str, int)) ): return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif type(value) == list: return self.generateMapItemListNode(transformed_fieldname, value) elif value is None: return self.nullExpression % (transformed_fieldname, ) else: raise TypeError( f'Lacework backend does not support map values of type {type(value)}')
def _check_unsupported_field(action, fieldname): if action == 'raise': raise BackendError( f'Lacework backend does not support the {fieldname} field')