#!/usr/bin/env bash
set -euo pipefail

KUBECONFIG="${KUBECONFIG:-${HOME}/.kube/config}"
ATTACK_NAMESPACE="${1:-${SECURITY_ATTACK_NAMESPACE:-website-production}}"
ATTACK_WORKLOAD="${2:-${SECURITY_ATTACK_WORKLOAD:-deployment/php-website-deployment}}"

usage() {
    cat <<'EOF'
Usage: scripts/security-attack-path [namespace] [workload]

Default:
  scripts/security-attack-path website-production deployment/php-website-deployment

This is a read-only compromise-path drill. It inspects what a compromised pod
would inherit: service account, mounted secrets, RBAC bindings, network
policies, and nearby services.
EOF
}

require_kubectl() {
    if ! command -v kubectl >/dev/null 2>&1; then
        echo "kubectl is required." >&2
        exit 1
    fi
    if [[ ! -f "${KUBECONFIG}" ]]; then
        echo "KUBECONFIG does not exist: ${KUBECONFIG}" >&2
        exit 1
    fi
}

section() {
    printf '\n== %s ==\n' "$1"
}

kubectl_ro() {
    kubectl --kubeconfig "${KUBECONFIG}" "$@"
}

jsonpath_or_unknown() {
    local resource="$1"
    local path="$2"
    local value

    value="$(kubectl_ro -n "${ATTACK_NAMESPACE}" get "${resource}" -o "jsonpath=${path}" 2>/dev/null || true)"
    printf '%s\n' "${value:-unknown}"
}

main() {
    local service_account
    local automount
    local selector

    case "${1:-}" in
        -h | --help | help)
            usage
            return 0
            ;;
    esac

    require_kubectl

    section "Attack Path Drill"
    printf 'Namespace: %s\n' "${ATTACK_NAMESPACE}"
    printf 'Workload:  %s\n' "${ATTACK_WORKLOAD}"

    if ! kubectl_ro -n "${ATTACK_NAMESPACE}" get "${ATTACK_WORKLOAD}" >/dev/null 2>&1; then
        echo "Target workload not found." >&2
        exit 1
    fi

    section "Identity"
    service_account="$(jsonpath_or_unknown "${ATTACK_WORKLOAD}" '{.spec.template.spec.serviceAccountName}')"
    automount="$(jsonpath_or_unknown "${ATTACK_WORKLOAD}" '{.spec.template.spec.automountServiceAccountToken}')"
    service_account="${service_account:-default}"
    printf 'ServiceAccount: %s\n' "${service_account}"
    printf 'Automount token: %s\n' "${automount}"
    if [[ "${automount}" != "false" ]]; then
        printf 'Focus: pod may receive a Kubernetes API token unless blocked by defaults.\n'
    fi

    section "Mounted Secrets And Config"
    kubectl_ro -n "${ATTACK_NAMESPACE}" get "${ATTACK_WORKLOAD}" \
        -o jsonpath='{range .spec.template.spec.volumes[*]}{.name}{" secret="}{.secret.secretName}{" configMap="}{.configMap.name}{" pvc="}{.persistentVolumeClaim.claimName}{" hostPath="}{.hostPath.path}{"\n"}{end}' || true

    section "RBAC Bindings In Namespace"
    kubectl_ro -n "${ATTACK_NAMESPACE}" get rolebinding -o wide 2>/dev/null || true
    printf '\nClusterRoleBindings mentioning service account %s/%s:\n' "${ATTACK_NAMESPACE}" "${service_account}"
    kubectl_ro get clusterrolebinding -o jsonpath='{range .items[?(@.subjects)]}{.metadata.name}{" "}{range .subjects[*]}{.kind}{"/"}{.namespace}{"/"}{.name}{" "}{end}{"\n"}{end}' 2>/dev/null |
        grep -F "ServiceAccount/${ATTACK_NAMESPACE}/${service_account}" || true

    section "Network Policies"
    kubectl_ro -n "${ATTACK_NAMESPACE}" get networkpolicy -o wide 2>/dev/null || true
    if ! kubectl_ro -n "${ATTACK_NAMESPACE}" get networkpolicy >/dev/null 2>&1; then
        printf 'Focus: no NetworkPolicy objects found; pod egress is probably unrestricted by namespace policy.\n'
    fi

    section "Nearby Services"
    kubectl_ro -n "${ATTACK_NAMESPACE}" get svc,endpoints -o wide 2>/dev/null || true

    section "Selected Pods"
    # shellcheck disable=SC2016
    selector="$(kubectl_ro -n "${ATTACK_NAMESPACE}" get "${ATTACK_WORKLOAD}" -o go-template='{{range $k,$v := .spec.selector.matchLabels}}{{printf "%s=%s," $k $v}}{{end}}' 2>/dev/null | sed 's/,$//')"
    if [[ -n "${selector}" ]]; then
        kubectl_ro -n "${ATTACK_NAMESPACE}" get pods -l "${selector}" -o wide
    else
        kubectl_ro -n "${ATTACK_NAMESPACE}" get pods -o wide
    fi

    section "Manual Follow-Up"
    cat <<EOF
Ask these questions before adding a fix:
- Does the pod need a service account token?
- Are any mounted Secrets unnecessary for runtime?
- Can this namespace use default-deny egress with explicit allows?
- Can the workload run as non-root with allowPrivilegeEscalation=false?
- Should this namespace be isolated from Gitea, registry, Pi-hole, and Kubernetes API?
EOF
}

main "$@"
