Repository navigation
Expand file tree
/
Copy pathsettings.py
More file actions
170 lines (148 loc) 路 8.8 KB
/
Copy pathsettings.py
File metadata and controls
170 lines (148 loc) 路 8.8 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
"""
Django settings for PostHog Enterprise Edition.
"""
import os
from posthog.settings import AUTHENTICATION_BACKENDS, DEBUG, DEMO, MIDDLEWARE, SITE_URL
from posthog.settings.utils import get_from_env
from posthog.utils import str_to_bool
# SSO
AUTHENTICATION_BACKENDS = [
*AUTHENTICATION_BACKENDS,
"ee.api.authentication.MultitenantSAMLAuth",
"posthog.api.oidc.MultitenantOIDCAuth",
"ee.api.authentication.CustomGoogleOAuth2",
]
# SAML base attributes
SOCIAL_AUTH_SAML_SP_ENTITY_ID = SITE_URL
SOCIAL_AUTH_SAML_SECURITY_CONFIG = {
"wantAttributeStatement": False, # AttributeStatement is optional in the specification
"requestedAuthnContext": False, # do not explicitly request a password login, also allow multifactor and others
}
# Attributes below are required for the SAML integration from social_core to work properly
SOCIAL_AUTH_SAML_SP_PUBLIC_CERT = ""
SOCIAL_AUTH_SAML_SP_PRIVATE_KEY = ""
SOCIAL_AUTH_SAML_ORG_INFO = {"en-US": {"name": "posthog", "displayname": "PostHog", "url": "https://posthog.com"}}
SOCIAL_AUTH_SAML_TECHNICAL_CONTACT = {
"givenName": "PostHog Support",
"emailAddress": "hey@posthog.com",
}
SOCIAL_AUTH_SAML_SUPPORT_CONTACT = SOCIAL_AUTH_SAML_TECHNICAL_CONTACT
# Google SSO
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY: str | None = os.getenv("SOCIAL_AUTH_GOOGLE_OAUTH2_KEY")
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET: str | None = os.getenv("SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET")
if "SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS" in os.environ:
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS: list[str] = os.environ[
"SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS"
].split(",")
elif DEMO:
# Only PostHog team members can use social auth in the demo environment
# This is because in the demo env social signups get is_staff=True to facilitate instance management
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = ["posthog.com"]
# Admin OAuth2 Verification
ADMIN_AUTH_GOOGLE_OAUTH2_KEY = os.getenv("ADMIN_AUTH_GOOGLE_OAUTH2_KEY")
ADMIN_AUTH_GOOGLE_OAUTH2_SECRET = os.getenv("ADMIN_AUTH_GOOGLE_OAUTH2_SECRET")
# Restrict admin OAuth to specific Google Workspace domains (comma-separated list)
ADMIN_AUTH_GOOGLE_ALLOWED_DOMAINS = [
d.strip() for d in os.environ.get("ADMIN_AUTH_GOOGLE_ALLOWED_DOMAINS", "posthog.com").split(",") if d.strip()
]
ENFORCE_ADMIN_OAUTH2 = str_to_bool(get_from_env("ENFORCE_ADMIN_OAUTH2", "True", type_cast=str))
if ENFORCE_ADMIN_OAUTH2 and ADMIN_AUTH_GOOGLE_OAUTH2_KEY and ADMIN_AUTH_GOOGLE_OAUTH2_SECRET:
ADMIN_OAUTH2_COOKIE_SECURE = str_to_bool(get_from_env("ADMIN_OAUTH2_COOKIE_SECURE", "True", type_cast=str))
# middleware must be added after `AuthenticationMiddleware``
MIDDLEWARE = MIDDLEWARE.copy()
auth_middleware_index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware")
MIDDLEWARE.insert(auth_middleware_index + 1, "ee.middleware.AdminOAuth2Middleware")
CUSTOMER_IO_API_KEY = get_from_env("CUSTOMER_IO_API_KEY", "", type_cast=str)
CUSTOMER_IO_API_URL = get_from_env("CUSTOMER_IO_API_URL", "https://api-eu.customer.io", type_cast=str)
# Schedule to run column materialization on. Follows crontab syntax.
# Use empty string to prevent from materializing
MATERIALIZE_COLUMNS_SCHEDULE_CRON = get_from_env("MATERIALIZE_COLUMNS_SCHEDULE_CRON", "0 5 * * SAT")
# Minimum query time before a query if considered for optimization by adding materialized columns
MATERIALIZE_COLUMNS_MINIMUM_QUERY_TIME = get_from_env("MATERIALIZE_COLUMNS_MINIMUM_QUERY_TIME", 40000, type_cast=int)
# How many hours backwards to look for queries to optimize
MATERIALIZE_COLUMNS_ANALYSIS_PERIOD_HOURS = get_from_env(
"MATERIALIZE_COLUMNS_ANALYSIS_PERIOD_HOURS", 7 * 24, type_cast=int
)
# How big of a timeframe to backfill when materializing event properties. 0 for no backfilling
MATERIALIZE_COLUMNS_BACKFILL_PERIOD_DAYS = get_from_env("MATERIALIZE_COLUMNS_BACKFILL_PERIOD_DAYS", 0, type_cast=int)
# Maximum number of columns to materialize at once. Avoids running into resource bottlenecks (storage + ingest + backfilling).
MATERIALIZE_COLUMNS_MAX_AT_ONCE = get_from_env("MATERIALIZE_COLUMNS_MAX_AT_ONCE", 100, type_cast=int)
BILLING_SERVICE_URL = get_from_env("BILLING_SERVICE_URL", "https://billing.posthog.com")
# Lifetime of the access token PostHog mints for the public billing API (ee/billing/access_token.py).
BILLING_ACCESS_TOKEN_TTL_SECONDS: int = get_from_env("BILLING_ACCESS_TOKEN_TTL_SECONDS", 15 * 60, type_cast=int)
# Whether to enable the admin portal. Default false for self-hosted as if not setup properly can pose security issues.
ADMIN_PORTAL_ENABLED = get_from_env("ADMIN_PORTAL_ENABLED", DEMO or DEBUG, type_cast=str_to_bool)
# Fixed personal API key for local development, created by `manage.py setup_local_api_key`
DEV_API_KEY = "phx_dev_local_test_api_key_1234567890abcdef"
PARALLEL_ASSET_GENERATION_MAX_TIMEOUT_MINUTES = get_from_env(
"PARALLEL_ASSET_GENERATION_MAX_TIMEOUT_MINUTES", 10.0, type_cast=float
)
TEMPORAL_TASK_TIMEOUT_MINUTES = PARALLEL_ASSET_GENERATION_MAX_TIMEOUT_MINUTES * 1.5
# Assistant
ANTHROPIC_API_KEY = get_from_env("ANTHROPIC_API_KEY", "")
OPENAI_API_KEY = get_from_env("OPENAI_API_KEY", "")
OPENAI_BASE_URL = get_from_env("OPENAI_BASE_URL", "https://api.openai.com/v1")
# LLM Gateway (internal service for proxying LLM requests with rate limiting and attribution)
LLM_GATEWAY_URL = get_from_env("LLM_GATEWAY_URL", "http://localhost:3308" if DEBUG else "")
LLM_GATEWAY_API_KEY = get_from_env("LLM_GATEWAY_PERSONAL_API_KEY", DEV_API_KEY if DEBUG else "")
INKEEP_API_KEY = get_from_env("INKEEP_API_KEY", "")
MISTRAL_API_KEY = get_from_env("MISTRAL_API_KEY", "")
GEMINI_API_KEY = get_from_env("GEMINI_API_KEY", "")
# Dedicated key for Replay Vision (own GCP project for cost/quota isolation); falls back to GEMINI_API_KEY
REPLAY_VISION_GEMINI_API_KEY = get_from_env("REPLAY_VISION_GEMINI_API_KEY", "")
PPLX_API_KEY = get_from_env("PPLX_API_KEY", "")
AZURE_INFERENCE_ENDPOINT = get_from_env("AZURE_INFERENCE_ENDPOINT", "", type_cast=str)
AZURE_INFERENCE_CREDENTIAL = get_from_env("AZURE_INFERENCE_CREDENTIAL", "", type_cast=str)
BRAINTRUST_API_KEY = get_from_env("BRAINTRUST_API_KEY", "")
LLMA_EVAL_OPENAI_API_KEY = get_from_env("LLMA_EVAL_OPENAI_API_KEY", "")
LLMA_EVAL_OPENAI_BASE_URL = get_from_env("LLMA_EVAL_OPENAI_BASE_URL", "")
LLMA_EVAL_ANTHROPIC_API_KEY = get_from_env("LLMA_EVAL_ANTHROPIC_API_KEY", "")
LLMA_EVAL_GEMINI_API_KEY = get_from_env("LLMA_EVAL_GEMINI_API_KEY", "")
SQS_QUEUES = {
"usage_reports": {
"url": get_from_env("SQS_USAGE_REPORT_QUEUE_URL", optional=True),
"region": get_from_env("SQS_REGION", "us-east-1", optional=True),
"type": "usage_reports",
},
"usage_reports_v2": {
"url": get_from_env("SQS_USAGE_REPORT_V2_QUEUE_URL", optional=True),
"region": get_from_env("SQS_USAGE_REPORT_V2_REGION", "us-east-1", optional=True),
"type": "usage_reports_v2",
},
"billing": {
"url": get_from_env("SQS_BILLING_QUEUE_URL", optional=True),
"region": get_from_env("SQS_BILLING_REGION", "us-east-1", optional=True),
"type": "billing",
},
}
# Salesforce OAuth Client Credentials for internal enrichment (preferred over username/password auth)
SALESFORCE_INTERNAL_CONSUMER_KEY = get_from_env("SF_INTERNAL_CONSUMER_KEY", "", type_cast=str)
SALESFORCE_INTERNAL_CONSUMER_SECRET = get_from_env("SF_INTERNAL_CONSUMER_SECRET", "", type_cast=str)
SALESFORCE_INTERNAL_DOMAIN = get_from_env("SF_INTERNAL_DOMAIN", "posthog.my.salesforce.com", type_cast=str)
# Salesforce legacy API credentials (fallback)
SALESFORCE_USERNAME = get_from_env("SF_USERNAME", "", type_cast=str)
SALESFORCE_PASSWORD = get_from_env("SF_PASSWORD", "", type_cast=str)
SALESFORCE_SECURITY_TOKEN = get_from_env("SF_SECURITY_TOKEN", "", type_cast=str)
# Harmonic API credentials
HARMONIC_API_KEY = get_from_env("HARMONIC_API_KEY", "", type_cast=str)
HARMONIC_BASE_URL = get_from_env("HARMONIC_BASE_URL", "https://api.harmonic.ai", type_cast=str)
# Vercel Integration
VERCEL_CLIENT_INTEGRATION_ID = get_from_env("VERCEL_CLIENT_INTEGRATION_ID", "", type_cast=str)
VERCEL_CLIENT_INTEGRATION_SECRET = get_from_env("VERCEL_CLIENT_INTEGRATION_SECRET", "", type_cast=str)
BILLING_PROVIDER_WEBHOOK_SECRET = get_from_env("BILLING_PROVIDER_WEBHOOK_SECRET", "", type_cast=str)
# SCIM Configuration
# django-scim2 requires these settings
SCIM_SERVICE_PROVIDER = {
"NETLOC": SITE_URL.replace("http://", "").replace("https://", ""),
"AUTHENTICATION_SCHEMES": [
{
"type": "oauthbearertoken",
"name": "OAuth Bearer Token",
"description": "Authentication scheme using the OAuth Bearer Token Standard",
"specUri": "https://www.rfc-editor.org/rfc/rfc6750.txt",
"documentationUri": "https://posthog.com/docs/settings/scim",
}
],
# User model is already configured via AUTH_USER_MODEL = "posthog.User"
"GROUP_MODEL": "products.access_control.backend.models.role.Role",
}