Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve CI output for legacy attack chain check #27587

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading