Skip to content

Commit 0e169b9

Browse files
authored
Merge pull request #1452 from Dstack-TEE/feat/auth-eth-bun-0.6
kms: refresh auth-eth-bun for 0.6 and publish its image from CI
2 parents ce2e369 + 895f785 commit 0e169b9

9 files changed

Lines changed: 486 additions & 194 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# SPDX-FileCopyrightText: © 2026 Phala Network <dstack@phala.network>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: KMS auth-eth-bun
6+
7+
# The auth-eth-bun webhook ships on its own cadence, separate from the KMS
8+
# image: a `kms-auth-eth-bun-v*` tag publishes
9+
# ghcr.io/dstack-tee/dstack-kms-auth-eth-bun:<version>. Pull requests and
10+
# pushes that touch the backend run the checks and build the image without
11+
# pushing it.
12+
on:
13+
workflow_dispatch:
14+
inputs:
15+
version:
16+
description: Existing release tag version without the kms-auth-eth-bun-v prefix
17+
required: true
18+
type: string
19+
push:
20+
branches: [ next, 'release/**' ]
21+
tags:
22+
- 'kms-auth-eth-bun-v*'
23+
paths:
24+
- 'dstack/kms/auth-eth-bun/**'
25+
- '.github/workflows/kms-auth-eth-bun.yml'
26+
pull_request:
27+
branches: [ next, 'release/**' ]
28+
paths:
29+
- 'dstack/kms/auth-eth-bun/**'
30+
- '.github/workflows/kms-auth-eth-bun.yml'
31+
32+
permissions:
33+
contents: read
34+
35+
env:
36+
IMAGE: ghcr.io/dstack-tee/dstack-kms-auth-eth-bun
37+
BACKEND_DIR: dstack/kms/auth-eth-bun
38+
39+
jobs:
40+
check:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- name: Checkout repository
44+
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
45+
with:
46+
ref: ${{ github.event_name == 'workflow_dispatch' && format('kms-auth-eth-bun-v{0}', inputs.version) || github.sha }}
47+
persist-credentials: false
48+
49+
- name: Set up Bun
50+
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
51+
with:
52+
# Keep in step with the base image in the Dockerfile.
53+
bun-version: 1.4.2
54+
# A release build must not restore a cache an untrusted run wrote.
55+
no-cache: true
56+
57+
- name: Install dependencies
58+
working-directory: ${{ env.BACKEND_DIR }}
59+
run: bun install --frozen-lockfile
60+
61+
- name: Audit dependencies
62+
working-directory: ${{ env.BACKEND_DIR }}
63+
run: bun audit --audit-level=moderate
64+
65+
- name: Lint
66+
working-directory: ${{ env.BACKEND_DIR }}
67+
run: bun run lint
68+
69+
- name: Test
70+
working-directory: ${{ env.BACKEND_DIR }}
71+
run: bun run test:run
72+
73+
image:
74+
needs: check
75+
runs-on: ubuntu-latest
76+
permissions:
77+
contents: read
78+
packages: write
79+
attestations: write
80+
id-token: write
81+
steps:
82+
- name: Decide whether to publish
83+
env:
84+
DISPATCH_VERSION: ${{ inputs.version }}
85+
run: |
86+
VERSION=
87+
if [ "$GITHUB_EVENT_NAME" = workflow_dispatch ]; then
88+
VERSION=$DISPATCH_VERSION
89+
else
90+
case "$GITHUB_REF" in
91+
refs/tags/kms-auth-eth-bun-v*) VERSION=${GITHUB_REF#refs/tags/kms-auth-eth-bun-v} ;;
92+
esac
93+
fi
94+
if [ -n "$VERSION" ]; then
95+
if [[ ! "$VERSION" =~ ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$ ]]; then
96+
echo "version must be a valid Docker tag" >&2
97+
exit 1
98+
fi
99+
echo "PUBLISH=1" >> "$GITHUB_ENV"
100+
echo "IMAGE_REF=$IMAGE:$VERSION" >> "$GITHUB_ENV"
101+
else
102+
echo "PUBLISH=" >> "$GITHUB_ENV"
103+
echo "IMAGE_REF=$IMAGE:check" >> "$GITHUB_ENV"
104+
fi
105+
106+
# Manual runs rebuild an existing release tag, not the selected branch.
107+
- name: Checkout repository
108+
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
109+
with:
110+
ref: ${{ github.event_name == 'workflow_dispatch' && format('kms-auth-eth-bun-v{0}', inputs.version) || github.sha }}
111+
persist-credentials: false
112+
113+
- name: Resolve the revision to build
114+
run: echo "GIT_REV=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
115+
116+
- name: Log in to GitHub Container Registry
117+
if: env.PUBLISH == '1'
118+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
119+
with:
120+
registry: ghcr.io
121+
username: ${{ github.actor }}
122+
password: ${{ secrets.GITHUB_TOKEN }}
123+
124+
- name: Set up Docker Buildx
125+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
126+
127+
- name: Build and push Docker image
128+
id: build
129+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
130+
with:
131+
context: ${{ env.BACKEND_DIR }}
132+
platforms: linux/amd64
133+
push: ${{ env.PUBLISH == '1' }}
134+
provenance: false
135+
tags: ${{ env.IMAGE_REF }}
136+
build-args: |
137+
GIT_REV=${{ env.GIT_REV }}
138+
labels: |
139+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
140+
org.opencontainers.image.revision=${{ env.GIT_REV }}
141+
org.opencontainers.image.description=dstack KMS auth webhook backed by the DstackKms contract
142+
143+
- name: Verify anonymous pull access
144+
if: env.PUBLISH == '1'
145+
env:
146+
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
147+
run: |
148+
token=$(curl -fsSL \
149+
"https://ghcr.io/token?scope=repository:dstack-tee/dstack-kms-auth-eth-bun:pull" \
150+
| jq -er .token)
151+
curl -fsSL -o /dev/null \
152+
-H "Authorization: Bearer $token" \
153+
-H "Accept: application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json" \
154+
"https://ghcr.io/v2/dstack-tee/dstack-kms-auth-eth-bun/manifests/$IMAGE_DIGEST"
155+
156+
- name: Generate artifact attestation
157+
if: env.PUBLISH == '1'
158+
uses: actions/attest-build-provenance@92c65d2898f1f53cfdc910b962cecff86e7f8fcc # v1
159+
with:
160+
subject-name: ${{ env.IMAGE }}
161+
subject-digest: ${{ steps.build.outputs.digest }}
162+
push-to-registry: true
163+
164+
- name: Summarize
165+
if: env.PUBLISH == '1'
166+
env:
167+
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
168+
run: |
169+
{
170+
echo "**Image**: \`$IMAGE_REF\`"
171+
echo
172+
echo "**Pinned**: \`$IMAGE@$IMAGE_DIGEST\`"
173+
echo
174+
echo "**Revision**: \`$GIT_REV\`"
175+
} >> "$GITHUB_STEP_SUMMARY"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-FileCopyrightText: © 2026 Phala Network <dstack@phala.network>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
*
6+
!package.json
7+
!bun.lock
8+
!index.ts

‎dstack/kms/auth-eth-bun/.oxlintrc.json‎

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
11
{
2-
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/crates/oxc_linter/src/config/schema.json",
3-
"rules": {
4-
"typescript": "warn",
5-
"unicorn": "warn",
6-
"react": "off",
7-
"jsx-a11y": "off",
8-
"nextjs": "off"
9-
},
2+
"$schema": "./node_modules/oxlint/configuration_schema.json",
3+
"plugins": ["typescript", "unicorn"],
104
"env": {
115
"node": true,
126
"es2022": true
137
},
14-
"globals": {
15-
"globalThis": "readonly",
16-
"console": "readonly"
17-
},
18-
"ignore_patterns": [
8+
"ignorePatterns": [
199
"node_modules/**",
2010
"dist/**",
2111
"build/**",

‎dstack/kms/auth-eth-bun/Dockerfile‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-FileCopyrightText: © 2026 Phala Network <dstack@phala.network>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Built from this directory, so the image carries exactly the checked-out
6+
# source and lockfile rather than a clone fetched at build time.
7+
FROM oven/bun:1.4.2-alpine@sha256:d888c0ae6c86d7866ff10c5aafdd9077b36aee6455b33dd270fb93c0dd5cef6f AS deps
8+
WORKDIR /app
9+
COPY package.json bun.lock ./
10+
RUN bun install --frozen-lockfile --production --ignore-scripts
11+
12+
FROM oven/bun:1.4.2-alpine@sha256:d888c0ae6c86d7866ff10c5aafdd9077b36aee6455b33dd270fb93c0dd5cef6f
13+
WORKDIR /app
14+
COPY --from=deps /app/node_modules ./node_modules
15+
COPY package.json index.ts ./
16+
ARG GIT_REV=unknown
17+
LABEL org.opencontainers.image.revision="${GIT_REV}"
18+
ENV NODE_ENV=production
19+
# The KMS webhook default (`kms.toml`) is http://auth-api:8000.
20+
ENV PORT=8000
21+
EXPOSE 8000
22+
USER bun
23+
CMD ["bun", "index.ts"]

‎dstack/kms/auth-eth-bun/README.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,33 @@ bun run check
6868

6969
The Bun server sets `idleTimeout` to 255s (Bun's maximum). Bun's default of 10s closes the socket while a slow `eth_call` is still in flight, which surfaces on the KMS side as `connection closed before message completed`.
7070

71+
## container image
72+
73+
tagged releases are published by the `KMS auth-eth-bun` workflow
74+
(`.github/workflows/kms-auth-eth-bun.yml`): pushing the tag
75+
`kms-auth-eth-bun-v<version>` builds this directory and publishes
76+
`ghcr.io/dstack-tee/dstack-kms-auth-eth-bun:<version>` with a build provenance
77+
attestation. pull requests that touch this directory run the audit, lint and
78+
tests and build the image without pushing it.
79+
80+
the image listens on port 8000, which matches the KMS webhook default
81+
`http://auth-api:8000`. deploy it by digest:
82+
83+
```yaml
84+
auth-api:
85+
image: ghcr.io/dstack-tee/dstack-kms-auth-eth-bun:<version>@sha256:<digest>
86+
environment:
87+
- ETH_RPC_URL=https://...
88+
- KMS_CONTRACT_ADDR=0x...
89+
- ETH_CHAIN_ID=8453
90+
```
91+
92+
to build it locally:
93+
94+
```bash
95+
docker build -t dstack-kms-auth-eth-bun .
96+
```
97+
7198
## API endpoints
7299

73100
### GET /
@@ -114,6 +141,14 @@ this implementation is fully compatible with the original fastify + ethers versi
114141
- **comprehensive testing**: vitest test suite validates compatibility
115142
- **backward compatibility**: supports both minimal and full BootInfo formats
116143

144+
### dstack-kms 0.6
145+
146+
dstack-kms 0.6 posts `dstack_verifier::PolicyBootInfo`: bytes as unprefixed
147+
hex, plus `teeVariant` and `keyProviderInfo`, which the contract does not take
148+
and this backend drops. the KMS checks `appId`, `composeHash` and `instanceId`
149+
widths itself before calling the webhook. the `dstack-kms 0.6 bootAuth payload`
150+
tests pin this contract.
151+
117152
### OpenAPI specification
118153

119154
the complete API specification is available in `openapi.json` and includes:

0 commit comments

Comments
 (0)