Harden CI runner and release gate security (#320)
## Summary - run untrusted pull-request jobs on ephemeral `ubuntu-24.04` runners - reserve the local backend runner pool for trusted branch pushes - remove world-writable Docker-socket fallbacks - pin core GitHub Actions and disable checkout credential persistence - remove the release-manager PHP parse-error fail-open path ## Why Pull-request code previously ran on persistent self-hosted runners with Docker access, and CI contained permission weakening and a release-gate break-glass success path. Those behaviors were unsafe for autonomous intake. ## Validation - workflow YAML parsed - backend AI workflow outputs are in sync - pinned action SHAs match the current v4 tags - `git diff --check` ## Risk and activation This is an R4 CI/release-policy change. Keep the PR draft for human review and let required CI prove the hosted-runner path before merge.
This commit is contained in:
+35
-49
@@ -19,7 +19,9 @@ concurrency:
|
||||
jobs:
|
||||
php:
|
||||
name: PHP ${{ matrix.suite }} (required)
|
||||
runs-on: [self-hosted, Linux, X64, pleno, backend, docker]
|
||||
# Pull requests are untrusted and must use an ephemeral GitHub-hosted runner.
|
||||
# Trusted branch pushes may use the local backend pool for throughput.
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-24.04' || 'backend' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -29,25 +31,21 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Ensure Docker access
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if docker ps >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
test -S /var/run/docker.sock || (echo "Docker socket is not available." >&2; exit 1)
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
sudo -n chmod 666 /var/run/docker.sock
|
||||
else
|
||||
chmod 666 /var/run/docker.sock
|
||||
fi
|
||||
docker ps >/dev/null
|
||||
docker ps >/dev/null 2>&1 || {
|
||||
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Setup Node.js
|
||||
if: ${{ matrix.suite == 'unit' }}
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -61,7 +59,7 @@ jobs:
|
||||
- name: Upload PHP suite logs
|
||||
if: ${{ failure() }}
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: php-${{ matrix.suite }}-logs
|
||||
path: .tmp/ci-logs/${{ matrix.suite }}
|
||||
@@ -70,14 +68,16 @@ jobs:
|
||||
|
||||
edge-agent:
|
||||
name: Edge Agent (required)
|
||||
runs-on: [self-hosted, Linux, X64, pleno, backend]
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-24.04' || 'backend' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -115,25 +115,21 @@ jobs:
|
||||
|
||||
edge-broker:
|
||||
name: Edge Broker (required)
|
||||
runs-on: [self-hosted, Linux, X64, pleno, backend, docker]
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-24.04' || 'backend' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Ensure Docker access
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if docker ps >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
test -S /var/run/docker.sock || (echo "Docker socket is not available." >&2; exit 1)
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
sudo -n chmod 666 /var/run/docker.sock
|
||||
else
|
||||
chmod 666 /var/run/docker.sock
|
||||
fi
|
||||
docker ps >/dev/null
|
||||
docker ps >/dev/null 2>&1 || {
|
||||
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Materialize CI compose env files
|
||||
run: |
|
||||
@@ -147,7 +143,7 @@ jobs:
|
||||
docker compose -f docker-compose.example.yml config > /dev/null
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -161,7 +157,7 @@ jobs:
|
||||
|
||||
edge-gateway-backend:
|
||||
name: Edge Gateway Backend (required)
|
||||
runs-on: [self-hosted, Linux, X64, pleno, backend, docker]
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-24.04' || 'backend' }}
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml:.github/docker-compose.ci.yml
|
||||
COMPOSE_PROJECT_NAME: edge-gateway-backend-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
@@ -175,21 +171,17 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Ensure Docker access
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if docker ps >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
test -S /var/run/docker.sock || (echo "Docker socket is not available." >&2; exit 1)
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
sudo -n chmod 666 /var/run/docker.sock
|
||||
else
|
||||
chmod 666 /var/run/docker.sock
|
||||
fi
|
||||
docker ps >/dev/null
|
||||
docker ps >/dev/null 2>&1 || {
|
||||
echo "Docker is unavailable to the runner identity. Fix the isolated runner configuration; the workflow will not weaken /var/run/docker.sock permissions." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Allocate CI ports
|
||||
run: |
|
||||
@@ -240,7 +232,7 @@ jobs:
|
||||
printf '\nEDGE_PUBLIC_BROKER_URL=http://edge-broker:4300/edge-broker\n' >> .env
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
@@ -411,12 +403,6 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if printf '%s' "$response_body" | grep -qi '<b>Parse error</b>'; then
|
||||
echo "::warning::Release Manager API returned a PHP parse error while recording the gate. Treating this as a break-glass pass so a fix can be deployed."
|
||||
printf '%s\n' "$response_body"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "$response_body"
|
||||
echo "Release Manager gate failed with HTTP $http_code." >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user