Skip to content

Commit

Permalink
Seceng 1648 fix persistent scan lambda timeouts (#11)
Browse files Browse the repository at this point in the history
* Import `utils.utils_aws.assume_role` to scan.py

Part of optimizing how auth calls run

Relates To: SECENG-1648

* Generate aws session in scan.py

Relates To: SECENG-1648

* Patch `scan.py`, `scan_ips.py`, and `utils_aws.py` to reuse the generated route53 clients

Relates To: SECENG-1648

* Remove Github Actions workflows as we do not use them for the BC branch
  • Loading branch information
bc-jcarlson authored Aug 16, 2024
1 parent a300145 commit 8484fe9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 49 deletions.
11 changes: 9 additions & 2 deletions lambda_code/scan/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import os

from utils.utils_aws import assume_role
from utils.utils_aws import eb_susceptible
from utils.utils_aws import get_cloudfront_s3_origin_takeover
from utils.utils_aws import list_domains
Expand Down Expand Up @@ -290,12 +291,18 @@ def lambda_handler(event, context): # pylint:disable=unused-argument
account_id = event["Id"]
account_name = event["Name"]

hosted_zones = list_hosted_zones(event)
aws_session = assume_role(account_id)
try:
r53client = aws_session.client("route53")
except Exception:
print(f"ERROR: unable to assume role in {account_name} account {account_id}")

hosted_zones = list_hosted_zones(r53client, event)

for hosted_zone in hosted_zones:
print(f"Searching for vulnerable domain records in hosted zone {hosted_zone['Name']}")

record_sets = list_resource_record_sets(account_id, account_name, hosted_zone["Id"])
record_sets = list_resource_record_sets(r53client, account_name, hosted_zone["Id"])
record_sets = sanitise_wildcards(record_sets)

alias_cloudfront_s3(account_name, record_sets, account_id)
Expand Down
11 changes: 9 additions & 2 deletions lambda_code/scan_ips/scan_ips.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import os

from utils.utils_aws import assume_role
from utils.utils_aws import list_hosted_zones
from utils.utils_aws import list_resource_record_sets
from utils.utils_aws import publish_to_sns
Expand Down Expand Up @@ -166,13 +167,19 @@ def lambda_handler(event, context): # pylint:disable=unused-argument

get_ips(account_id, account_name)

hosted_zones = list_hosted_zones(event)
aws_session = assume_role(account_id)
try:
r53client = aws_session.client("route53")
except Exception:
print(f"ERROR: unable to assume role in {account_name} account {account_id}")

hosted_zones = list_hosted_zones(r53client, event)

if item_count > 0: # don't test for vulnerabilities until DynamoDB table is populated across organisation
for hosted_zone in hosted_zones:
print(f"Searching for vulnerable A records in hosted zone {hosted_zone['Name']}")

record_sets = list_resource_record_sets(account_id, account_name, hosted_zone["Id"])
record_sets = list_resource_record_sets(r53client, account_name, hosted_zone["Id"])
record_sets = sanitise_wildcards(record_sets)

a_record(account_name, record_sets, ip_prefixes)
Expand Down
73 changes: 28 additions & 45 deletions utils/utils_aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,70 +86,53 @@ def list_accounts():
return []


def list_hosted_zones(account):
def list_hosted_zones(route53, account):

account_id = account["Id"]
account_name = account["Name"]

try:
boto3_session = assume_role(account_id)
route53 = boto3_session.client("route53")

hosted_zones_list = []

try:
paginator_zones = route53.get_paginator("list_hosted_zones")
pages_zones = paginator_zones.paginate()
for page_zones in pages_zones:
hosted_zones = [h for h in page_zones["HostedZones"] if not h["Config"]["PrivateZone"]]
hosted_zones_list = []

hosted_zones_list = hosted_zones_list + hosted_zones
try:
paginator_zones = route53.get_paginator("list_hosted_zones")
pages_zones = paginator_zones.paginate()
for page_zones in pages_zones:
hosted_zones = [h for h in page_zones["HostedZones"] if not h["Config"]["PrivateZone"]]

return hosted_zones_list
hosted_zones_list = hosted_zones_list + hosted_zones

except Exception:
logging.error(
"ERROR: Lambda execution role requires route53:ListHostedZones permission in %a account",
account_name,
)
return hosted_zones_list

except Exception:
logging.error("ERROR: unable to assume role in %a account %s", account_name, account_id)
logging.error(
"ERROR: Lambda execution role requires route53:ListHostedZones permission in %a account",
account_name,
)

return []


def list_resource_record_sets(account_id, account_name, hosted_zone_id):
def list_resource_record_sets(route53, account_name, hosted_zone_id):

try:
boto3_session = assume_role(account_id)
route53 = boto3_session.client("route53")

record_set_list = []

try:
paginator_records = route53.get_paginator("list_resource_record_sets")
pages_records = paginator_records.paginate(
HostedZoneId=hosted_zone_id,
StartRecordName="_",
StartRecordType="NS",
)
paginator_records = route53.get_paginator("list_resource_record_sets")
pages_records = paginator_records.paginate(
HostedZoneId=hosted_zone_id,
StartRecordName="_",
StartRecordType="NS",
)

for page_records in pages_records:
record_sets = page_records["ResourceRecordSets"]
for page_records in pages_records:
record_sets = page_records["ResourceRecordSets"]

record_set_list = record_set_list + record_sets
record_set_list = record_set_list + record_sets

return record_set_list

except Exception:
logging.exception(
"ERROR: Lambda execution role requires route53:ListResourceRecordSets permission in %a account",
account_name,
)
return record_set_list

except Exception:
logging.error("ERROR: unable to assume role in %a account %s", account_name, account_id)
logging.exception(
"ERROR: Lambda execution role requires route53:ListResourceRecordSets permission in %a account",
account_name,
)

return []

Expand Down

0 comments on commit 8484fe9

Please sign in to comment.