Per-Org SIEM Configuration
Arbitex supports per-organization SIEM connector configuration for organizations that need to route their audit events to a dedicated SIEM endpoint, independently of the global platform connectors. This is distinct from global connectors, which are configured at the platform level via environment variables and receive events from all organizations.
Per-org SIEM configs are stored in the siem_configs database table with Fernet-encrypted credential payloads. The platform loads active configs for each org at request time using a 60-second TTL cache.
Architecture
Section titled “Architecture”Audit Event │ ▼SinkManager │ ├─► Global connectors (env var config, all orgs) │ └─► Per-org connectors (DB config, org-specific) │ └─ siem_config_service.get_org_siem_configs(db, org_id) │ └─ SiemConfig rows (Fernet-encrypted) │ └─ instantiate_connector(type, decrypted_config)When an audit event is dispatched, the SinkManager routes it to all configured global connectors and all active per-org connectors for the event’s org. Connectors operate independently — a failure in one does not affect delivery to others.
Data model
Section titled “Data model”Per-org SIEM configurations are stored in the siem_configs table (SiemConfig):
| Column | Type | Description |
|---|---|---|
id | UUID | Config entry identifier |
org_id | UUID | Owning organization UUID |
connector_type | string (≤30) | Connector type identifier (see below) |
config | text | Fernet-encrypted JSON config string |
is_enabled | bool | Whether this config is active for event routing |
created_at | timestamp | Creation time |
updated_at | timestamp | Last modification time |
last_delivery_at | timestamp | Timestamp of most recent successful delivery |
delivery_status | string | healthy, degraded, or failed |
The config column stores a URL-safe base64 Fernet token that decrypts to a JSON object containing connector credentials. The encryption key is set via the FERNET_KEY environment variable. In development/test, a transient per-process key is generated with a warning log — FERNET_KEY must be set in production.
Indexes: (org_id), (org_id, is_enabled) for fast per-org lookups.
Supported connector types
Section titled “Supported connector types”Seven connector types are supported for per-org configuration:
connector_type | Connector | Protocol | Notes |
|---|---|---|---|
splunk_hec | Splunk HEC | HTTPS POST | HTTP Event Collector |
sentinel | Microsoft Sentinel | HTTPS POST (DCR) | Azure Monitor Log Ingestion API |
elastic | Elasticsearch | HTTPS Bulk API | API key or basic auth |
datadog | Datadog | HTTPS Logs Intake v2 | API key |
sumo_logic | Sumo Logic | HTTPS HTTP Source | URL-embedded auth |
cortex_xsiam | Palo Alto Cortex XSIAM | HTTPS | HEC-compatible; uses SplunkHECConnector internally |
qradar | IBM QRadar | Syslog CEF over TLS | Dedicated QRadarConnector |
Multiple configs for the same connector type can exist for an org (e.g., two Splunk instances). Each is a separate row with its own encrypted config.
Config schema per connector type
Section titled “Config schema per connector type”splunk_hec
Section titled “splunk_hec”{ "url": "https://splunk.example.com:8088/services/collector/event", "token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "index": "arbitex_audit", "source": "arbitex"}| Field | Required | Description |
|---|---|---|
url | Yes | HEC endpoint URL |
token | Yes | HEC token |
index | No | Splunk index name |
source | No | Event source label |
sentinel
Section titled “sentinel”{ "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "client_secret": "your-client-secret", "dcr_endpoint": "https://your-dce.eastus-1.ingest.monitor.azure.com", "dcr_id": "dcr-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "stream_name": "Custom-ArbitexAudit_CL"}| Field | Required | Description |
|---|---|---|
tenant_id | Yes | Azure AD tenant ID |
client_id | Yes | Azure AD app client ID |
client_secret | Yes | Azure AD app client secret |
dcr_endpoint | Yes | Data Collection Endpoint URL |
dcr_id | Yes | DCR immutable ID |
stream_name | Yes | Custom stream name in DCR |
elastic
Section titled “elastic”{ "url": "https://your-cluster.es.io:9200", "api_key": "base64encodedapikey==", "index": "arbitex-audit"}| Field | Required | Description |
|---|---|---|
url | Yes | Elasticsearch cluster URL |
api_key | Yes | API key (base64-encoded) |
index | Yes | Target index name |
datadog
Section titled “datadog”{ "api_key": "your-datadog-api-key", "site": "datadoghq.com", "source": "arbitex", "service": "arbitex-gateway"}| Field | Required | Description |
|---|---|---|
api_key | Yes | Datadog API key |
site | No | Datadog site (default datadoghq.com) |
source | No | Log source tag |
service | No | Service tag |
sumo_logic
Section titled “sumo_logic”{ "url": "https://endpoint1.collection.sumologic.com/receiver/v1/http/your-token"}| Field | Required | Description |
|---|---|---|
url | Yes | HTTP Source URL (authentication embedded in URL) |
cortex_xsiam
Section titled “cortex_xsiam”{ "url": "https://your-xsiam-instance.xdr.paloaltonetworks.com/api/v1/event-collector", "token": "your-xsiam-token"}Cortex XSIAM uses the HEC-compatible ingestion endpoint. The SplunkHECConnector is used internally with the connector ID set to cortex_xsiam_org for log identification.
| Field | Required | Description |
|---|---|---|
url | Yes | XSIAM HEC endpoint URL |
token | Yes | XSIAM ingestion token |
qradar
Section titled “qradar”{ "host": "qradar.example.com", "port": 514, "tls_cert": "/etc/arbitex/certs/qradar-client.pem"}| Field | Required | Description |
|---|---|---|
host | Yes | QRadar syslog receiver hostname or IP |
port | No | Syslog port. Default 514. |
tls_cert | No | Path to TLS client certificate PEM file |
Cache behavior
Section titled “Cache behavior”Per-org configs are loaded with a 60-second TTL cache (_ORG_CONFIG_CACHE). The cache is keyed by org_id and stores a list of SiemConfig ORM objects along with a monotonic timestamp.
- Cache hit: Configs loaded from the in-process cache within the TTL window.
- Cache miss: DB query executed via
SELECT … WHERE org_id = ? AND is_enabled = TRUE. - Invalidation:
invalidate_org_cache(org_id)removes the cache entry. This is called after any create, update, or delete operation on aSiemConfigrow, so changes take effect within one TTL period or immediately on the next miss.
Connector instantiation
Section titled “Connector instantiation”When a config is loaded from the cache, instantiate_connector(connector_type, decrypted_config) is called to build a live SIEMConnector instance. Instantiation failures are logged as errors but do not prevent other connectors from being instantiated or events from being dispatched to healthy connectors.
Delivery status
Section titled “Delivery status”The delivery_status column tracks connector health. Values:
| Status | Meaning |
|---|---|
healthy | Most recent delivery succeeded |
degraded | Recent delivery failures with ongoing retries |
failed | Connector has exhausted retries; dead letter queue active |
last_delivery_at is updated on each successful delivery. Use these fields to monitor per-org connector health and trigger alerts when delivery_status transitions to failed.
Configuring a per-org SIEM connector
Section titled “Configuring a per-org SIEM connector”Configuration is managed via direct database access or the platform admin API (endpoint documented separately). To add a connector for an org:
- Prepare the connector config JSON for the target connector type.
- Encrypt it:
encrypt_config(config_dict)returns a Fernet token string. - Insert a row into
siem_configs:
INSERT INTO siem_configs (org_id, connector_type, config, is_enabled)VALUES ( 'your-org-uuid', 'splunk_hec', 'gAAAAA...', -- Fernet token from encrypt_config() true);- The cache for the org is invalidated automatically by
invalidate_org_cache(org_id)if called after the insert, or expires within 60 seconds otherwise.
Disabling a per-org connector
Section titled “Disabling a per-org connector”Set is_enabled = false on the siem_configs row and call invalidate_org_cache(org_id). The connector is no longer loaded during cache population and is excluded from event dispatch.
See also
Section titled “See also”- SIEM integration overview — global connector configuration and OCSF event format
- Splunk HEC guide — Splunk connector setup
- Microsoft Sentinel guide — Sentinel connector setup
- Elasticsearch guide — Elastic connector setup
- Datadog guide — Datadog connector setup
- Sumo Logic guide — Sumo Logic connector setup