diff --git a/scripts/build-and-test.sh b/scripts/build-and-test.sh index ef1e9a7..b4105c8 100644 --- a/scripts/build-and-test.sh +++ b/scripts/build-and-test.sh @@ -17,7 +17,14 @@ echo "==============================================================" CODE=$(wget -qO /tmp/idx.html --server-response http://127.0.0.1/ 2>&1 | sed -n 's/.*HTTP\/1\.[01] \([0-9]*\).*/\1/p' | head -1) chk "HTTP status for /" "$CODE" "200" if grep -qi 'Atheos IDE' /tmp/idx.html 2>/dev/null; then ok "served page is the Atheos IDE"; else bad "served page is not Atheos"; fi -if grep -qiE 'install|setup' /tmp/idx.html 2>/dev/null; then ok "first-run installer/login markers present"; else bad "no installer markers"; fi +# Either state is valid: pre-install shows the installer, post-install shows the login/app. +if grep -qiE 'install|setup' /tmp/idx.html 2>/dev/null; then + ok "installer markers present (pre-install state)" +elif [ -f "$W/config.php" ] && [ -s "$W/config.php" ]; then + ok "installer already completed (config.php populated)" +else + bad "neither installer markers nor a populated config.php" +fi SOCK=$(sed -n 's/^listen = //p' /etc/php83/php-fpm.d/www.conf | head -1) NGX=$(sed -n 's/.*fastcgi_pass unix:\([^;]*\);.*/\1/p' /etc/nginx/http.d/atheos.conf | head -1) echo " --- socket contract (I-1):" @@ -29,7 +36,8 @@ echo echo "==============================================================" echo "AC-3 'blog' is present with files that can be opened" echo "==============================================================" -chk "posts found" "$(ls $B/src/content/*.md 2>/dev/null | wc -l | tr -d ' ')" "20" +POSTS=$(ls $B/src/content/*.md 2>/dev/null | wc -l | tr -d ' ') +if [ "$POSTS" -ge 20 ]; then ok "posts found ($POSTS, expected >= 20)"; else bad "posts found ($POSTS, expected >= 20)"; fi if [ -d "$W/workspace/blog/.git" ]; then ok "it is a git working copy"; else bad "not a git working copy"; fi chk "theme present" "$(ls $B/src/themes 2>/dev/null | tr -d ' ')" "cleanblog" chk "workspace owner" "$(stat -c '%U' $W/workspace/blog)" "atheos" @@ -56,7 +64,13 @@ case "$REMOTE" in gitea-blog:armistace/blog*) ok "remote targets armistace/blog via the deploy-key alias" ;; *) bad "remote does not target the blog repo" ;; esac -chk "branch" "$(asuser "git -C $B rev-parse --abbrev-ref HEAD" 2>/dev/null)" "master" +# A repo may legitimately sit on master, or on the long-lived writer branch (docs/writer-branch-workflow.md). +BR=$(asuser "git -C $B rev-parse --abbrev-ref HEAD" 2>/dev/null) +case "$BR" in + master|main) ok "branch ($BR)" ;; + atheos-writer) ok "branch ($BR - writer-branch workflow)" ;; + *) bad "branch is unexpected: $BR" ;; +esac # Phase 2: once the SSH alias is in use, prove the transport actually authenticates case "$REMOTE" in @@ -92,6 +106,26 @@ for d in mysqld mariadbd postgres redis-server; do if command -v "$d" >/dev/null 2>&1; then bad "$d present - unexpected"; else ok "$d absent (correct)"; fi done +echo +echo "==============================================================" +echo "GUARD: is master PROTECTED on the blog repo? (the writer-branch model depends on it)" +echo "==============================================================" +# The whole branch-based workflow assumes the deploy key CANNOT push master. That is a +# repo-side setting we cannot verify from here by inspection - so test it the way an +# attacker would: attempt a direct push to master and require it to be REJECTED. +if [ "${SKIP_MASTER_PUSH_TEST:-0}" = "1" ]; then + echo " SKIPPED (SKIP_MASTER_PUSH_TEST=1)" +else + PUSH_OUT=$(asuser "git -C $B push origin HEAD:master --dry-run" 2>&1) + if echo "$PUSH_OUT" | grep -qiE 'protected|not allowed|denied|forbidden|remote rejected'; then + ok "master is protected - the deploy key CANNOT push it" + else + bad "master is NOT protected - the deploy key could push master directly!" + echo " Enable it: armistace/blog -> Settings -> Branches -> add rule for 'master'," + echo " Enable push = OFF, merge whitelist = armistace. See docs/writer-branch-workflow.md" + fi +fi + echo echo "==============================================================" echo "FR-11 GUARD: agent created NO identity or armistace credential"