#!/bin/sh
# Run once in the configure service. All generated files belong to uid 10001.
set -eu
umask 077
: "${DOMAIN:?Set DOMAIN to the public entry address}"
: "${OIDC_ISSUER:?Set OIDC_ISSUER to the identity provider issuer}"
: "${OIDC_CLIENT_ID:?Set OIDC_CLIENT_ID}"
# Control, peer and metrics listeners stay on unpublished Docker networks.
container_bind=0.0.0.0
authority_routing=${AUTHORITY_ROUTING:-lb}
case "$authority_routing" in
    lb) authority_host=authority-lb ;;
    direct) authority_host=authority-a ;;
    *) echo 'AUTHORITY_ROUTING must be lb or direct.' >&2; exit 1 ;;
esac
test ! -e /etc/gdsgate/authority-a.toml || {
    echo 'Configuration already exists; use gdsgate setup change for updates.' >&2
    exit 1
}

case "$TLS_MODE" in
    dns|ip) ;;
    *) echo 'TLS_MODE must be dns or ip.' >&2; exit 1 ;;
esac
# The private registration certificate is cluster-issued in both public modes.
# Public DNS certificates belong to the Proxy, independently of Authority HA.
gdsgate setup prepare --domain 127.0.0.1 --security-profile pilot --join-relay \
    --role authority --authority-bind "$container_bind" \
    --authority-output /etc/gdsgate/authority-a.toml \
    --policy-output /etc/gdsgate/policy.cedar \
    --store-url postgres://gdsgate@postgres:5432/gdsgate \
    --store-password-file /run/secrets/store_password \
    --oidc-issuer "$OIDC_ISSUER" --oidc-client-id "$OIDC_CLIENT_ID" \
    --access-group "$ACCESS_GROUP" --unit-dir /tmp/units

gdsgate setup change --authority-config /etc/gdsgate/authority-a.toml \
    --set authority:ha.enabled=yes \
    --set authority:ha.owner=authority-a \
    --set authority:ha.max_cluster_sessions=1024 \
    --set "authority:telemetry.metrics_listen=$container_bind:9090" \
    --set authority:admin.identity_dir=/admin \
    --set authority:admin.endpoint=https://authority-a:50051 \
    --set authority:audit.export_path=/var/lib/gdsgate/authority/audit.jsonl \
    --set "authority:endpoints.proxy_public=$DOMAIN:$PUBLIC_PORT" \
    --set "authority:endpoints.proxy_internal=$DOMAIN:$TUNNEL_PORT" \
    --set "authority:endpoints.proxy_ws=$DOMAIN:$WS_PORT"
if [ "$TLS_MODE" = ip ]; then
    gdsgate setup change --authority-config /etc/gdsgate/authority-a.toml \
        --set "authority:endpoints.proxy_join=$DOMAIN:$JOIN_PORT"
else
    sed -i '/^proxy_join =/d' /etc/gdsgate/authority-a.toml
    gdsgate setup change --authority-config /etc/gdsgate/authority-a.toml \
        --set authority:proxy.public_join=yes
fi

cat >> /etc/gdsgate/authority-a.toml <<'EOF'

[ha.authority_peers]
authority-a = "https://authority-a:50051"
authority-b = "https://authority-b:50051"

[ha.keyring_sync]
enabled = true
initialize = true
state_dir = "/var/lib/gdsgate/authority/keyring-sync"
poll_secs = 5
EOF
if [ "$ENABLE_DEMO" = 1 ]; then
    cat >> /etc/gdsgate/authority-a.toml <<'EOF'

[[discovery.resources]]
id = "ha-demo"
kind = "postgres"

[[discovery.resources]]
id = "ha-denied"
kind = "postgres"
EOF
    cat >> /etc/gdsgate/policy.cedar <<'EOF'

