Skip to content
Draft
Show file tree
Hide file tree
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
10 changes: 10 additions & 0 deletions k8s/apps/bases/scanners/dns-processor/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ spec:
key: DB_USER
- name: NATS_SERVERS
value: nats://nats.pubsub:4222
- name: CNAME_MONITOR_ONLY_LIST
valueFrom:
secretKeyRef:
name: scanners
key: CNAME_MONITOR_ONLY_LIST
- name: SERVICE_ACCOUNT_EMAIL
valueFrom:
secretKeyRef:
name: scanners
key: SERVICE_ACCOUNT_EMAIL
- name: NOTIFICATION_API_KEY
valueFrom:
secretKeyRef:
Expand Down
84 changes: 84 additions & 0 deletions scanners/dns-processor/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
DB_NAME = os.getenv("DB_NAME")
DB_URL = os.getenv("DB_URL")

CNAME_MONITOR_ONLY_LIST = os.getenv("CNAME_MONITOR_ONLY_LIST", "").split(",")
SERVICE_ACCOUNT_EMAIL = os.getenv("SERVICE_ACCOUNT_EMAIL")

SCAN_THREAD_COUNT = int(os.getenv("SCAN_THREAD_COUNT", 1))

# Establish DB connection
Expand Down Expand Up @@ -170,6 +173,18 @@ def check_mx_diff(processed_results, domain_id):
return mx_record_diff


def is_cname_target(resolve_chain, domains):
# Check if any CNAME record in the resolve chain points to a domain in the provided list
for rrset in resolve_chain:
for record in rrset:
record_parts = record.split(" ")
if len(record_parts) >= 5 and record_parts[3] == "CNAME":
record_target = record_parts[4].strip(".")
if record_target in domains:
return True
return False


def process_msg(msg):
subject = msg.subject
reply = msg.reply
Expand Down Expand Up @@ -370,6 +385,75 @@ def process_msg(msg):
f"Error while updating domain after retrying for received message: {msg}: {error_str}"
)

if processed_results.get("cname_record") is not None and CNAME_MONITOR_ONLY_LIST:
try:
# Use resolve chain instead of CNAME as some domains have CNAMEs that point to other CNAMEs before reaching the final target domain
is_cname_target_in_monitor_only_list = is_cname_target(
resolve_chain=processed_results.get("resolve_chain", []),
domains=CNAME_MONITOR_ONLY_LIST,
)

if is_cname_target_in_monitor_only_list:
# Get current claim asset states of domain
approved_state_claims_cursor = db.aql.execute(
"""
FOR v, e IN 1..1 INBOUND @domain_id claims
FILTER v.verified == true
FILTER e.assetState == "approved"
RETURN e
""",
bind_vars={"domain_id": domain["_id"]},
)
if approved_state_claims_cursor.empty():
logger.debug(
f"No approved claims for domain with CNAME in monitor-only list for received message: {msg}"
)
else:
approved_state_claims = [claim for claim in approved_state_claims_cursor]
for claim in approved_state_claims:
try:
logger.info(f"Domain with CNAME in monitor-only list has approved claim, updating claim state to monitor-only for claim: {claim}")
claim["assetState"] = "monitor-only"
db.collection("claims").update(claim)

insert_activity = {
"timestamp": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[
:-3
]
+ "Z",
"initiatedBy": {
"id": "dns-processor",
"userName": SERVICE_ACCOUNT_EMAIL,
"role": "service",
},
"target": {
"resource": domain["domain"],
"updatedProperties": [
{
"name": "assetState",
"oldValue": "approved",
"newValue": "monitor-only",
}
],
"organization": {"id": claim["_from"].split("/")[1]},
"resourceType": "domain",
},
"action": "update",
"reason": None,
}
db.collection("auditLogs").insert(insert_activity)

except Exception as e:
logger.error(
f"Error while processing claim with approved state for domain with CNAME in monitor-only list for received message: {msg}: {str(e)}"
)
continue

except Exception as e:
logger.error(
f"Error while parsing CNAME record for received message: {msg}: {str(e)}"
)

except Exception as e:
logger.error(
f"Error while inserting processed results for received message: {msg}: {str(e)} \n\nFull traceback: {traceback.format_exc()}"
Expand Down
3 changes: 2 additions & 1 deletion services/summaries/summaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def domain_has_verified_claim(domain, db):
"""
FOR v, e IN 1..1 INBOUND @domain_id claims
FILTER v.verified == true
FILTER e.assetState == "approved"
RETURN v
""",
bind_vars={"domain_id": domain["_id"]},
Expand Down Expand Up @@ -334,7 +335,7 @@ def update_org_summaries(host=DB_URL, name=DB_NAME, user=DB_USER, password=DB_PA
logging.error(f"Error processing domain {domain['_id']}: {e}")
continue

dmarc_phase_total = (
dmarc_phase_total = (
dmarc_phase_assess
+ dmarc_phase_deploy
+ dmarc_phase_enforce
Expand Down