Add input IP parsing
This commit is contained in:
parent
67c2174ab3
commit
d4b8ad0b8c
12
block.py
12
block.py
@ -175,8 +175,10 @@ expressions = {
|
|||||||
"proxy_ip_longitude": ["Blob.proxy_ip_longitude"],
|
"proxy_ip_longitude": ["Blob.proxy_ip_longitude"],
|
||||||
"dns_ip_latitude": ["Blob.dns_ip_latitude"],
|
"dns_ip_latitude": ["Blob.dns_ip_latitude"],
|
||||||
"dns_ip_longitude": ["Blob.dns_ip_longitude"],
|
"dns_ip_longitude": ["Blob.dns_ip_longitude"],
|
||||||
|
"input_ip_address": ["Blob.input_ip_address"],
|
||||||
"input_ip_latitude": ["Blob.input_ip_latitude"],
|
"input_ip_latitude": ["Blob.input_ip_latitude"],
|
||||||
"input_ip_longitude": ["Blob.input_ip_longitude"],
|
"input_ip_longitude": ["Blob.input_ip_longitude"],
|
||||||
|
"input_ip_isp": ["Blob.input_ip_isp"],
|
||||||
# First-seen timestamps for age deltas
|
# First-seen timestamps for age deltas
|
||||||
"digital_id_first_seen": ["Blob.digital_id_first_seen"],
|
"digital_id_first_seen": ["Blob.digital_id_first_seen"],
|
||||||
"account_email_first_seen": ["Blob.account_email_first_seen"],
|
"account_email_first_seen": ["Blob.account_email_first_seen"],
|
||||||
@ -227,6 +229,7 @@ def __main__(
|
|||||||
DeviceId: str,
|
DeviceId: str,
|
||||||
FuzzyDeviceId: str,
|
FuzzyDeviceId: str,
|
||||||
ReasonCode: str,
|
ReasonCode: str,
|
||||||
|
input_ip_address: str = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
# Convert input parameters into a flat dictionary
|
# Convert input parameters into a flat dictionary
|
||||||
data = {
|
data = {
|
||||||
@ -255,6 +258,7 @@ def __main__(
|
|||||||
"DeviceId": DeviceId,
|
"DeviceId": DeviceId,
|
||||||
"FuzzyDeviceId": FuzzyDeviceId,
|
"FuzzyDeviceId": FuzzyDeviceId,
|
||||||
"ReasonCode": ReasonCode,
|
"ReasonCode": ReasonCode,
|
||||||
|
"input_ip_address": input_ip_address,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Convert dictionary to a single-row DataFrame
|
# Convert dictionary to a single-row DataFrame
|
||||||
@ -283,7 +287,11 @@ def __main__(
|
|||||||
return coalesce(*values)
|
return coalesce(*values)
|
||||||
|
|
||||||
extracted = combined_df["blob"].apply(_extract_with_fallback)
|
extracted = combined_df["blob"].apply(_extract_with_fallback)
|
||||||
if column in combined_df.columns:
|
if column == "input_ip_address" and column in combined_df.columns:
|
||||||
|
existing = combined_df[column]
|
||||||
|
has_existing = existing.notnull() & (existing.astype(str).str.strip() != "")
|
||||||
|
combined_df[column] = existing.where(has_existing, extracted)
|
||||||
|
elif column in combined_df.columns:
|
||||||
combined_df[column] = extracted.where(extracted.notnull(), combined_df[column])
|
combined_df[column] = extracted.where(extracted.notnull(), combined_df[column])
|
||||||
else:
|
else:
|
||||||
combined_df[column] = extracted
|
combined_df[column] = extracted
|
||||||
@ -292,6 +300,8 @@ def __main__(
|
|||||||
# logger.info(combined_df.iloc[0].drop("blob").to_dict())
|
# logger.info(combined_df.iloc[0].drop("blob").to_dict())
|
||||||
else:
|
else:
|
||||||
for column in expressions:
|
for column in expressions:
|
||||||
|
if column == "input_ip_address" and column in combined_df.columns:
|
||||||
|
continue
|
||||||
combined_df[column] = None
|
combined_df[column] = None
|
||||||
# logger.info("pre_flowx data")
|
# logger.info("pre_flowx data")
|
||||||
# logger.info(combined_df.iloc[0].to_dict())
|
# logger.info(combined_df.iloc[0].to_dict())
|
||||||
|
|||||||
@ -29,6 +29,9 @@ THX_FIELDS = [
|
|||||||
"account_email_attributes",
|
"account_email_attributes",
|
||||||
"tps_ip_latitude",
|
"tps_ip_latitude",
|
||||||
"tps_ip_longitude",
|
"tps_ip_longitude",
|
||||||
|
"input_ip_address",
|
||||||
|
"input_ip_connection_type",
|
||||||
|
"input_ip_isp",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Hardcoded M2 data dictionary (replaces file lookup)
|
# Hardcoded M2 data dictionary (replaces file lookup)
|
||||||
|
|||||||
@ -101,6 +101,10 @@
|
|||||||
"ReasonCode": {
|
"ReasonCode": {
|
||||||
"type": ["string", "null"],
|
"type": ["string", "null"],
|
||||||
"description": "Reason code from ThreatMetrix."
|
"description": "Reason code from ThreatMetrix."
|
||||||
|
},
|
||||||
|
"input_ip_address": {
|
||||||
|
"type": ["string", "null"],
|
||||||
|
"description": "Input IP address from ThreatMetrix."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|||||||
@ -74,6 +74,18 @@
|
|||||||
"type": ["string", "null"],
|
"type": ["string", "null"],
|
||||||
"description": "TPS IP longitude"
|
"description": "TPS IP longitude"
|
||||||
},
|
},
|
||||||
|
"input_ip_address": {
|
||||||
|
"type": ["string", "null"],
|
||||||
|
"description": "Input IP address from ThreatMetrix"
|
||||||
|
},
|
||||||
|
"input_ip_connection_type": {
|
||||||
|
"type": ["string", "null"],
|
||||||
|
"description": "Input IP connection type from ThreatMetrix"
|
||||||
|
},
|
||||||
|
"input_ip_isp": {
|
||||||
|
"type": ["string", "null"],
|
||||||
|
"description": "Input IP ISP from ThreatMetrix"
|
||||||
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"type": ["string", "null"],
|
"type": ["string", "null"],
|
||||||
"description": "Recommended Action."
|
"description": "Recommended Action."
|
||||||
|
|||||||
@ -57,11 +57,18 @@ class TestBlock(unittest.TestCase):
|
|||||||
"hd_score_iso_m2"
|
"hd_score_iso_m2"
|
||||||
]:
|
]:
|
||||||
self.assertIn(key, result)
|
self.assertIn(key, result)
|
||||||
|
self.assertEqual(result["input_ip_address"], "2600:387:15:5211::a")
|
||||||
|
self.assertEqual(result["input_ip_connection_type"], "tx")
|
||||||
|
self.assertEqual(result["input_ip_isp"], "at&t enterprises llc")
|
||||||
# self.assertAlmostEqual(float(result["hd_score_m1"]), 1145.0, delta=1.0)
|
# self.assertAlmostEqual(float(result["hd_score_m1"]), 1145.0, delta=1.0)
|
||||||
# self.assertAlmostEqual(float(result["hd_score_m2"]), 1182.0, delta=1.0)
|
# self.assertAlmostEqual(float(result["hd_score_m2"]), 1182.0, delta=1.0)
|
||||||
# self.assertAlmostEqual(float(result["hd_score_iso_m2"]), 1061.0, delta=1.0)
|
# self.assertAlmostEqual(float(result["hd_score_iso_m2"]), 1061.0, delta=1.0)
|
||||||
# THX payload is flattened; no nested thx dict should remain
|
# THX payload is flattened; no nested thx dict should remain
|
||||||
|
|
||||||
|
def test_top_level_input_ip_address_wins_over_blob(self):
|
||||||
|
result = __main__(**{**input_json, "input_ip_address": "top-level-ip"})
|
||||||
|
self.assertEqual(result["input_ip_address"], "top-level-ip")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user