Some checks are pending
Check Python Version Consistency / Check Python Version (push) Waiting to run
132 lines
5.1 KiB
Markdown
132 lines
5.1 KiB
Markdown
# Google Cloud Secret Manager Setup Guide
|
|
|
|
This guide provides the `gcloud` commands to set up secrets in Google Cloud Secret Manager and configure the Cloud Run service to use them.
|
|
|
|
## 1. Create Secrets in Secret Manager
|
|
|
|
First, create the `CHAT_WEBHOOK_URL` and `GOOGLE_API_KEY` secrets.
|
|
|
|
```bash
|
|
# Create CHAT_WEBHOOK_URL secret
|
|
echo -n "your-chat-webhook-url" | gcloud secrets create CHAT_WEBHOOK_URL --data-file=-
|
|
|
|
# Create GOOGLE_API_KEY secret
|
|
echo -n "your-google-api-key" | gcloud secrets create GOOGLE_API_KEY --data-file=-
|
|
```
|
|
Replace `"your-chat-webhook-url"` and `"your-google-api-key"` with your actual secret values.
|
|
|
|
## 2. Grant Secret Accessor Role
|
|
|
|
Grant the `Secret Manager Secret Accessor` role to the service account that your Cloud Run service uses. By default, this is the default compute service account.
|
|
|
|
```bash
|
|
# Get your project number
|
|
PROJECT_NUMBER=$(gcloud projects describe <YOUR_PROJECT_ID> --format="value(projectNumber)")
|
|
|
|
# Construct the service account email
|
|
SERVICE_ACCOUNT_EMAIL="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
|
|
|
|
# Grant access to CHAT_WEBHOOK_URL
|
|
gcloud secrets add-iam-policy-binding CHAT_WEBHOOK_URL
|
|
--member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}"
|
|
--role="roles/secretmanager.secretAccessor"
|
|
|
|
# Grant access to GOOGLE_API_KEY
|
|
gcloud secrets add-iam-policy-binding GOOGLE_API_KEY
|
|
--member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}"
|
|
--role="roles/secretmanager.secretAccessor"
|
|
```
|
|
Replace `<YOUR_PROJECT_ID>` with your Google Cloud project ID.
|
|
|
|
## 3. Update `bridge/server.py` to Use Secrets
|
|
|
|
Modify `bridge/server.py` to read secrets from Secret Manager when it's not running in a local development environment.
|
|
|
|
Here is the code patch to apply to `bridge/server.py`. This patch adds a function to retrieve secrets and modifies the `post_to_chat` function to use it.
|
|
|
|
```python
|
|
# Add this import at the top of bridge/server.py
|
|
from google.cloud import secretmanager
|
|
|
|
# Add this function to bridge/server.py
|
|
def get_secret(secret_id: str, project_id: str, version_id: str = "latest") -> str:
|
|
"""
|
|
Get a secret from Google Cloud Secret Manager.
|
|
"""
|
|
try:
|
|
client = secretmanager.SecretManagerServiceClient()
|
|
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
|
|
response = client.access_secret_version(name=name)
|
|
return response.payload.data.decode("UTF-8")
|
|
except Exception as e:
|
|
print(f"Error accessing secret {secret_id}: {e}")
|
|
return None
|
|
|
|
# The following is a patch for the lifespan context manager in bridge/server.py
|
|
# --- old
|
|
# from dotenv import load_dotenv
|
|
# load_dotenv()
|
|
# --- new
|
|
from dotenv import load_dotenv
|
|
from google.cloud import secretmanager
|
|
|
|
load_dotenv()
|
|
|
|
def get_secret(secret_id: str, project_id: str, version_id: str = "latest") -> str:
|
|
"""
|
|
Get a secret from Google Cloud Secret Manager.
|
|
"""
|
|
try:
|
|
client = secretmanager.SecretManagerServiceClient()
|
|
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
|
|
response = client.access_secret_version(name=name)
|
|
return response.payload.data.decode("UTF-8")
|
|
except Exception as e:
|
|
print(f"Error accessing secret {secret_id}: {e}")
|
|
return None
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Startup
|
|
if os.getenv("GAE_ENV", "").startswith("standard"):
|
|
project_id = os.getenv("GOOGLE_CLOUD_PROJECT")
|
|
if project_id:
|
|
os.environ["CHAT_WEBHOOK_URL"] = get_secret("CHAT_WEBHOOK_URL", project_id)
|
|
os.environ["GOOGLE_API_KEY"] = get_secret("GOOGLE_API_KEY", project_id)
|
|
|
|
if not os.path.exists(STATE_DIR):
|
|
os.makedirs(STATE_DIR)
|
|
|
|
watcher_task = asyncio.create_task(state_watcher_with_approval_check())
|
|
print("Bridge server started, watcher with approval check is running.")
|
|
yield
|
|
# Shutdown
|
|
watcher_task.cancel()
|
|
try:
|
|
await watcher_task
|
|
except asyncio.CancelledError:
|
|
print("Watcher task cancelled.")
|
|
```
|
|
Apply this patch to your `bridge/server.py` file. This code checks for the `GAE_ENV` environment variable, which is set in App Engine and Cloud Run environments. If it's present, it fetches the secrets from Secret Manager and sets them as environment variables for the application to use.
|
|
|
|
---
|
|
|
|
## GitHub Actions Secrets (aktive per 2026-05-25)
|
|
|
|
Disse secrets er satt i [OSVauco → Settings → Secrets → Actions](https://github.com/vauco-saas/OSVauco/settings/secrets/actions)
|
|
og brukes av `.github/workflows/backup-gdrive-nightly.yml`.
|
|
|
|
| Secret | Formål | Status |
|
|
|---|---|---|
|
|
| `RCLONE_GDRIVE_SA_JSON` | Hele JSON-nøkkelen for `vauco-gdrive-backup` service account | ✅ Aktiv |
|
|
| `GDRIVE_BACKUP_FOLDER_ID` | GDrive-mappe-ID (`0AB6RSjTedmwEUk9PVA`) for backup-destinasjon | ✅ Aktiv |
|
|
|
|
**Service account:** `vauco-gdrive-backup@propane-will-491900-m5.iam.gserviceaccount.com`
|
|
|
|
**Forny nøkkel ved behov:**
|
|
```bash
|
|
gcloud iam service-accounts keys create ~/vauco-gdrive-backup-sa-new.json \
|
|
--iam-account=vauco-gdrive-backup@propane-will-491900-m5.iam.gserviceaccount.com
|
|
# Oppdater GitHub Secret RCLONE_GDRIVE_SA_JSON med nytt innhold
|
|
```
|