Skip to content

Sync Guardrails to Akto #2

Sync Guardrails to Akto

Sync Guardrails to Akto #2

name: Sync Guardrails to Akto
on:
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate JSON files
run: |
set -euo pipefail
shopt -s nullglob
echo "::group::Discovering policy files"
files=(atlas/*.json argus/*.json)
if [ ${#files[@]} -eq 0 ]; then
echo "::warning::No guardrail files found. Exiting."
exit 0
fi
echo "Found ${#files[@]} file(s): ${files[*]}"
echo "::endgroup::"
echo "::group::Validating files"
seen_names=()
for f in "${files[@]}"; do
jq empty "$f" 2>/dev/null || { echo "::error file=$f::Invalid JSON"; exit 1; }
name=$(basename "$f" .json)
if [[ " ${seen_names[*]} " == *" $name "* ]]; then
echo "::error file=$f::Duplicate policy name: $name"
exit 1
fi
seen_names+=("$name")
echo "✅ $f — name: $name"
done
echo "::endgroup::"
- name: Sync policies to Akto
env:
AKTO_API_URL: ${{ secrets.AKTO_API_URL }}
AKTO_API_KEY: ${{ secrets.AKTO_API_KEY }}
run: |
set -uo pipefail
shopt -s nullglob
success=0; unchanged=0; failed=0
failed_files=()
sync_dir() {
local dir="$1"
local context_source="$2"
local files=("$dir"/*.json)
if [ ${#files[@]} -eq 0 ] || [ ! -f "${files[0]}" ]; then
echo " No files in $dir — skipping"
return
fi
echo "::group::Syncing $dir (x-context-source: $context_source)"
for f in "${files[@]}"; do
name=$(basename "$f" .json)
hash=$(sha256sum "$f" | awk '{print $1}')
echo "→ [$context_source] $name (sha256: ${hash:0:16}...)"
payload=$(jq \
--arg n "$name" \
--arg h "$hash" \
--arg by "Github Workflow" \
'{policy: (. + {name: $n, createdBy: $by, sourceHash: $h, source: "GITHUB_WORKFLOW"})}' "$f")
http_code=$(curl -sS -o /tmp/resp.txt -w "%{http_code}" \
--retry 3 --retry-delay 2 --retry-all-errors \
--max-time 30 \
-X POST "$AKTO_API_URL/api/createGuardrailPolicy" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $AKTO_API_KEY" \
-H "x-context-source: $context_source" \
--data-raw "$payload")
body=$(cat /tmp/resp.txt)
if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
status=$(echo "$body" | jq -r '.status // "ok"' 2>/dev/null || echo "ok")
case "$status" in
unchanged)
echo " ⏭ $name — unchanged (no-op)"
unchanged=$((unchanged+1))
;;
*)
echo " ✅ $name — synced (HTTP $http_code)"
success=$((success+1))
;;
esac
else
echo "::error file=$f::Sync failed — HTTP $http_code: $body"
failed=$((failed+1))
failed_files+=("$f")
fi
sleep 0.2
done
echo "::endgroup::"
}
echo "::group::Syncing atlas → ENDPOINT"
sync_dir atlas ENDPOINT
echo "::endgroup::"
echo "::group::Syncing argus → AGENTIC"
sync_dir argus AGENTIC
echo "::endgroup::"
echo ""
echo "===== Summary ====="
echo "✅ Synced: $success"
echo "⏭ Unchanged: $unchanged"
echo "❌ Failed: $failed"
if [ "$failed" -gt 0 ]; then
echo "::error::${#failed_files[@]} policy(s) failed to sync:"
printf ' - %s\n' "${failed_files[@]}"
exit 1
fi