Skip to content

Commit

Permalink
Improve CI output for legacy attack chain check (#27587)
Browse files Browse the repository at this point in the history
  • Loading branch information
warriorstar-orion authored Dec 24, 2024
1 parent 6825da4 commit cc9b5fb
Showing 1 changed file with 39 additions and 19 deletions.
58 changes: 39 additions & 19 deletions tools/ci/check_legacy_attack_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ def format_error(self):
return f"{self.source_info.file_path}:{self.source_info.line}: {RED}{self.make_error_message()}{NC}"


def make_error_from_procdecl(proc_decl: ProcDecl, msg) -> str:
if os.getenv("GITHUB_ACTIONS") == "true":
return f"::error file={proc_decl.source_info.file_path},line={proc_decl.source_info.line},title=Attack Chain::{proc_decl.source_info.file_path}:{proc_decl.source_info.line}: {RED}{msg}{NC}"

else:
return f"{proc_decl.source_info.file_path}:{proc_decl.source_info.line}: {RED}{msg}{NC}"


# Walker for determining if a proc contains any calls to a legacy attack chain
# proc on an object that is in the type tree of our migrating type.
#
Expand Down Expand Up @@ -149,11 +157,10 @@ def visit_Expr(self, node, source_info):
start = time.time()

CALLS = defaultdict(set)
ERROR_STRINGS = list()
LEGACY_PROCS = defaultdict(list)
MODERN_PROCS = defaultdict(list)
SETTING_CACHE = dict()
LEGACY_PROCS = dict()
MODERN_PROCS = dict()
BAD_TREES = dict()
PROCS = dict()

dme = DME.from_file("paradise.dme", parse_procs=True)

Expand All @@ -171,44 +178,57 @@ def visit_Expr(self, node, source_info):
)
except:
SETTING_CACHE[pth] = False
LEGACY_PROCS[pth] = {
x for x in td.proc_names(modified=True) if "__legacy__attackchain" in x
}
MODERN_PROCS[pth] = {x for x in td.proc_names(modified=True) if x in NEW_PROCS}
for proc_name in td.proc_names(modified=True):
if "__legacy__attackchain" in proc_name:
for proc_decl in td.proc_decls(proc_name):
LEGACY_PROCS[pth].append(proc_decl)
elif proc_name in NEW_PROCS:
for proc_decl in td.proc_decls(proc_name):
MODERN_PROCS[pth].append(proc_decl)
for proc_decl in td.proc_decls():
walker = AttackChainCallWalker(td, proc_decl)
proc_decl.walk(walker)

for pth, new_attack_chain in SETTING_CACHE.items():
for pth in sorted(SETTING_CACHE.keys()):
new_attack_chain = SETTING_CACHE[pth]
cursor = pth
if new_attack_chain:
if LEGACY_PROCS[pth]:
exit_code = 1
print(f"new_attack_chain on {pth} still has legacy procs:")
for proc in sorted(LEGACY_PROCS[pth]):
print(f"\t{proc}")
for proc_decl in sorted(LEGACY_PROCS[pth], key=lambda x: x.name):
ERROR_STRINGS.append(
make_error_from_procdecl(
proc_decl,
f"migrated type with legacy proc {pth}/{proc_decl.name}(...)",
)
)
while cursor not in ASSISTED_TYPES and not cursor.is_root:
if LEGACY_PROCS[cursor] and not SETTING_CACHE[cursor]:
exit_code = 1
print(f"new_attack_chain on {pth} but related type {cursor} is not")
cursor = cursor.parent
if pth in CALLS and any([x.legacy for x in CALLS[pth]]):
print("Legacy sites requiring migration:")
for call in CALLS[pth]:
if call.legacy:
print(call.format_error())
ERROR_STRINGS.append(call.format_error())
elif pth not in ASSISTED_TYPES:
if MODERN_PROCS[pth]:
exit_code = 1
print(f"new_attack_chain not on {pth} using new procs:")
for proc in sorted(MODERN_PROCS[pth]):
print(f"\t{proc}")
for proc_decl in sorted(MODERN_PROCS[pth], key=lambda x: x.name):
ERROR_STRINGS.append(
make_error_from_procdecl(
proc_decl,
f"legacy type with migrated proc {pth}/{proc_decl.name}(...)",
)
)
if pth in CALLS and any([not x.legacy for x in CALLS[pth]]):
exit_code = 1
print("Unexpected new call sites:")
for call in CALLS[pth]:
if not call.legacy:
print(call.format_error())
ERROR_STRINGS.append(call.format_error())

for legacy_proc_error in sorted(ERROR_STRINGS):
print(legacy_proc_error)

end = time.time()
print(f"check_legacy_attack_chain tests completed in {end - start:.2f}s\n")
Expand Down

0 comments on commit cc9b5fb

Please sign in to comment.