fix: use service account key for Cloud Run workspace provisioning

GCE metadata tokens lack the cloud-platform OAuth scope, causing 403
PERMISSION_DENIED when creating Cloud Run services. Use an explicit JWT
from GOOGLE_SERVICE_ACCOUNT_KEY env var when present, with ADC as fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-19 15:45:51 -08:00
parent aa2f5dbc3a
commit 68f844ce52

View File

@@ -10,7 +10,7 @@
* - Auth is enforced by our Vibn session before the URL is revealed
*/
import { GoogleAuth } from 'google-auth-library';
import { GoogleAuth, JWT } from 'google-auth-library';
const PROJECT_ID = 'master-ai-484822';
const REGION = 'northamerica-northeast1';
@@ -18,11 +18,28 @@ const IMAGE = `${REGION}-docker.pkg.dev/${PROJECT_ID}/vibn-ide/theia:latest
const VIBN_URL = process.env.NEXTAUTH_URL ?? 'https://vibnai.com';
const CLOUD_RUN_API = `https://run.googleapis.com/v2/projects/${PROJECT_ID}/locations/${REGION}/services`;
const SCOPES = ['https://www.googleapis.com/auth/cloud-platform'];
async function getAccessToken(): Promise<string> {
const auth = new GoogleAuth({
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
// Prefer an explicit service account key (avoids GCE metadata scope limitations)
const keyJson = process.env.GOOGLE_SERVICE_ACCOUNT_KEY;
if (keyJson) {
const key = JSON.parse(keyJson) as {
client_email: string;
private_key: string;
};
const jwt = new JWT({
email: key.client_email,
key: key.private_key,
scopes: SCOPES,
});
const token = await jwt.getAccessToken();
if (!token.token) throw new Error('Failed to get GCP access token from service account key');
return token.token;
}
// Fall back to ADC (works locally or on GCE with cloud-platform scope)
const auth = new GoogleAuth({ scopes: SCOPES });
const client = await auth.getClient();
const token = await client.getAccessToken();
if (!token.token) throw new Error('Failed to get GCP access token');