Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 16 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

Expand All @@ -19,40 +17,34 @@ jobs:
with:
node-version: "22"
- run: npm install -g @informalsystems/quint
- run: quint typecheck spec/docker_socket_policy.qnt
- run: quint run --max-steps=100 --invariants allInvariants --backend typescript spec/docker_socket_policy.qnt
- run: make typecheck
- run: make verify BACKEND=typescript

go:
runs-on: ubuntu-latest
defaults:
run:
working-directory: go
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
cache-dependency-path: go/go.sum
- run: go build ./...
- run: go test ./... -count=1
- run: go vet ./...
- run: make lint-go
- run: make test-go
- run: make build-go

rust:
runs-on: ubuntu-latest
defaults:
run:
working-directory: rs
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- run: cargo build --release
- run: cargo test
with:
toolchain: "1.85"
- run: make lint-rs
- run: make test-rs
- run: make build-rs

typescript:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ts
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -61,24 +53,22 @@ jobs:
cache: npm
cache-dependency-path: ts/package-lock.json
- run: npm ci
- run: npx tsc --noEmit
- run: npx tsc && node --test dist/*.test.js
- run: make lint-ts
- run: make test-ts
- run: make build-ts

integration:
runs-on: ubuntu-latest
needs: [go]
steps:
- uses: actions/checkout@v4
- run: make test-integration
- run: make test-integration-rs
- run: make test-integration-ts

reproducible-build:
runs-on: ubuntu-latest
needs: [go, rust, typescript]
steps:
- uses: actions/checkout@v4
- name: Verify Go reproducibility
run: make verify-reproducible-go
- name: Verify Rust reproducibility
run: make verify-reproducible-rs
- name: Verify TypeScript reproducibility
run: make verify-reproducible-ts
- run: make verify-reproducible-all
74 changes: 38 additions & 36 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,27 @@ permissions:
id-token: write

jobs:
release-verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: "1.85"
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: ts/package-lock.json
- run: npm ci
- name: Release verification gate
run: make release-verify

version:
needs: [release-verify]
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.bump.outputs.tag }}
Expand All @@ -36,48 +56,18 @@ jobs:
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag "${{ steps.bump.outputs.tag }}"
git push origin "${{ steps.bump.outputs.tag }}"
- name: Create draft release
- name: Create draft prerelease
run: |
gh release create "${{ steps.bump.outputs.tag }}" \
--title "${{ steps.bump.outputs.tag }}" \
--generate-notes \
--draft
--draft \
--prerelease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

validate:
needs: [version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Validate Go
run: |
cd go && go vet ./...
go test ./... -count=1
go build -o /dev/null .
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: "1.85"
- name: Validate Rust
run: |
cd rs && cargo test
cargo build --release
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: ts/package-lock.json
- name: Validate TypeScript
run: |
cd ts && npm ci
npm run build
node --test dist/*.test.js

release-go:
needs: [version, validate]
needs: [version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -146,7 +136,7 @@ jobs:
ghcr.io/chainsafe/docker-socket-policy-go:${{ needs.version.outputs.tag }}

release-rust:
needs: [version, validate]
needs: [version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -208,7 +198,7 @@ jobs:
ghcr.io/chainsafe/docker-socket-policy-rs:${{ needs.version.outputs.tag }}

release-ts:
needs: [version, validate]
needs: [version]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -276,3 +266,15 @@ jobs:
run: |
cosign sign --yes \
ghcr.io/chainsafe/docker-socket-policy-ts:${{ needs.version.outputs.tag }}

publish-release:
runs-on: ubuntu-latest
needs: [version, release-go, release-rust, release-ts]
steps:
- name: Publish release
run: |
gh release edit "${{ needs.version.outputs.tag }}" \
--draft=false \
--prerelease=false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ go/docker-socket-policy
# Dependencies
/quint-llm-kit/

# Internal planning docs
/docs/superpowers/

# TypeScript
ts/dist/
ts/node_modules/
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ deploy/ — Docker Compose + integration tests
- Zero external deps where possible (Go: yaml.v3, Rust: tokio/hyper/serde/clap, TS: yaml)

## Test Coverage
- Go: 58 unit tests (policy: 9, middleware: 21, proxy: 28)
- Rust: 104 unit tests (policy: 15, middleware: 48, proxy: 41)
- TypeScript: 80 unit tests (policy: 10, middleware: 37, proxy: 26, transport: 3, handler: 3)
- Go: 74 unit tests (policy: 10, middleware: 29, proxy: 31, audit: 4)
- Rust: 112 unit tests (policy: 15, middleware: 50, proxy: 37, handler: 4, audit: 4, transport: 2)
- TypeScript: 108 unit tests (policy: 10, middleware: 37, proxy: 26, transport: 5, handler: 6, flags: 16, audit: 4)
- 26 integration tests via deploy/test.sh + docker-compose

## Test Conventions
Expand Down
58 changes: 44 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ OUTPUT_DIR ?= .
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
QUINT ?= $(shell command -v quint 2>/dev/null || echo node $$HOME/.hermes/node/lib/node_modules/@informalsystems/quint/dist/src/cli.js)
SPEC ?= spec/docker_socket_policy.qnt
BACKEND ?=

.PHONY: build clean test lint verify typecheck validate
.PHONY: build clean test lint verify typecheck validate ci-verify release-verify
.PHONY: build-go test-go lint-go build-rs test-rs build-ts test-ts

# ─── Go ──────────────────────────────────────────────
Expand Down Expand Up @@ -66,34 +67,63 @@ typecheck:
$(QUINT) typecheck $(SPEC)

verify:
$(QUINT) run --max-steps=100 --invariants allInvariants $(SPEC)
if [ -n "$(BACKEND)" ]; then \
$(QUINT) run --max-steps=100 --invariants allInvariants --backend $(BACKEND) $(SPEC); \
else \
$(QUINT) run --max-steps=100 --invariants allInvariants $(SPEC); \
fi

verify-ts:
$(QUINT) run --max-steps=50 --invariants allInvariants --backend typescript $(SPEC)

ci-verify:
$(MAKE) typecheck
$(MAKE) verify BACKEND=typescript
$(MAKE) test-all
$(MAKE) test-integration
$(MAKE) verify-reproducible-all

release-verify:
$(MAKE) typecheck
$(MAKE) verify BACKEND=rust
$(MAKE) test-all
$(MAKE) test-integration
$(MAKE) verify-reproducible-all

# ─── Integration tests ───────────────────────────────

IMPL ?= go

test-integration:
docker compose -f deploy/docker-compose.yml down --remove-orphans -v 2>/dev/null; \
docker compose -f deploy/docker-compose.yml run --rm test; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.yml down --remove-orphans -v 2>/dev/null; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.yml run --build --rm test; \
rc=$$?; \
docker compose -f deploy/docker-compose.yml down --remove-orphans -v; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.yml down --remove-orphans -v; \
exit $$rc

test-integration-tcp:
docker compose -f deploy/docker-compose.tcp.yml down --remove-orphans -v 2>/dev/null; \
docker compose -f deploy/docker-compose.tcp.yml run --rm test; \
rc=$$?; \
docker compose -f deploy/docker-compose.tcp.yml down --remove-orphans -v; \
exit $$rc
test-integration-rs:
$(MAKE) test-integration IMPL=rs

test-integration-ts:
$(MAKE) test-integration IMPL=ts

# Unix-socket provisioning tests. The proxy only connects to the Docker
# daemon over a Unix socket — TCP would bypass user/group socket ownership,
# which is the security model this target exercises. Not run in CI (uses
# group-restricted socket setup); run locally per IMPL.
test-integration-sock:
docker compose -f deploy/docker-compose.sock.yml down --remove-orphans -v 2>/dev/null; \
docker compose -f deploy/docker-compose.sock.yml run --rm test; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.sock.yml down --remove-orphans -v 2>/dev/null; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.sock.yml run --build --rm test; \
rc=$$?; \
docker compose -f deploy/docker-compose.sock.yml down --remove-orphans -v; \
IMPL=$(IMPL) docker compose -f deploy/docker-compose.sock.yml down --remove-orphans -v; \
exit $$rc

test-integration-sock-rs:
$(MAKE) test-integration-sock IMPL=rs

test-integration-sock-ts:
$(MAKE) test-integration-sock IMPL=ts

validate: typecheck verify lint-go test-go

# ─── Reproducible build verification ─────────────────
Expand Down
6 changes: 4 additions & 2 deletions deploy/config/beacon.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
service_name: beacon
user_id: '2001'
group_id: '2001'
# Host systemd service account (must be a system-level user < 1000).
# The in-container user is set separately via container_config.user.
user_id: '100'
group_id: '100'

allowed_image_prefixes:
- chainsafe/lodestar
Expand Down
6 changes: 3 additions & 3 deletions deploy/docker-compose.sock.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: docker-socket-policy-test-sock
name: docker-socket-policy-test-sock-${IMPL:-go}

volumes:
sock-data:
Expand All @@ -20,7 +20,7 @@ services:

proxy-granted:
build:
context: ../go
context: ../${IMPL:-go}
dockerfile: Dockerfile
# User 65532 with GID 2001 — has group access to the restricted socket
user: 65532:2001
Expand All @@ -41,7 +41,7 @@ services:

proxy-denied:
build:
context: ../go
context: ../${IMPL:-go}
dockerfile: Dockerfile
# User 65532 with GID 3001 — NOT in dockertest group, should fail
user: 65532:3001
Expand Down
47 changes: 0 additions & 47 deletions deploy/docker-compose.tcp.yml

This file was deleted.

Loading
Loading