Skip to content

Commit 463651b

Browse files
authored
Merge pull request #724 from runtimed/dev/jroberts/projects-artifacts
Dev/jroberts/projects artifacts
2 parents 77a4e87 + 54389eb commit 463651b

45 files changed

Lines changed: 1830 additions & 168 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dev.vars.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This is an example file for local Worker development.
22
# Copy this file to .dev.vars and fill in the values.
33
# This file SHOULD NOT contain real production secrets.
4-
AUTH_ISSUER="http://localhost:8787/local_oidc"
4+
AUTH_ISSUER="https://auth.stage.anaconda.com/api/auth"
55

66
# Local authentication control
77
# Set to "true" to enable local OIDC endpoints for development
@@ -19,3 +19,8 @@ ALLOW_LOCAL_AUTH="true"
1919
# - VITE_CLIENT_ID: Your OAuth client ID
2020
#
2121
# The backend expects RS256 JWT tokens from the OIDC provider.
22+
23+
# Cloudflare Access headers for service-to-service authentication with Projects service
24+
# These are optional - only needed if you want to test Cloudflare Access authentication locally
25+
# CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID="your-client-id"
26+
# CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET="your-client-secret"

.github/workflows/.deploy-reusable.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ on:
2222
required: true
2323
CLOUDFLARE_ACCOUNT_ID:
2424
required: true
25+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID:
26+
required: false
27+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET:
28+
required: false
2529

2630
jobs:
2731
deploy:
@@ -78,6 +82,7 @@ jobs:
7882
VITE_GIT_COMMIT_HASH: ${{ github.sha }}
7983
VITE_LS_DEV: "true"
8084
ENABLE_LIVESTORE_DEVTOOLS: ${{ vars.ENABLE_LIVESTORE_DEVTOOLS }}
85+
VITE_USE_PROJECTS_ARTIFACTS: ${{ vars.VITE_USE_PROJECTS_ARTIFACTS }}
8186

8287
- name: Build iframe outputs
8388
run: pnpm run build:iframe
@@ -99,6 +104,24 @@ jobs:
99104
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
100105
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
101106

107+
- name: Set Cloudflare service token secrets from GitHub
108+
# Set secrets in Cloudflare Workers from GitHub environment secrets
109+
# This approach is compatible with future Kubernetes deployment where
110+
# these would be set as environment variables in the pod/deployment
111+
run: |
112+
if [ -n "$CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID" ] && [ -n "$CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET" ]; then
113+
echo "Setting Cloudflare service token secrets from GitHub environment secrets..."
114+
echo "$CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID" | pnpm wrangler secret put CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID --env ${{ inputs.environment }}
115+
echo "$CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET" | pnpm wrangler secret put CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET --env ${{ inputs.environment }}
116+
else
117+
echo "Cloudflare service token secrets not provided in GitHub environment, skipping..."
118+
fi
119+
env:
120+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
121+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
122+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID }}
123+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET }}
124+
102125
- name: Deploy base app (with retry)
103126
run: |
104127
# Retry deployment up to 3 times with exponential backoff

.github/workflows/auto-deploy-preview.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ jobs:
1414
secrets:
1515
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
1616
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
17+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID }}
18+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET }}

.github/workflows/deploy-preview-manually.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ jobs:
2020
secrets:
2121
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
2222
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
23+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID }}
24+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET }}

.github/workflows/deploy-production.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ jobs:
3737
secrets:
3838
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
3939
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
40+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID }}
41+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET }}

.github/workflows/validate-preview.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ jobs:
1414
secrets:
1515
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
1616
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
17+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_ID }}
18+
CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET: ${{ secrets.CLOUDFLARE_SERVICE_TOKEN_CLIENT_SECRET }}

backend/api-key-routes.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Hono } from "hono";
22
import { type Env } from "./types.ts";
3-
import { authMiddleware, type AuthContext } from "./middleware.ts";
3+
import { authMiddleware, type RequestContext } from "./middleware.ts";
44
import {
55
createApiKeyProvider,
66
isUsingLocalProvider,
@@ -16,8 +16,9 @@ import {
1616
import { RuntError, ErrorType } from "./types.ts";
1717
import { D1Driver } from "@japikey/cloudflare";
1818
import { JSONWebKeySet } from "jose";
19+
import { getBearerToken } from "./utils/request-utils.ts";
1920

20-
const apiKeyRoutes = new Hono<{ Bindings: Env; Variables: AuthContext }>();
21+
const apiKeyRoutes = new Hono<{ Bindings: Env; Variables: RequestContext }>();
2122

2223
/**
2324
* Middleware to ensure OAuth authentication (not API key) for sensitive operations
@@ -38,7 +39,7 @@ const oauthOnlyMiddleware = async (c: any, next: any) => {
3839
}
3940

4041
// Check if this was authenticated via API key
41-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
42+
const authToken = getBearerToken(c.req);
4243
if (authToken) {
4344
const provider = createApiKeyProvider(c.env);
4445
const providerContext = createProviderContext(c.env, authToken);
@@ -85,7 +86,7 @@ apiKeyRoutes.get("/:kid/.well-known/jwks.json", async (c) => {
8586
*/
8687
apiKeyRoutes.post("/", oauthOnlyMiddleware, async (c) => {
8788
const passport = c.get("passport");
88-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
89+
const authToken = getBearerToken(c.req);
8990

9091
if (!passport || !authToken) {
9192
return c.json(
@@ -138,7 +139,7 @@ apiKeyRoutes.post("/", oauthOnlyMiddleware, async (c) => {
138139
apiKeyRoutes.get("/:id", authMiddleware, async (c) => {
139140
const keyId = c.req.param("id");
140141
const passport = c.get("passport");
141-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
142+
const authToken = getBearerToken(c.req);
142143

143144
if (!passport || !authToken) {
144145
return c.json(
@@ -193,7 +194,7 @@ apiKeyRoutes.get("/:id", authMiddleware, async (c) => {
193194
*/
194195
apiKeyRoutes.get("/", authMiddleware, async (c) => {
195196
const passport = c.get("passport");
196-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
197+
const authToken = getBearerToken(c.req);
197198

198199
if (!passport || !authToken) {
199200
return c.json(
@@ -271,7 +272,7 @@ apiKeyRoutes.get("/", authMiddleware, async (c) => {
271272
apiKeyRoutes.delete("/:id", authMiddleware, async (c) => {
272273
const keyId = c.req.param("id");
273274
const passport = c.get("passport");
274-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
275+
const authToken = getBearerToken(c.req);
275276

276277
if (!passport || !authToken) {
277278
return c.json(
@@ -335,7 +336,7 @@ apiKeyRoutes.delete("/:id", authMiddleware, async (c) => {
335336
apiKeyRoutes.patch("/:id", authMiddleware, async (c) => {
336337
const keyId = c.req.param("id");
337338
const passport = c.get("passport");
338-
const authToken = c.req.header("Authorization")?.replace("Bearer ", "");
339+
const authToken = getBearerToken(c.req);
339340

340341
if (!passport || !authToken) {
341342
return c.json(

0 commit comments

Comments
 (0)