#!/usr/bin/env bash

set -euo pipefail

ns=foobar

create() {
  oc -n ${ns} create -f -
}

apply() {
  oc -n ${ns} apply -f -
}

namespace() {
  cat <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: $ns
EOF
}

# including the annoations for net-istio
ksvc() {
  cat <<EOF
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  annotations:
    serving.knative.openshift.io/enablePassthrough: "true"
spec:
  template:
    spec:
      annotations:
        sidecar.istio.io/inject: "true"
        sidecar.istio.io/rewriteAppHTTPProbers: "true"
      containers:
      - image: gcr.io/knative-samples/helloworld-go
        env:
        - name: TARGET
          value: "Go Sample v1"
EOF
}

secret() {
  cat <<EOF
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
  name: helloworld-go
data:
  tls.crt: $1
  tls.key: $2
EOF
}

generate_tls_secret() {
  local hostname=$1
  local ip=$2
  local serial=$3

  tmp=$(mktemp -d)
  pushd $tmp >/dev/null

  openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
    -keyout example.key -set_serial ${serial} -out example.crt -subj "/CN=$hostname" \
    -addext "subjectAltName=DNS:$hostname,IP:$ip" >/dev/null
  popd >/dev/null

  secret $(cat $tmp/example.crt | base64 -w0) $(cat $tmp/example.key | base64 -w0)
}

domainmapping() {
  cat <<EOF
apiVersion: serving.knative.dev/v1alpha1
kind: DomainMapping
metadata:
  name: $1
spec:
  ref:
    name: helloworld-go
    kind: Service
    apiVersion: serving.knative.dev/v1
  tls:
    secretName: helloworld-go
EOF
}

namespace | create || echo "failed to create namespace, ignoring, possibly already created?"
ksvc | create
oc wait -n ${ns} --for=condition=Ready ksvc/helloworld-go

# get the IP address of the ingress router, by doing a DNS on the ksvc URL
hostname=$(oc get -n ${ns} ksvc helloworld-go -o json | jq -r .status.url | sed 's|^https://||')
ip=$(dig "$hostname" +short)

fakeHostname="helloworld.example.com"

generate_tls_secret ${fakeHostname} ${ip} 1  | create
domainmapping "$fakeHostname" | create
oc wait -n ${ns} --for=condition=Ready "domainmapping/$fakeHostname"

# wait a while to let the route propagate
sleep 10

curl -k --resolve $fakeHostname:443:$ip https://$fakeHostname

serial1=$(echo "" | openssl s_client -showcerts -servername $fakeHostname -connect $ip:443 2>&1|openssl x509 -noout -serial)

echo "Serial1: $serial1"

# update the certificate (oc apply on the update secret)
generate_tls_secret ${fakeHostname} ${ip} 2 | apply

# sleep to let whatever reconcile
echo "Sleeping for 60s to give time for the secret change to propagate"
sleep 60

curl -k --resolve $fakeHostname:443:$ip https://$fakeHostname
serial2=$(echo "" | openssl s_client -showcerts -servername $fakeHostname -connect $ip:443 2>&1|openssl x509 -noout -serial)

echo "Serial2: $serial2"

if [ "$serial1" == "$serial2" ]
then
  echo "❌ Certificate serial should be different now!"
else
  echo "✅ Certificate serials differ as expected. All good!"
fi

echo "Run \"oc delete namespace $ns\" to cleanup"
