Skip to content

Commit e95fca7

Browse files
dkrai04claude
andauthored
Firebase credential rotation (#520)
* chore: rotate Firebase credentials for security - Add Firebase credential rotation documentation - Add automated rotation scripts (rotate, verify, cleanup) - Update .gitignore to exclude sensitive Firebase key files - New service account: blend-firebase-10281134 Security incident: Firebase credentials were exposed in DEPLOYMENT.md commit history. This rotation addresses the exposure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: update cloudbuild.yaml with new Firebase credentials and Docker path * fix: update Dockerfile to use pnpm and new Firebase credentials * fix: correct standalone output paths in Dockerfile * docs: document completed Firebase credential rotation * chore: remove credential rotation helper scripts after successful rotation - Removed rotate-credentials.sh (rotation complete) - Removed verify-deployment.sh (verification complete) - Removed cleanup-old-credentials.sh (cleanup complete) - Updated FIREBASE_CREDENTIAL_ROTATION.md with final status - Keep only documentation for future reference * chore(security): implement comprehensive credential security improvements Priority 1: Remove Hardcoded Credentials - Update .gitignore to explicitly exclude .env.local and .env.production - Add patterns for firebase-*.json and credentials*.json - Create .env.example template with placeholder values and setup instructions - Remove hardcoded database password from .env files (use Secret Manager) - Remove hardcoded Firebase private key from .env files (use Secret Manager) Priority 2: Update Firebase References - Updated .env.local and .env.production with new Firebase App ID - Updated to new service account: blend-firebase-10281134 - Added instructions for fetching secrets from Secret Manager Priority 3: Dockerfile Security - Replace hardcoded ENV values with ARG build arguments - Update cloudbuild.yaml to pass Firebase config as build arguments - Enable flexible configuration without hardcoding in Dockerfile Security Improvements: - Database password now comes from Secret Manager (not hardcoded) - Firebase private key now comes from Secret Manager (not hardcoded) - .env files are properly excluded from git tracking - Template file (.env.example) provided for local development setup - Build-time configuration uses arguments for flexibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: remove Firebase credential rotation documentation - Removed FIREBASE_CREDENTIAL_ROTATION.md after successful rotation - All security improvements are complete and verified - Credentials successfully rotated and tested in production 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add local setup guide for blend-monitor - Add LOCAL_SETUP.md with step-by-step instructions - Add cloud_sql_proxy to .gitignore to prevent binary commits - Include troubleshooting section for common issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4299564 commit e95fca7

File tree

6 files changed

+271
-28
lines changed

6 files changed

+271
-28
lines changed

.gcloudignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Exclude node_modules and build artifacts
2+
node_modules/
3+
**/node_modules/
4+
.next/
5+
**/.next/
6+
dist/
7+
**/dist/
8+
.turbo/
9+
**/.turbo/
10+
storybook-static/
11+
12+
# Exclude git and IDE files
13+
.git/
14+
.vscode/
15+
.idea/
16+
17+
# Exclude other apps source (but keep package.json for dependencies)
18+
apps/ascent/app/**
19+
apps/ascent/public/**
20+
apps/site/src/**
21+
apps/site/public/**
22+
apps/storybook/stories/**
23+
apps/storybook/.storybook/**
24+
25+
# Exclude test and documentation files
26+
**/*.test.ts
27+
**/*.test.tsx
28+
**/*.spec.ts
29+
**/*.spec.tsx
30+
**/README.md
31+
**/.DS_Store

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,20 @@ next-env.d.ts
4141
!.env.example
4242
!.env.template
4343
.env.local
44+
.env.production
4445
.env.development.local
4546
.env.test.local
4647
.env.production.local
4748
.env.staging
4849
.env.dev
4950
.env.prod
5051

52+
# Sensitive credentials (extra safety)
53+
**/.env.local
54+
**/.env.production
55+
**/firebase-*.json
56+
**/credentials*.json
57+
5158
# OS files
5259
.DS_Store
5360
.DS_Store?
@@ -155,6 +162,12 @@ coverage/
155162
# Firebase
156163
.firebase/
157164
.firebaserc.local
165+
firebase-*-key*.json
166+
firebase-*-private-key.txt
167+
168+
# Cloud SQL Proxy binary
169+
**/cloud_sql_proxy
170+
cloud_sql_proxy
158171

159172
# Build outputs
160173
dist/

apps/blend-monitor/.env.example

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# ===================================
2+
# Blend Monitor - Environment Variables Template
3+
# ===================================
4+
# Copy this file to .env.local for local development
5+
# Replace placeholder values with actual credentials
6+
# NEVER commit .env.local or .env.production to git!
7+
# ===================================
8+
9+
# ===================================
10+
# Firebase Client Configuration (Public - Safe to expose in frontend)
11+
# ===================================
12+
NEXT_PUBLIC_FIREBASE_API_KEY=your-firebase-api-key-here
13+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com
14+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
15+
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project-id.firebasestorage.app
16+
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
17+
NEXT_PUBLIC_FIREBASE_APP_ID=1:your-sender-id:web:your-app-id
18+
NEXT_PUBLIC_FIREBASE_DATABASE_URL=https://your-project-id-default-rtdb.region.firebasedatabase.app
19+
20+
# ===================================
21+
# Firebase Admin Configuration (Private - Server-side only)
22+
# ===================================
23+
FIREBASE_PROJECT_ID=your-project-id
24+
FIREBASE_DATABASE_URL=https://your-project-id-default-rtdb.region.firebasedatabase.app
25+
FIREBASE_CLIENT_EMAIL=your-service-account@your-project-id.iam.gserviceaccount.com
26+
# FIREBASE_PRIVATE_KEY should come from Secret Manager in production
27+
# For local development, use Cloud SQL Proxy and Secret Manager
28+
# DO NOT hardcode the private key here!
29+
30+
# ===================================
31+
# Database Configuration (Local Development via Cloud SQL Proxy)
32+
# ===================================
33+
DATABASE_HOST=localhost
34+
DATABASE_PORT=5433
35+
DATABASE_NAME=blend_monitor
36+
DATABASE_USER=admin
37+
# DATABASE_PASSWORD should come from Secret Manager
38+
# For local development:
39+
# 1. Start Cloud SQL Proxy: ./cloud_sql_proxy -instances=PROJECT:REGION:INSTANCE=tcp:5433
40+
# 2. Set password from Secret Manager: gcloud secrets versions access latest --secret="blend-monitor-db-password"
41+
# DO NOT hardcode the password here!
42+
43+
# Database URL (constructed from above values)
44+
# DATABASE_URL=postgresql://admin:PASSWORD_FROM_SECRET_MANAGER@localhost:5433/blend_monitor
45+
46+
# ===================================
47+
# Application Settings
48+
# ===================================
49+
NODE_ENV=development
50+
51+
# ===================================
52+
# Production Configuration
53+
# ===================================
54+
# In production (Cloud Run), these are set via:
55+
# - Environment variables in cloudbuild.yaml
56+
# - Secrets from Secret Manager
57+
# - Cloud SQL Unix socket connection
58+
#
59+
# DO NOT use .env files in production!
60+
# All sensitive values MUST come from Secret Manager
61+
#
62+
# Production secrets:
63+
# - DATABASE_PASSWORD → blend-monitor-db-password (Secret Manager)
64+
# - FIREBASE_PRIVATE_KEY → blend-monitor-firebase-key (Secret Manager)
65+
# ===================================
66+
67+
# ===================================
68+
# Local Development Setup Instructions
69+
# ===================================
70+
# 1. Copy this file: cp .env.example .env.local
71+
# 2. Get Firebase config from Firebase Console
72+
# 3. Set up Cloud SQL Proxy for database access
73+
# 4. Get database password from Secret Manager:
74+
# gcloud secrets versions access latest --secret="blend-monitor-db-password" --project=PROJECT_ID
75+
# 5. Get Firebase private key from Secret Manager:
76+
# gcloud secrets versions access latest --secret="blend-monitor-firebase-key" --project=PROJECT_ID
77+
# 6. Update .env.local with actual values
78+
# ===================================

apps/blend-monitor/Dockerfile

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,49 @@
11
# Build stage
22
FROM node:20-alpine AS builder
33

4-
# Install dependencies for native modules
4+
# Install dependencies for native modules and pnpm
55
RUN apk add --no-cache libc6-compat
6+
RUN corepack enable && corepack prepare pnpm@latest --activate
67

78
WORKDIR /app
89

9-
# Copy package file
10+
# Copy monorepo files
11+
COPY pnpm-workspace.yaml ./
12+
COPY pnpm-lock.yaml ./
1013
COPY package.json ./
11-
12-
# Install dependencies (without lock file since it's in the monorepo root)
13-
RUN npm install
14-
15-
# Copy source files
16-
COPY . .
17-
18-
# Set build-time environment variables (actual values for build)
19-
ENV NEXT_PUBLIC_FIREBASE_API_KEY="AIzaSyD2aRkOI4iCwiZOW5kEejrL9jv9JvytKpo"
20-
ENV NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN="storybook-452807.firebaseapp.com"
21-
ENV NEXT_PUBLIC_FIREBASE_PROJECT_ID="storybook-452807"
22-
ENV NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET="storybook-452807.firebasestorage.app"
23-
ENV NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID="567047894553"
24-
ENV NEXT_PUBLIC_FIREBASE_APP_ID="1:567047894553:web:1cd999e1c9bf9b81ff5c88"
25-
ENV NEXT_PUBLIC_FIREBASE_DATABASE_URL="https://storybook-452807-default-rtdb.asia-southeast1.firebasedatabase.app"
14+
COPY turbo.json ./
15+
16+
# Copy blend-monitor app
17+
COPY apps/blend-monitor ./apps/blend-monitor
18+
19+
# Copy shared packages if needed
20+
COPY packages ./packages
21+
22+
# Install dependencies
23+
RUN pnpm install --frozen-lockfile
24+
25+
# Build arguments for Firebase configuration
26+
ARG NEXT_PUBLIC_FIREBASE_API_KEY
27+
ARG NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
28+
ARG NEXT_PUBLIC_FIREBASE_PROJECT_ID
29+
ARG NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
30+
ARG NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
31+
ARG NEXT_PUBLIC_FIREBASE_APP_ID
32+
ARG NEXT_PUBLIC_FIREBASE_DATABASE_URL
33+
34+
# Set build-time environment variables from build arguments
35+
ENV NEXT_PUBLIC_FIREBASE_API_KEY=${NEXT_PUBLIC_FIREBASE_API_KEY}
36+
ENV NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=${NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN}
37+
ENV NEXT_PUBLIC_FIREBASE_PROJECT_ID=${NEXT_PUBLIC_FIREBASE_PROJECT_ID}
38+
ENV NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=${NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}
39+
ENV NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=${NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}
40+
ENV NEXT_PUBLIC_FIREBASE_APP_ID=${NEXT_PUBLIC_FIREBASE_APP_ID}
41+
ENV NEXT_PUBLIC_FIREBASE_DATABASE_URL=${NEXT_PUBLIC_FIREBASE_DATABASE_URL}
2642

2743
# Build the application
2844
ENV NEXT_TELEMETRY_DISABLED 1
29-
RUN npm run build
45+
WORKDIR /app/apps/blend-monitor
46+
RUN pnpm run build
3047

3148
# Production stage
3249
FROM node:20-alpine AS runner
@@ -41,18 +58,16 @@ RUN addgroup --system --gid 1001 nodejs
4158
RUN adduser --system --uid 1001 nextjs
4259

4360
# Copy necessary files from builder
44-
COPY --from=builder /app/public ./public
45-
COPY --from=builder /app/.next/standalone ./
46-
COPY --from=builder /app/.next/static ./.next/static
47-
48-
# Set correct permissions
49-
RUN chown -R nextjs:nodejs /app
61+
COPY --from=builder --chown=nextjs:nodejs /app/apps/blend-monitor/.next/standalone ./
62+
COPY --from=builder --chown=nextjs:nodejs /app/apps/blend-monitor/.next/static ./apps/blend-monitor/.next/static
63+
COPY --from=builder --chown=nextjs:nodejs /app/apps/blend-monitor/public ./apps/blend-monitor/public
5064

5165
USER nextjs
5266

5367
# Expose port
5468
EXPOSE 8080
5569
ENV PORT 8080
70+
ENV HOSTNAME="0.0.0.0"
5671

5772
# Start the application
58-
CMD ["node", "server.js"]
73+
CMD ["node", "apps/blend-monitor/server.js"]

apps/blend-monitor/LOCAL_SETUP.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Blend Monitor - Local Setup Guide
2+
3+
Quick guide to run blend-monitor locally on your machine.
4+
5+
## Prerequisites
6+
7+
- Node.js 18+
8+
- pnpm installed
9+
- GCP CLI authenticated with `storybook-452807` project
10+
11+
## Setup Steps
12+
13+
### 1. Download Cloud SQL Proxy
14+
15+
```bash
16+
cd apps/blend-monitor
17+
curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
18+
chmod +x cloud_sql_proxy
19+
```
20+
21+
### 2. Configure Environment Variables
22+
23+
Copy the example file:
24+
25+
```bash
26+
cp .env.example .env.local
27+
```
28+
29+
Fetch secrets from GCP Secret Manager:
30+
31+
```bash
32+
# Get database password
33+
gcloud secrets versions access latest --secret="blend-monitor-db-password" --project=storybook-452807
34+
35+
# Get Firebase private key
36+
gcloud secrets versions access latest --secret="blend-monitor-firebase-key" --project=storybook-452807
37+
```
38+
39+
Add the secrets to `.env.local`:
40+
41+
- `DATABASE_PASSWORD=<paste the database password>`
42+
- `FIREBASE_PRIVATE_KEY=<paste the private key>`
43+
44+
### 3. Start Cloud SQL Proxy
45+
46+
```bash
47+
./cloud_sql_proxy -instances=storybook-452807:us-central1:blend-dashboard=tcp:5433 &
48+
```
49+
50+
### 4. Run Development Server
51+
52+
From the monorepo root:
53+
54+
```bash
55+
pnpm --filter blend-monitor dev
56+
```
57+
58+
Or from the blend-monitor directory:
59+
60+
```bash
61+
pnpm dev
62+
```
63+
64+
### 5. Access the App
65+
66+
Open http://localhost:3000 in your browser.
67+
68+
## Stopping the App
69+
70+
Kill the dev server (Ctrl+C) and stop the Cloud SQL proxy:
71+
72+
```bash
73+
pkill -f cloud_sql_proxy
74+
```
75+
76+
## Troubleshooting
77+
78+
**Port already in use?**
79+
80+
- Kill the process: `lsof -ti:3000 | xargs kill -9`
81+
82+
**Database connection failed?**
83+
84+
- Ensure Cloud SQL proxy is running: `ps aux | grep cloud_sql_proxy`
85+
- Check proxy logs for connection errors
86+
87+
**Firebase authentication failed?**
88+
89+
- Verify `FIREBASE_PRIVATE_KEY` is properly formatted in `.env.local`
90+
- Ensure the private key includes `\n` for newlines in the string

apps/blend-monitor/cloudbuild.yaml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
steps:
2-
# Build the container image
2+
# Build the container image with build arguments
33
- name: 'gcr.io/cloud-builders/docker'
44
args:
55
- 'build'
66
- '-t'
77
- 'gcr.io/$PROJECT_ID/blend-monitor:$BUILD_ID'
88
- '-t'
99
- 'gcr.io/$PROJECT_ID/blend-monitor:latest'
10+
- '-f'
11+
- 'apps/blend-monitor/Dockerfile'
12+
- '--build-arg'
13+
- 'NEXT_PUBLIC_FIREBASE_API_KEY=$_FIREBASE_API_KEY'
14+
- '--build-arg'
15+
- 'NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=$_FIREBASE_AUTH_DOMAIN'
16+
- '--build-arg'
17+
- 'NEXT_PUBLIC_FIREBASE_PROJECT_ID=$_FIREBASE_PROJECT_ID'
18+
- '--build-arg'
19+
- 'NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=$_FIREBASE_STORAGE_BUCKET'
20+
- '--build-arg'
21+
- 'NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=$_FIREBASE_MESSAGING_SENDER_ID'
22+
- '--build-arg'
23+
- 'NEXT_PUBLIC_FIREBASE_APP_ID=$_FIREBASE_APP_ID'
24+
- '--build-arg'
25+
- 'NEXT_PUBLIC_FIREBASE_DATABASE_URL=$_FIREBASE_DATABASE_URL'
1026
- '.'
1127

1228
# Push the container image to Container Registry
@@ -59,9 +75,9 @@ substitutions:
5975
_FIREBASE_PROJECT_ID: 'storybook-452807'
6076
_FIREBASE_STORAGE_BUCKET: 'storybook-452807.firebasestorage.app'
6177
_FIREBASE_MESSAGING_SENDER_ID: '567047894553'
62-
_FIREBASE_APP_ID: '1:567047894553:web:1cd999e1c9bf9b81ff5c88'
78+
_FIREBASE_APP_ID: '1:567047894553:web:f2e38d23fbc9bdbbff5c88'
6379
_FIREBASE_DATABASE_URL: 'https://storybook-452807-default-rtdb.asia-southeast1.firebasedatabase.app'
64-
_FIREBASE_CLIENT_EMAIL: 'firebase-adminsdk-fbsvc@storybook-452807.iam.gserviceaccount.com'
80+
_FIREBASE_CLIENT_EMAIL: 'blend-firebase-10281134@storybook-452807.iam.gserviceaccount.com'
6581

6682
options:
6783
logging: CLOUD_LOGGING_ONLY

0 commit comments

Comments
 (0)