A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
81
fork

Configure Feed

Select the types of activity you want to include in your feed.

add monitor script

+101
+101
scripts/dpop-monitor.sh
··· 1 + #!/bin/bash 2 + # Monitor PDS logs for DPoP JWTs and compare iat timestamps 3 + # Usage: ./dpop-monitor.sh [pod-name] 4 + 5 + POD="${1:-atproto-pds-6d5c45457d-wcmhc}" 6 + 7 + echo "Monitoring DPoP JWTs from pod: $POD" 8 + echo "Press Ctrl+C to stop" 9 + echo "-------------------------------------------" 10 + 11 + kubectl logs -f "$POD" 2>/dev/null | while read -r line; do 12 + # Extract DPoP JWT from the line 13 + dpop=$(echo "$line" | grep -oP '"dpop":"[^"]+' | sed 's/"dpop":"//') 14 + 15 + if [ -n "$dpop" ]; then 16 + # Extract log timestamp (milliseconds) 17 + log_time_ms=$(echo "$line" | grep -oP '"time":\d+' | grep -oP '\d+') 18 + 19 + # Extract URL 20 + url=$(echo "$line" | grep -oP '"url":"[^"]+' | sed 's/"url":"//') 21 + 22 + # Extract status code 23 + status=$(echo "$line" | grep -oP '"statusCode":\d+' | grep -oP '\d+') 24 + 25 + # Extract client IP (cf-connecting-ip) 26 + client_ip=$(echo "$line" | grep -oP '"cf-connecting-ip":"[^"]+' | sed 's/"cf-connecting-ip":"//') 27 + 28 + # Extract user-agent to identify the source 29 + user_agent=$(echo "$line" | grep -oP '"user-agent":"[^"]+' | sed 's/"user-agent":"//') 30 + 31 + # Extract referer (often contains the source app) 32 + referer=$(echo "$line" | grep -oP '"referer":"[^"]+' | sed 's/"referer":"//' | grep -oP 'https://[^/]+' | sed 's|https://||') 33 + 34 + # Decode JWT payload (second part between dots) 35 + payload=$(echo "$dpop" | cut -d. -f2) 36 + 37 + # Add padding if needed for base64 38 + padding=$((4 - ${#payload} % 4)) 39 + if [ $padding -ne 4 ]; then 40 + payload="${payload}$(printf '=%.0s' $(seq 1 $padding))" 41 + fi 42 + 43 + # Decode and extract iat 44 + decoded=$(echo "$payload" | base64 -d 2>/dev/null) 45 + iat=$(echo "$decoded" | grep -oP '"iat":\d+' | grep -oP '\d+') 46 + exp=$(echo "$decoded" | grep -oP '"exp":\d+' | grep -oP '\d+') 47 + htu=$(echo "$decoded" | grep -oP '"htu":"[^"]+' | sed 's/"htu":"//') 48 + 49 + if [ -n "$iat" ] && [ -n "$log_time_ms" ]; then 50 + # Convert log time to seconds 51 + log_time_s=$((log_time_ms / 1000)) 52 + 53 + # Calculate difference (positive = token from future, negative = token from past) 54 + diff=$((iat - log_time_s)) 55 + 56 + # Determine source - prefer referer, then htu domain, then user-agent 57 + if [ -n "$referer" ]; then 58 + source="$referer" 59 + else 60 + # Extract domain from htu (the target of the DPoP request) 61 + htu_domain=$(echo "$htu" | grep -oP 'https://[^/]+' | sed 's|https://||') 62 + 63 + # For server-to-server calls, try to identify by known IPs 64 + case "$client_ip" in 65 + 152.44.36.124) source="atcr.io" ;; 66 + 2a04:3541:8000:1000:*) source="tangled.org" ;; 67 + *) 68 + if echo "$user_agent" | grep -q "indigo-sdk"; then 69 + source="indigo-sdk" 70 + elif echo "$user_agent" | grep -q "Go-http-client"; then 71 + source="Go-app" 72 + else 73 + source="${user_agent:0:30}" 74 + fi 75 + source="$source ($client_ip)" 76 + ;; 77 + esac 78 + fi 79 + 80 + # Color coding 81 + if [ $diff -gt 0 ]; then 82 + color="\033[31m" # Red - future token (problem!) 83 + status_text="FUTURE" 84 + elif [ $diff -lt -5 ]; then 85 + color="\033[33m" # Yellow - old token 86 + status_text="OLD" 87 + else 88 + color="\033[32m" # Green - ok 89 + status_text="OK" 90 + fi 91 + reset="\033[0m" 92 + 93 + echo "" 94 + echo -e "${color}[$status_text]${reset} Diff: ${diff}s | Source: $source | Status: $status" 95 + echo " iat (token): $iat ($(date -d @$iat -u '+%H:%M:%S UTC'))" 96 + echo " PDS received: $log_time_s ($(date -d @$log_time_s -u '+%H:%M:%S UTC'))" 97 + echo " URL: $url" 98 + [ -n "$client_ip" ] && echo " Client IP: $client_ip" 99 + fi 100 + fi 101 + done