// A served resource for the deployment's negative access check.
forbid(principal, action == Action::"connect", resource == Database::"ha-denied");
EOF
fi
cp /etc/gdsgate/authority-a.toml /etc/gdsgate/authority-b.toml
# Only A's initial rings seed the canonical snapshot. B bootstraps from A.
sed -i '/^control_keyring =/d; /^audit_keyring =/d' /etc/gdsgate/authority-b.toml
gdsgate setup change --authority-config /etc/gdsgate/authority-b.toml \
    --set authority:ha.owner=authority-b \
    --set authority:ha.keyring_sync.initialize=no \
    --set authority:ha.keyring_sync.bootstrap_endpoint=https://authority-a:50050 \
    --set authority:ha.keyring_sync.bootstrap_fingerprint=REPLACE_WITH_TRANSPORT_CA_FINGERPRINT \
    --set 'authority:ha.keyring_sync.bootstrap_token=${file:/run/secrets/authority-bootstrap.token}'

case "$TLS_MODE" in
    dns) set -- --enroll-cert /etc/gdsgate/transport-ca.pem \
        --tls-cert /etc/gdsgate/tls/fullchain.pem --tls-key /etc/gdsgate/tls/privkey.pem ;;
    ip) set -- --join-relay ;;
esac
gdsgate setup prepare --domain "$DOMAIN" --security-profile pilot "$@" \
    --role proxy --authority-host "$authority_host" \
    --proxy-output /etc/gdsgate/proxy.toml \
    --state-dir /var/lib/gdsgate/proxy \
    --oidc-issuer "$OIDC_ISSUER" --oidc-client-id "$OIDC_CLIENT_ID" \
    --unit-dir /tmp/units

# A trailing comma makes setup change write a one-element array.
gdsgate setup change --proxy-config /etc/gdsgate/proxy.toml \
    --set "proxy:telemetry.metrics_listen=$container_bind:9090" \
    --set "proxy:proxy.peer_listen=$container_bind:50065" \
    --set proxy:proxy.peer_addr=https://proxy-a:50065 \
    --set "proxy:proxy.public_proxy_protocol_from=$PROXY_LB_IP," \
    --set proxy:enroll.transport_sni=enroll.gdsgate.internal \
    --set proxy:enroll.transport_ca=/etc/gdsgate/transport-ca.pem \
    --set 'proxy:enroll.token=${file:/run/secrets/proxy.token}'

for name in proxy-a proxy-b; do
    cp /etc/gdsgate/proxy.toml "/etc/gdsgate/$name.toml"
    gdsgate setup change --proxy-config "/etc/gdsgate/$name.toml" \
        --set "proxy:enroll.node_name=$name" \
        --set "proxy:proxy.peer_addr=https://$name:50065"
done
if [ "$authority_routing" = direct ]; then
    gdsgate setup change --proxy-config /etc/gdsgate/proxy-a.toml \
        --set proxy:endpoints.authority_failover=authority-b:50051, \
        --set proxy:endpoints.authority_enroll_failover=authority-b:50050,
    gdsgate setup change --proxy-config /etc/gdsgate/proxy-b.toml \
        --set proxy:endpoints.authority=authority-b:50051 \
        --set proxy:endpoints.authority_failover=authority-a:50051, \
        --set proxy:endpoints.authority_enroll=authority-b:50050 \
        --set proxy:endpoints.authority_enroll_failover=authority-a:50050, \
        --set proxy:enroll.endpoint=https://authority-b:50050
fi
rm /etc/gdsgate/proxy.toml

# The first start renews the generated registration certificate for the final
# advertised gateway addresses. A pre-start warning is not a parse error.
config_check_status=0
gdsgate config check /etc/gdsgate/authority-a.toml --role authority || config_check_status=$?
test "$config_check_status" -eq 0 || test "$config_check_status" -eq 2
echo "Configured A, joining B and individual Proxy files; Authority routing: $authority_routing. Set the trusted bootstrap pin and issue B permission before starting B; issue separate Proxy tokens before starting Proxies."
