-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
237 lines (224 loc) · 13.6 KB
/
Copy path.env.example
File metadata and controls
237 lines (224 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# AdvisoryHub — production env reference.
#
# THIS FILE IS NOT NEEDED FOR LOCAL DEVELOPMENT.
# Local dev is fully driven by docker-compose.yml; the kanidm bootstrap
# script (dev/kanidm/setup.sh) writes the only variable that's
# genuinely random (the OIDC client secret) into
# dev/kanidm/.env.kanidm, which compose loads automatically.
#
# This file documents every env var AdvisoryHub reads, for use when
# wiring a production deployment via your platform's secret manager
# (Kubernetes Secrets, Docker Swarm secrets, AWS SSM, …). Each section
# notes whether the value is a *secret* (must come from a vault) or a
# *config knob* (safe to commit to a manifest).
# --- Django (config) ---
DJANGO_SECRET_KEY= # SECRET — required in prod (startup fails on the dev default); long random string
DJANGO_DEBUG=False
DJANGO_ALLOWED_HOSTS=advisoryhub.example.org
DJANGO_TIME_ZONE=UTC
# --- Database (secret + config) ---
DATABASE_URL=postgres://USER:PASSWORD@HOST:5432/advisoryhub
# --- OIDC (mozilla-django-oidc) ---
OIDC_RP_CLIENT_ID= # config (per environment)
OIDC_RP_CLIENT_SECRET= # SECRET
OIDC_OP_AUTHORIZATION_ENDPOINT=
OIDC_OP_TOKEN_ENDPOINT=
OIDC_OP_USER_ENDPOINT=
OIDC_OP_JWKS_ENDPOINT=
# OIDC end_session_endpoint for RP-initiated logout. Leave empty to fall
# back to local-only logout (note: with a live SSO session on the OP this
# means clicking "Sign out" silently re-authenticates the user).
OIDC_OP_LOGOUT_ENDPOINT=
OIDC_RP_SIGN_ALGO=RS256
OIDC_VERIFY_SSL=True # keep True in prod
OIDC_GROUP_CLAIM=groups
OIDC_ADMIN_GROUP=advisoryhub-security
# Trust the OIDC `email` claim only when verified (INV-OIDC-6). An explicit
# `email_verified: false` always blocks account create/link; this governs the
# *absent* case. Kanidm omits the claim, so the default (False) keeps linking
# working. Set True for an OP allowing unverified-email signup or upstream
# federation that forwards `email` without re-verification.
OIDC_REQUIRE_EMAIL_VERIFIED=False
# --- Celery + cache (broker = Valkey, Redis-compatible) ---
# In prod prefer rediss:// (TLS) + AUTH — e.g. rediss://:<password>@host:6379/0 — the
# broker carries task payloads and the cache holds rate-limit/maintenance state.
# Run the shared Valkey with `--maxmemory-policy noeviction` so an eviction can never
# silently drop broker messages or rate-limit/maintenance keys.
CELERY_BROKER_URL=redis://valkey:6379/0
CELERY_RESULT_BACKEND=redis://valkey:6379/1
CACHE_URL=redis://valkey:6379/2
# --- Email ---
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
DEFAULT_FROM_EMAIL=AdvisoryHub <noreply@example.org>
EMAIL_HOST=smtp.example.org
EMAIL_PORT=587
EMAIL_HOST_USER= # empty disables SMTP auth
EMAIL_HOST_PASSWORD= # SECRET
EMAIL_USE_TLS=True # STARTTLS; use EMAIL_USE_SSL for implicit TLS (465)
EMAIL_USE_SSL=False
EMAIL_TIMEOUT=30 # seconds; bounds every SMTP operation so a hung server cannot wedge a worker
# Absolute-URL base for links in notification emails; empty keeps them
# site-relative (which won't resolve from a mail client).
ADVISORYHUB_BASE_URL=https://advisoryhub.example.org
# --- Help / support links (site footer) ---
# Base GitHub repo for AdvisoryHub itself. The footer's "Report an issue"
# (<repo>/issues/new) and "Report a vulnerability in AdvisoryHub"
# (<repo>/security/advisories/new) links are DERIVED from this, so a repo move
# is a single change here. Blank disables both links.
ADVISORYHUB_REPO_URL=https://github.com/eclipse-csi/advisoryhub
# Where the footer's "Ask a question" link points (Eclipse CSI org discussions).
# Independent of the repo above; blank disables the link.
ADVISORYHUB_DISCUSSIONS_URL=https://github.com/orgs/eclipse-csi/discussions
# --- Operability ---
LOG_FORMAT=json # JSON in prod; "plain" in dev
LOG_LEVEL=INFO
RATELIMIT_ENABLE=True
# Trusted reverse proxies that append to X-Forwarded-For in front of the
# app. 0 = ignore XFF (use the direct peer). Set to your real proxy depth
# (e.g. 1 behind a single ingress/LB) so per-IP rate limits and audit-log
# IPs reflect the true client and can't be forged via a spoofed header.
TRUSTED_PROXY_COUNT=1
# When TLS terminates at the proxy (ingress/Route/LB), trust its
# X-Forwarded-Proto so SECURE_SSL_REDIRECT doesn't loop and secure
# cookies/CSRF engage. Only enable when ALL traffic passes a proxy that
# sets (never forwards) the header. Pair with CSRF_TRUSTED_ORIGINS.
USE_X_FORWARDED_PROTO=True
CSRF_TRUSTED_ORIGINS=https://advisoryhub.example.org
STEP_UP_REQUIRED=True
STEP_UP_MAX_AGE_SECONDS=300
READYZ_INCLUDE_PUB_REPO=False # turn on if you want /readyz to ls-remote
READYZ_INCLUDE_BROKER=False # turn on to also probe the Celery broker in /readyz
SENTRY_DSN= # SECRET — empty disables Sentry
SENTRY_ENVIRONMENT=production
SENTRY_TRACES_SAMPLE_RATE=0
SENTRY_RELEASE= # optional — release tag on events (e.g. the image tag)
# Prometheus. /metrics is always exposed (keep it on a private port). Under
# multiple gunicorn workers, set PROMETHEUS_MULTIPROC_DIR to a writable,
# empty-at-boot tmpfs and run `gunicorn config.wsgi -c gunicorn.conf.py` so the
# custom advisoryhub_* counters aggregate across workers. The Celery worker
# exports its own series on PROMETHEUS_WORKER_METRICS_PORT (set on the worker;
# run it with --pool=threads so one exporter sees all task threads and
# --concurrency can be raised). See architecture.md §8.3 / §8.8.
PROMETHEUS_MULTIPROC_DIR= # e.g. /run/prometheus (tmpfs) — required for multi-worker gunicorn
PROMETHEUS_WORKER_METRICS_PORT=9808 # 0 disables; set on the worker only
# --- Content-Security-Policy ---
CSP_REPORT_ONLY=False # CSP is enforced by default; set True for Report-Only (e.g. diagnosing a new violation)
CSP_REPORT_URI= # optional: collector URL wired into the report-uri directive
# --- Public report intake ---
# ALTCHA (self-hosted proof-of-work) gates anonymous submissions on /report/.
# Empty disables the captcha (the honeypot + per-IP/user rate limits still apply).
# Widget assets are vendored and served same-origin — no CDN and no CSP change.
ALTCHA_HMAC_KEY= # SECRET — HMAC-signs ALTCHA challenges; empty = no captcha
# --- Publication Git repository (Phase D) ---
PUB_REPO_URL=git@github.com:eclipse/advisories.git
PUB_REPO_BRANCH=main
PUB_REPO_AUTH=ssh # or "token"
PUB_REPO_SSH_KEY_PATH=/run/secrets/pub_repo_ssh_key
PUB_REPO_TOKEN= # SECRET (only when PUB_REPO_AUTH=token)
PUB_COMMIT_AUTHOR_NAME=AdvisoryHub Bot
PUB_COMMIT_AUTHOR_EMAIL=advisoryhub-bot@example.org
# OSV/CSAF files are bucketed by the advisory's publication year.
# Path template placeholders: {advisory_id}, {year} (year of first publication).
PUB_OSV_PATH_TEMPLATE=osv/{year}/{advisory_id}.json
PUB_CSAF_PATH_TEMPLATE=csaf/{year}/{advisory_id}.json
# CVE Record export — only emitted for advisories with an EF-assigned CVE.
# Path template placeholders: {cve_id}, {year}, {bucket} (the sequence number
# with its last three digits replaced by "xxx"). The default mirrors the
# official CVEProject/cvelistV5 directory layout.
PUB_CVE_PATH_TEMPLATE=cves/{year}/{bucket}/{cve_id}.json
# Eclipse Foundation CNA identity written into the CVE record. The org id is a
# v4 UUID (cveMetadata.assignerOrgId / providerMetadata.orgId) and MUST be set
# to the real EF CNA UUID — publishing a CVE-assigned advisory fails loudly
# while it is empty.
PUB_CVE_ASSIGNER_ORG_ID=00000000-0000-4000-8000-000000000000
PUB_CVE_ASSIGNER_SHORT_NAME=eclipse
# Stale-publication-task reaper (beat, every 10 min): fails tasks orphaned in
# 'running' (worker hard-killed mid-run) or 'queued' (enqueue lost to a broker
# outage) so they stop blocking publish. RUNNING is measured from started_at
# and must comfortably exceed the worker's hard time_limit (660s); QUEUED is
# measured from created_at and must exceed the broker visibility_timeout
# (3600s) so a delayed redelivery always wins first.
PUB_TASK_STALE_RUNNING_AFTER_SECONDS=1800
PUB_TASK_STALE_QUEUED_AFTER_SECONDS=7200
# --- GHSA integration (GitHub App + Eclipse PMI) ---
# AdvisoryHub talks to GitHub as a registered GitHub App with permissions
# repository_security_advisories: read & write (+ metadata: read). The
# write scope also backs the owner "Move to GHSA" action (authoring a
# repository advisory from a misfiled native report); metadata: read backs
# the private-vulnerability-reporting check that gates it. No extra env var
# is needed — both reuse GHSA_FEATURE_ENABLED + the GitHub App below. The App
# is installed per-repo by Eclipse org admins. The single load-bearing
# secret here is the App private key — never commit it; mount it as a
# file via GITHUB_APP_PRIVATE_KEY_PATH (preferred) rather than pasting it
# inline. v1 supports a single installation; the installation id is
# configured below.
GHSA_FEATURE_ENABLED=False
# Auto-publish a GHSA-linked advisory (export OSV/CSAF/CVE) when GitHub
# publishes it — the inbound-only GHSA lifecycle (INV-GHSA-3). On by default.
GHSA_AUTO_PUBLISH_ENABLED=True
GITHUB_APP_ID= # config (numeric App id)
GITHUB_APP_PRIVATE_KEY_PATH=/run/secrets/github_app_private_key # SECRET (file)
GITHUB_APP_PRIVATE_KEY= # SECRET (inline fallback; leave empty in prod)
GITHUB_APP_WEBHOOK_SECRET= # SECRET (HMAC key for inbound webhook verification)
GITHUB_APP_API_BASE_URL=https://api.github.com
# Stale-CVE-push reaper (beat, every 10 min): fails GhsaCvePushTask rows
# orphaned in 'running' (worker hard-killed; run_cve_push has no acks_late so
# there is no redelivery) or 'queued' (enqueue lost to a broker outage), and
# corrects the advisory's stuck "Pending" CVE-push badge. RUNNING must exceed
# the GitHub client's per-call timeouts (~40s); QUEUED must exceed the broker
# visibility_timeout (3600s). DB-only — runs even while GHSA_FEATURE_ENABLED
# is False (no GitHub egress).
GHSA_CVE_PUSH_STALE_RUNNING_AFTER_SECONDS=1800
GHSA_CVE_PUSH_STALE_QUEUED_AFTER_SECONDS=7200
# Installations are persisted in the database (see the
# `ghsa_githubappinstallation` table). After upgrading from Phase 1, run
# `python manage.py discover_github_installations` once to populate it,
# or wait for the first `installation.created` webhook to arrive.
PMI_API_BASE_URL=https://projects.eclipse.org/api
PMI_API_TOKEN= # SECRET only if PMI requires auth; usually blank
PMI_SYNC_INTERVAL_HOURS=6 # celery beat cadence for repo mirror refresh
# Celery beat cadence for the inbound-lifecycle reconcile poll (re-sync active
# GHSA-linked advisories to mirror GitHub state — INV-GHSA-3).
GHSA_SYNC_INTERVAL_HOURS=6
# Celery beat cadence for the full GHSA discovery sweep — auto-creates rows for
# GHSAs not yet mirrored (the backstop for `repository_advisory.reported`
# webhooks GitHub may not deliver). Heavier than reconcile (lists every repo),
# so a slower default. On-demand discovery from the admin console is primary.
GHSA_DISCOVERY_INTERVAL_HOURS=24
# --- Security-team roster sync (notification reach for never-logged-in members) ---
# Pre-provisions notification-only "shadow" users for each project's Eclipse
# security team, so @group mentions and team notifications reach members who
# have never logged in (they gain NO in-app access until first login — see
# INV-OIDC-5). Off by default: it needs the *authenticated* Eclipse API
# (OAuth2 client credentials) to resolve member emails the public PMI feed
# hides. Leave PMI_ROSTER_SYNC_ENABLED=False until the ECLIPSE_API_* creds are set.
PMI_ROSTER_SYNC_ENABLED=False
PMI_ROSTER_SYNC_INTERVAL_HOURS=24 # celery beat cadence for roster refresh
ECLIPSE_API_BASE_URL=https://api.eclipse.org
ECLIPSE_API_TOKEN_URL=https://auth.eclipse.org/auth/realms/eclipse/protocol/openid-connect/token
ECLIPSE_API_CLIENT_ID= # SECRET — OAuth2 client id (client-credentials grant)
ECLIPSE_API_CLIENT_SECRET= # SECRET — OAuth2 client secret
ECLIPSE_API_SCOPE= # optional OAuth2 scope(s), space-separated
# --- LLM-assisted duplicate detection (similarity app) ---
# Off by default. When enabled, every new advisory/report is checked for
# potential duplicates: advisory content (potentially EMBARGOED) is sent to
# the configured LLM provider — enabling this flag is the explicit consent
# for that egress (INV-SIM-2). Deployments that must keep content on-prem
# should set SIMILARITY_LLM_PROVIDER=openai and point SIMILARITY_LLM_BASE_URL
# at a local OpenAI-compatible server (Ollama, vLLM, LM Studio).
SIMILARITY_CHECK_ENABLED=False
SIMILARITY_LLM_PROVIDER=anthropic # anthropic | openai (incl. OpenAI-compatible servers)
SIMILARITY_LLM_MODEL=claude-opus-4-8
SIMILARITY_LLM_API_KEY= # SECRET — provider API key (blank for keyless local servers)
SIMILARITY_LLM_BASE_URL= # empty = provider default; e.g. http://ollama:11434 for local
SIMILARITY_LLM_TIMEOUT=120 # per-request read timeout (seconds)
SIMILARITY_CANDIDATE_LIMIT=60 # max prefilter candidates sent to the judge call
SIMILARITY_MIN_CONFIDENCE=20 # store matches at/above this confidence (0-100)
# Stale-similarity-check reaper (beat, every 10 min): fails checks orphaned in
# 'running' (worker hard-killed mid-run) or 'queued' (enqueue lost to a broker
# outage) so the panel's re-run button works again. RUNNING must comfortably
# exceed the worker's hard time_limit (360s); QUEUED must exceed the broker
# visibility_timeout (3600s). DB-only — the reaper runs even while
# SIMILARITY_CHECK_ENABLED=False (no LLM egress).
SIMILARITY_CHECK_STALE_RUNNING_AFTER_SECONDS=1800
SIMILARITY_CHECK_STALE_QUEUED_AFTER_SECONDS=7200