#!/usr/bin/env python3
"""Agent for deploying and managing honeytokens for breach detection."""

import os
import json
import uuid
import hashlib
import argparse
from datetime import datetime

import re

import requests

_SAFE_TABLE_RE = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$')


def create_dns_canarytoken(email, memo, webhook_url=None):
    """Create a DNS canary token via Canarytokens.org API."""
    data = {
        "type": "dns",
        "email": email,
        "memo": memo,
    }
    if webhook_url:
        data["webhook_url"] = webhook_url
    resp = requests.post("https://canarytokens.org/generate", data=data, timeout=15)
    resp.raise_for_status()
    return resp.json()


def create_web_bug_token(email, memo, webhook_url=None):
    """Create a web bug (image beacon) canary token."""
    data = {
        "type": "web_image",
        "email": email,
        "memo": memo,
    }
    if webhook_url:
        data["webhook_url"] = webhook_url
    resp = requests.post("https://canarytokens.org/generate", data=data, timeout=15)
    resp.raise_for_status()
    return resp.json()


def create_aws_key_token(email, memo, webhook_url=None):
    """Create an AWS credential canary token."""
    data = {
        "type": "aws_keys",
        "email": email,
        "memo": memo,
    }
    if webhook_url:
        data["webhook_url"] = webhook_url
    resp = requests.post("https://canarytokens.org/generate", data=data, timeout=15)
    resp.raise_for_status()
    return resp.json()


def generate_honeytoken_id():
    """Generate a unique honeytoken identifier."""
    return f"HT-{uuid.uuid4().hex[:12].upper()}"


def deploy_aws_credential_token(target_path, canary_key_id, canary_secret):
    """Deploy fake AWS credentials file as a honeytoken."""
    content = (
        "[default]\n"
        f"aws_access_key_id = {canary_key_id}\n"
        f"aws_secret_access_key = {canary_secret}\n"
        "region = us-east-1\n"
    )
    os.makedirs(os.path.dirname(target_path), exist_ok=True)
    with open(target_path, "w") as f:
        f.write(content)
    return {
        "type": "aws_credentials",
        "path": target_path,
        "token_id": generate_honeytoken_id(),
        "deployed_at": datetime.utcnow().isoformat(),
    }


def deploy_database_honeytoken(db_connection_string, table_name="users"):
    """Generate SQL to insert honeytoken records into a database."""
    if not _SAFE_TABLE_RE.match(table_name):
        raise ValueError(f"Invalid table name: {table_name!r}")
    token_id = generate_honeytoken_id()
    fake_users = [
        {
            "username": "svc_backup_admin",
            "email": f"{token_id}@canary.internal",
            "role": "admin",
            "api_key": hashlib.sha256(token_id.encode()).hexdigest()[:40],
        },
        {
            "username": "emergency_break_glass",
            "email": f"bg-{token_id}@canary.internal",
            "role": "superadmin",
            "api_key": hashlib.sha256(f"bg-{token_id}".encode()).hexdigest()[:40],
        },
    ]
    sql_statements = []
    for user in fake_users:
        sql = (
            f"INSERT INTO [{table_name}] (username, email, role, api_key) "
            "VALUES (?, ?, ?, ?);"
        )
        sql_statements.append({
            "query": sql,
            "params": [user["username"], user["email"], user["role"], user["api_key"]],
        })
    return {"token_id": token_id, "sql_statements": sql_statements, "records": fake_users}


def deploy_dns_token_in_config(config_path, dns_hostname, key_name="backup_server"):
    """Embed a DNS canary token in a configuration file."""
    config_entry = f"{key_name} = {dns_hostname}\n"
    with open(config_path, "a") as f:
        f.write(f"\n# Backup configuration\n{config_entry}")
    return {
        "type": "dns_config",
        "config_path": config_path,
        "dns_hostname": dns_hostname,
        "deployed_at": datetime.utcnow().isoformat(),
    }


def create_deployment_plan(target_environment):
    """Create a honeytoken deployment plan for an environment."""
    plan = {
        "environment": target_environment,
        "tokens": [
            {"type": "aws_credentials", "location": "/opt/backup/.aws/credentials",
             "description": "Fake AWS creds in backup directory"},
            {"type": "dns", "location": "/etc/app/config.yml",
             "description": "DNS canary in app config"},
            {"type": "database", "location": "users table",
             "description": "Honeytoken admin accounts"},
            {"type": "web_bug", "location": "internal wiki",
             "description": "Image beacon in sensitive docs"},
            {"type": "dns", "location": "/root/.ssh/config",
             "description": "DNS canary in SSH config"},
        ],
    }
    return plan


def check_token_alerts(webhook_log_path):
    """Parse webhook logs to check for honeytoken trigger alerts."""
    if not os.path.exists(webhook_log_path):
        return []
    with open(webhook_log_path) as f:
        logs = json.load(f)
    alerts = []
    for entry in logs:
        if entry.get("type") == "canarytoken_triggered":
            alerts.append({
                "token_memo": entry.get("memo", ""),
                "source_ip": entry.get("src_ip", ""),
                "triggered_at": entry.get("time", ""),
                "token_type": entry.get("token_type", ""),
            })
    return alerts


def main():
    parser = argparse.ArgumentParser(description="Honeytoken Deployment Agent")
    parser.add_argument("--email", default=os.getenv("CANARY_EMAIL", "soc@company.com"))
    parser.add_argument("--webhook", default=os.getenv("CANARY_WEBHOOK"))
    parser.add_argument("--output", default="honeytoken_report.json")
    parser.add_argument("--action", choices=[
        "create_dns", "create_aws", "create_web", "plan", "full_deploy"
    ], default="plan")
    args = parser.parse_args()

    report = {"generated_at": datetime.utcnow().isoformat(), "tokens": {}}

    if args.action == "plan":
        plan = create_deployment_plan("production")
        report["deployment_plan"] = plan
        print(f"[+] Deployment plan: {len(plan['tokens'])} tokens")

    if args.action in ("create_dns", "full_deploy"):
        token = create_dns_canarytoken(args.email, "Production honeytoken", args.webhook)
        report["tokens"]["dns"] = token
        print(f"[+] DNS canary token created")

    if args.action in ("create_aws", "full_deploy"):
        token = create_aws_key_token(args.email, "AWS credential honeytoken", args.webhook)
        report["tokens"]["aws"] = token
        print(f"[+] AWS credential token created")

    if args.action in ("create_web", "full_deploy"):
        token = create_web_bug_token(args.email, "Web beacon honeytoken", args.webhook)
        report["tokens"]["web_bug"] = token
        print(f"[+] Web bug token created")

    with open(args.output, "w") as f:
        json.dump(report, f, indent=2, default=str)
    print(f"[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
