#!/bin/bash

# Create a temporary path that will be added to the PATH to avoid picking up
# binaries from the environment that aren't a version match.
mkdir -p ./bin

KIND_PATH=./bin/kind
KUBECTL_PATH=./bin/kubectl
REGISTRY_HTTP_ADDR="docker-registry-local:5001"

# Download kind at the expected version at the given path.
download-kind "${KIND_PATH}"

# Download kubectl at the expected version.
download-kubectl "${KUBECTL_PATH}"

# We must supply an absolute path to the configuration directory. Replace the
# CONFDIR variable in the kind configuration with the conf directory of the
# running test.
sed -i.bak "s#CONFDIR#${PWD}/conf#g" conf/kind-config.yaml
rm conf/kind-config.yaml.bak

# Create folder which will contain the registry certificate information
mkdir -p "${PWD}/conf/docker-registry/certs"

# Create local registry self signed certificate files
openssl req -new -newkey rsa:4096 -nodes -sha256 \
    -keyout "${PWD}/conf/docker-registry/certs/domain.key" \
    -addext "subjectAltName = DNS:docker-registry-local" \
    -x509 -days 365 \
    -subj "/C=US/ST=CA/L=SF/O=SPIRE/CN=docker-registry-local" \
    -out "${PWD}/conf/docker-registry/certs/domain.crt"

# Start the kind cluster.
start-kind-cluster "${KIND_PATH}" k8stest ./conf/kind-config.yaml

# Start local registry service connected to kind network
docker-up registry

# Copy the signed image using crane, which pushes platform manifests before the
# index (dependency order). This avoids the race condition in "cosign copy" where
# the image index is pushed concurrently with its platform manifests, causing
# MANIFEST_BLOB_UNKNOWN errors when the index references a platform manifest
# that has not yet been committed.
docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy ghcr.io/spiffe/spire-agent:1.14.0 "${REGISTRY_HTTP_ADDR}/workload:signed"

# Copy the cosign signature tag separately, after the image is fully committed.
# Cosign stores signatures as OCI tags with the format sha256-<hex-digest>.sig.
signed_digest=$(docker run --rm --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    digest "${REGISTRY_HTTP_ADDR}/workload:signed")
sig_tag="sha256-${signed_digest#sha256:}.sig"
docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy "ghcr.io/spiffe/spire-agent:${sig_tag}" "${REGISTRY_HTTP_ADDR}/workload:${sig_tag}"

# For unsigned/skiplist workload testing, use a different SPIRE agent version (1.13.0)
# This ensures unsigned variants have a different digest than the signed image (1.14.0)
# Using crane (not cosign) so signatures are not copied
# These images will be added to skiplist to bypass Sigstore verification
docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy ghcr.io/spiffe/spire-agent:1.13.0 "${REGISTRY_HTTP_ADDR}/workload:unsigned"

docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy ghcr.io/spiffe/spire-agent:1.13.0 "${REGISTRY_HTTP_ADDR}/workload:unsigned-skiplist1"

docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy ghcr.io/spiffe/spire-agent:1.13.0 "${REGISTRY_HTTP_ADDR}/workload:unsigned-skiplist2"

docker run --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    copy ghcr.io/spiffe/spire-agent:1.13.0 "${REGISTRY_HTTP_ADDR}/workload:signed-wrong-subject"

# Copy certificate to ssl certificates dest folder on kind cluster
docker exec k8stest-control-plane \
    cp /mnt/reg-certificate/docker-registry/certs/domain.crt /etc/ssl/certs/

# Load the given images in the cluster.
container_images=("spire-server:latest-local" "spire-agent:latest-local")
load-images "${KIND_PATH}" k8stest "${container_images[@]}"

# Get the agent image ID and unsigned workload digest, then update the agent config
agent_image_id=$(docker inspect --format='{{.Id}}' spire-agent:latest-local)

# Get the digest of the unsigned workload image (all unsigned variants use the same 1.9.6 base)
# We need to query the local registry to get the digest as seen by the agent
unsigned_digest=$(docker run --rm --network="kind" \
    -v "${PWD}/conf/docker-registry/certs/domain.crt:/etc/ssl/certs/domain.crt" \
    gcr.io/go-containerregistry/crane:latest \
    digest "${REGISTRY_HTTP_ADDR}/workload:unsigned")

# Update agent config with both agent ID and unsigned digest
sed -i.bak "s#AGENT_ID#${agent_image_id}#g; s#UNSIGNED_DIGEST#docker-registry-local:5001/workload@${unsigned_digest}#g" "${PWD}/conf/agent/spire-agent.yaml"
rm "${PWD}/conf/agent/spire-agent.yaml.bak"

# Set the kubectl context.
set-kubectl-context "${KUBECTL_PATH}" kind-k8stest
