1
0
mirror of https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git synced 2026-11-03 01:13:24 +00:00
Files
SREDevOps.org Agent 1a929e3e24 fix(gateway)!: replace token cookies with revocable sessions and harden abuse controls (#40)
- Replace user:token cookies with opaque server-side sessions, revocable on logout, delete, recreate and expiry; bind every credential to the path user and add cross-user regression tests.
- Rate-limit /users and /login, add optional signup invite codes and form same-origin checks, and unify login failures to 401.
- Require explicit ALLOW_INSECURE_COOKIES for plain HTTP, use __Host-dsh_gw_session when secure, and fix secure cookie deletion.
- Strip client-supplied forwarding/SSO headers, add an optional upstream allowlist, per-user in-flight and WebSocket message caps, credential-free handshake errors, and sweep-time state pruning.
- Digest-pin base images, hash-pin gateway dependencies, verify DSH_COMMIT in the build, and run the gateway image as non-root with a pinned Python base.
- Update manifests, production checklist, architecture/security docs and add an SSO preflight script.

BREAKING CHANGE: existing dsh_gw_session=<user>:<token> cookies are invalid; users must sign in again. Unknown users on POST /login now return 401 instead of 404, and the gateway refuses COOKIE_SECURE=false unless ALLOW_INSECURE_COOKIES=1.

Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
2026-10-31 00:57:35 -03:00

287 lines
11 KiB
YAML

# Release pipeline. Pushing a tag that matches the identity in versions.env
# publishes both images (version + latest), creates the GitHub Release from
# git-cliff, and opens a PR that refreshes CHANGELOG.md on main.
#
# The tag must be dsh-vX.Y.Z or dsh-vX.Y.Z-rN and must match versions.env;
# tags are immutable, so a broken release is fixed with a new -rN revision.
name: Release
on:
push:
tags:
- "dsh-v*"
workflow_dispatch:
inputs:
tag:
description: Existing tag to release (must match versions.env)
required: true
type: string
# Read-only by default; the build and publish jobs add the write scopes they
# need as job-level grants.
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
meta:
name: Validate release identity
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
identity: ${{ steps.meta.outputs.identity }}
dsh_version: ${{ steps.meta.outputs.dsh_version }}
dsh_commit: ${{ steps.meta.outputs.dsh_commit }}
pnpm_version: ${{ steps.meta.outputs.pnpm_version }}
release_revision: ${{ steps.meta.outputs.release_revision }}
ghcr_image: ${{ steps.meta.outputs.ghcr_image }}
gateway_image: ${{ steps.meta.outputs.gateway_image }}
tag: ${{ steps.meta.outputs.tag }}
run_tests: ${{ steps.meta.outputs.run_tests }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Validate tag against versions.env
id: meta
shell: bash
env:
# Passed through the environment, never interpolated into the script:
# a tag name or dispatch input can contain shell metacharacters.
REQUESTED_TAG: ${{ inputs.tag || github.ref_name }}
run: |
set -euo pipefail
set -a
# shellcheck disable=SC1091
source versions.env
set +a
tag="$REQUESTED_TAG"
identity="$DSH_VERSION"
[ -z "$RELEASE_REVISION" ] || identity="$DSH_VERSION-$RELEASE_REVISION"
if [ "$tag" != "$identity" ]; then
echo "tag '$tag' does not match versions.env identity '$identity'" >&2
exit 1
fi
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
git fetch origin main '+refs/heads/release/*:refs/remotes/origin/release/*'
commit=$(git rev-list -n1 "refs/tags/$tag")
allowed=0
for ref in origin/main origin/release/*; do
if git rev-parse -q --verify "$ref" >/dev/null && git merge-base --is-ancestor "$commit" "$ref"; then
allowed=1
break
fi
done
if [ "$allowed" -ne 1 ]; then
echo "tag commit $commit is not on main or a release branch" >&2
exit 1
fi
# Tests already ran in PR CI when the tag is on main; only re-run
# them for release-branch tags (where ci.yaml does not trigger).
run_tests=true
if git rev-parse -q --verify origin/main >/dev/null && git merge-base --is-ancestor "$commit" origin/main; then
run_tests=false
fi
else
echo "tag '$tag' does not exist in this repository" >&2
exit 1
fi
if ! upstream="$(git ls-remote --tags --exit-code "$DSH_REPO" \
"refs/tags/$DSH_VERSION^{}" "refs/tags/$DSH_VERSION")"; then
echo "upstream ref '$DSH_VERSION' not found in $DSH_REPO" >&2
exit 1
fi
# Never release a ref that no longer resolves to the pinned commit: an
# annotated tag has a peeled ^{} line, a lightweight tag only the ref.
resolved="$(printf '%s\n' "$upstream" \
| awk -v t="refs/tags/$DSH_VERSION^{}" '$2 == t {print $1}' | head -n1)"
if [ -z "$resolved" ]; then
resolved="$(printf '%s\n' "$upstream" \
| awk -v t="refs/tags/$DSH_VERSION" '$2 == t {print $1}' | head -n1)"
fi
if [ "$resolved" != "$DSH_COMMIT" ]; then
echo "upstream $DSH_REPO@$DSH_VERSION resolved to '$resolved'," \
"versions.env pins DSH_COMMIT=$DSH_COMMIT" >&2
exit 1
fi
{
echo "identity=$identity"
echo "dsh_version=$DSH_VERSION"
echo "dsh_commit=$DSH_COMMIT"
echo "pnpm_version=$PNPM_VERSION"
echo "release_revision=$RELEASE_REVISION"
echo "ghcr_image=$GHCR_IMAGE"
echo "gateway_image=$GATEWAY_IMAGE"
echo "tag=$tag"
echo "run_tests=$run_tests"
} >> "$GITHUB_OUTPUT"
- name: Verify repository pins
run: ./scripts/check-versions.sh
tests:
name: Unit tests and lint
needs: meta
# The test steps are guarded individually rather than the whole job so a
# main-branch tag (run_tests=false) still leaves this job "successful" and
# does not cascade-skip build-main/build-gateway.
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: examples/dsh-agents-as-a-service/gateway
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python
if: needs.meta.outputs.run_tests == 'true'
uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.12"
cache: pip
cache-dependency-path: |
examples/dsh-agents-as-a-service/gateway/requirements.txt
examples/dsh-agents-as-a-service/gateway/requirements-dev.txt
- name: Install dependencies
if: needs.meta.outputs.run_tests == 'true'
run: |
set -euo pipefail
python -m pip install --upgrade pip
pip install --require-hashes -r requirements.txt -r requirements-dev.txt
- name: Lint
if: needs.meta.outputs.run_tests == 'true'
run: |
set -euo pipefail
python -m ruff check .
python -m ruff format --check .
- name: Unit tests
if: needs.meta.outputs.run_tests == 'true'
run: python -m pytest -q
build-main:
name: Publish main image
needs: [meta, tests]
uses: ./.github/workflows/_build-image.yaml
permissions:
contents: read
packages: write
id-token: write
attestations: write
with:
image: ${{ needs.meta.outputs.ghcr_image }}
version: ${{ needs.meta.outputs.identity }}
context: .
dockerfile: Dockerfile
build-args: |
DSH_VERSION=${{ needs.meta.outputs.dsh_version }}
DSH_COMMIT=${{ needs.meta.outputs.dsh_commit }}
RELEASE_REVISION=${{ needs.meta.outputs.release_revision }}
PNPM_VERSION=${{ needs.meta.outputs.pnpm_version }}
VCS_REF=${{ github.sha }}
tags: |
${{ needs.meta.outputs.ghcr_image }}:${{ needs.meta.outputs.identity }}
${{ needs.meta.outputs.ghcr_image }}:latest
build-gateway:
name: Publish gateway image
needs: [meta, tests]
uses: ./.github/workflows/_build-image.yaml
permissions:
contents: read
packages: write
id-token: write
attestations: write
with:
image: ${{ needs.meta.outputs.gateway_image }}
version: ${{ needs.meta.outputs.identity }}
context: examples/dsh-agents-as-a-service/gateway
dockerfile: Dockerfile
tags: |
${{ needs.meta.outputs.gateway_image }}:${{ needs.meta.outputs.identity }}
${{ needs.meta.outputs.gateway_image }}:latest
publish-release:
name: Changelog and GitHub Release
needs: [meta, build-main, build-gateway]
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Install git-cliff
env:
GIT_CLIFF_VERSION: v2.14.2
# SHA-256 of git-cliff-2.14.2-x86_64-unknown-linux-gnu.tar.gz; upstream
# publishes the matching SHA-512 next to the asset. Update with the version.
GIT_CLIFF_SHA256: 24f397c733add5390fdceee3a2088588ab0d5f944ce00d34cb7029b888cf2db4
run: |
set -euo pipefail
version="${GIT_CLIFF_VERSION#v}"
asset="git-cliff-${version}-x86_64-unknown-linux-gnu.tar.gz"
curl -fsSL --proto '=https' -o "/tmp/$asset" \
"https://github.com/orhun/git-cliff/releases/download/$GIT_CLIFF_VERSION/$asset"
printf '%s %s\n' "$GIT_CLIFF_SHA256" "/tmp/$asset" | sha256sum -c -
tar -xzf "/tmp/$asset" -C /tmp
install -m 0755 "/tmp/git-cliff-$version/git-cliff" /usr/local/bin/git-cliff
git-cliff --version
- name: Generate CHANGELOG and release notes
env:
IDENTITY: ${{ needs.meta.outputs.identity }}
run: |
set -euo pipefail
git-cliff --tag "$IDENTITY" --output CHANGELOG.md
git-cliff --tag "$IDENTITY" --latest --strip header --output /tmp/release-notes.md
echo "### Release $IDENTITY" >> "$GITHUB_STEP_SUMMARY"
head -n 40 /tmp/release-notes.md >> "$GITHUB_STEP_SUMMARY"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IDENTITY: ${{ needs.meta.outputs.identity }}
run: |
set -euo pipefail
if gh release view "$IDENTITY" >/dev/null 2>&1; then
echo "release $IDENTITY already exists; skipping" >&2
else
gh release create "$IDENTITY" --title "$IDENTITY" --notes-file /tmp/release-notes.md --verify-tag
fi
- name: Open CHANGELOG pull request
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IDENTITY: ${{ needs.meta.outputs.identity }}
continue-on-error: true
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if git diff --quiet -- CHANGELOG.md; then
echo "CHANGELOG.md already up to date"
exit 0
fi
branch="chore/changelog-$IDENTITY"
git switch -c "$branch"
git add CHANGELOG.md
git commit -m "chore(changelog): refresh for $IDENTITY"
git push origin "$branch"
gh pr create \
--base main \
--head "$branch" \
--title "chore(changelog): refresh for $IDENTITY" \
--body "Generated by git-cliff for $IDENTITY. Do not edit CHANGELOG.md by hand."