first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
---
title: "Adaptive Load Balancing"
description: "Advanced load balancing algorithms with predictive scaling, health monitoring, and performance optimization for enterprise-grade traffic distribution."
icon: "brain"
---
<Info>
**Looking for comprehensive provider routing documentation?**
For a detailed guide covering how adaptive load balancing works with governance routing, the two-level architecture (provider + key selection), Model Catalog integration, and example scenarios, see the [**Provider Routing Guide**](/providers/provider-routing).
This page focuses on the technical implementation and performance characteristics of adaptive load balancing.
</Info>
## Overview
**Adaptive Load Balancing** in Bifrost Enterprise automatically optimizes traffic distribution across providers and keys based on real-time performance metrics. The system operates at **two levels** - provider selection (direction) and key selection (route) - continuously monitoring error rates, latency, and throughput to dynamically adjust weights, ensuring optimal performance and reliability.
### Key Features
| Feature | Description |
|---------|-------------|
| **Dynamic Weight Adjustment** | Automatically adjusts key weights based on performance metrics |
| **Real-time Performance Monitoring** | Tracks error rates, latency, and success rates per model-key combination |
| **Cross-Node Synchronization** | Gossip protocol ensures consistent weight information across all cluster nodes |
| **Circuit Breaker Integration** | Temporarily removes poorly performing keys from rotation |
| **Fast Recovery** | Momentum-based scoring helps routes recover quickly after transient failures |
<Tip>
**Zero-overhead design**: All route selection logic adds less than **10 microseconds** to hot path latency. Weight calculations happen asynchronously every 5 seconds, so request routing uses pre-computed weights with minimal overhead.
</Tip>
---
## Architecture
The load balancing system operates at two levels:
- **Direction-level** (provider + model): Decides which provider to use for a given model
- **Route-level** (provider + model + key): Decides which API key to use within a provider
This two-tier approach enables both macro-level provider selection and micro-level key optimization.
```mermaid
graph TB
Request["Incoming Request<br/>model: gpt-4"]
subgraph DirectionSelection["Direction Selection"]
DS["Provider Selector<br/>Score-based selection"]
DP1["OpenAI<br/>score: 0.92"]
DP2["Azure<br/>score: 0.85"]
DP3["Anthropic<br/>score: 0.78"]
end
subgraph RouteSelection["Route Selection"]
RS["Key Selector<br/>Weighted random"]
K1["Key 1<br/>weight: 850"]
K2["Key 2<br/>weight: 620"]
K3["Key 3<br/>weight: 45"]
end
subgraph Tracker["Metrics Tracker"]
T["Real-time Metrics<br/>5-second recomputation"]
M1["Error Rate"]
M2["Latency Score"]
M3["Utilization"]
end
Request --> DS
DS --> DP1 & DP2 & DP3
DP1 --> RS
RS --> K1 & K2 & K3
K1 --> Response["API Response"]
Response --> T
T --> M1 & M2 & M3
M1 & M2 & M3 -.->|"Update Weights"| DS & RS
```
---
## How Weight Calculation Works
Every 5 seconds, the system recalculates weights for all routes based on four factors:
| Factor | Weight | Purpose |
|--------|--------|---------|
| **Error Penalty** | 50% | Penalizes routes with high error rates |
| **Latency Score** | 20% | Penalizes routes with abnormally slow responses |
| **Utilization Score** | 5% | Prevents overloading high-performing routes |
| **Momentum Bias** | Additive | Rewards routes that are recovering well |
The system combines these into a single score, then converts it to a weight between 1 and 1000. Lower penalties mean higher weights, which means more traffic.
$$
Score = (P_{error} \times 0.5) + (P_{latency} \times 0.2) + (P_{util} \times 0.05) - M_{momentum}
$$
$$
Weight = W_{min} + (1 - Score) \times (W_{max} - W_{min})
$$
```mermaid
flowchart LR
subgraph Inputs["Raw Metrics"]
E["Error Rate"]
L["Latency"]
U["Utilization"]
M["Momentum"]
end
subgraph Scoring["Score Computation"]
EP["Error Penalty<br/>50% weight"]
LP["Latency Score<br/>20% weight"]
US["Utilization Score<br/>5% weight"]
MS["Momentum Bias"]
end
subgraph Output["Final Weight"]
NS["Normalized Score"]
FW["Route Weight<br/>1 - 1000"]
end
E --> EP
L --> LP
U --> US
M --> MS
EP & LP & US --> NS
MS --> NS
NS --> FW
```
---
## Key Capabilities
1. **Automatic Route Health Management**: Routes automatically transition between 4 states (Healthy, Degraded, Failed, Recovering) based on error rates and latency. No manual intervention required when a route fails or recovers.
2. **Fair Traffic Distribution**: The system prevents any single route from being overloaded while still favoring better performers. Low-weight routes always get minimum traffic to prove recovery.
3. **Real-time Dashboard**: Provides visibility into weight distribution, performance metrics (error rates, latency), state transitions, and actual vs expected traffic per route.
<Frame>
<img src="/media/ui-load-balancing.png" alt="Adaptive Load Balancing Dashboard" />
</Frame>
4. **Multi-Factor Scoring**: Routes are scored using 4 components - Error Penalty (50% weight, time-decayed), Latency Score (token-aware via MV-TACOS algorithm), Utilization Score (fair-share balancing), and Momentum (accelerates recovery after failures).
5. **Smart Key Selection**: Uses weighted random selection with jitter (5% band) and 25% exploration probability to probe potentially recovered routes, rather than always picking the best route.
6. **Performance Thresholds**: Specific triggers drive state transitions —&gt; 2% error rate triggers Degraded, &gt;5% error rate or TPM hit triggers Failed, &lt;2% error with 50%+ expected traffic triggers Healthy.
<Tip>
The system is designed to be self-healing: it penalizes failing routes quickly, but also enables fast recovery (90% penalty reduction in 30 seconds) once issues are fixed.
</Tip>
---
## Next Steps
<Steps>
<Step title="Enable Adaptive Load Balancing">
Contact your Bifrost Enterprise representative to enable adaptive load balancing for your deployment
</Step>
<Step title="Monitor Weight Distribution">
Use the dashboard to observe how weights adapt to real traffic patterns
</Step>
<Step title="Analyze Performance">
Review route state transitions and weight adjustments to understand system behavior
</Step>
</Steps>

View File

@@ -0,0 +1,402 @@
---
title: "Getting started"
description: "Advanced governance features with enhanced security, compliance reporting, audit trails, and enterprise-grade access controls for large-scale deployments."
icon: "play"
---
## Overview
Enterprise Governance extends Bifrost's [core governance capabilities](../features/governance) with advanced security, compliance, and user management features designed for large-scale enterprise deployments. This module provides comprehensive identity management, regulatory compliance, and detailed audit capabilities.
**Enterprise Extensions:**
- **Identity & Access Management** - OpenID Connect integration with Okta and Microsoft Entra
- **User-Level Governance** - Individual user authentication and budget allocation
- **[Role-Based Access Control](./rbac)** - Fine-grained permissions with custom roles and resource-level controls
- **Team Synchronization** - Automatic team membership based on identity provider groups
- **Compliance Framework** - SOC 2 Type II, GDPR, ISO 27001, and HIPAA compliance
- **Advanced Auditing** - Comprehensive audit reports and compliance dashboards
**Builds Upon Core Governance:**
- All standard [Virtual Keys, Teams, and Customers](../features/governance) functionality
- Hierarchical budget management and rate limiting
- Model and provider access controls
- Usage tracking and cost management
---
## Identity Provider Integration
Bifrost Enterprise supports OpenID Connect (OIDC) integration with popular identity providers for single sign-on (SSO) authentication. Users are automatically provisioned on first login, with roles and team memberships synchronized from your identity provider.
**Supported Identity Providers:**
<CardGroup cols={2}>
<Card title="Okta" icon="key" href="/enterprise/setting-up-okta">
Full OIDC integration with custom roles and group sync.
</Card>
<Card title="Microsoft Entra ID" icon="microsoft" href="/enterprise/setting-up-entra">
Azure AD integration with app roles and group claims.
</Card>
</CardGroup>
**Key Features:**
- **Automatic User Provisioning** - Users are created on first SSO login
- **Role Synchronization** - Admin, Developer, and Viewer roles mapped from identity provider
- **Team Membership** - Groups from your identity provider automatically create and sync teams
- **Secure Token Handling** - JWT validation with automatic token refresh
### Role Hierarchy
Bifrost uses a three-tier role hierarchy that maps to your identity provider roles:
| Role | Privilege Level | Description |
|------|-----------------|-------------|
| **Admin** | Highest | Full access to all Bifrost features and settings |
| **Developer** | Medium | Access to development features, API keys, and logs |
| **Viewer** | Lowest | Read-only access to dashboards and reports |
When a user has multiple roles, Bifrost automatically assigns the highest privilege role.
For detailed information on managing roles and permissions, including creating custom roles and assigning granular permissions, see [Role-Based Access Control](./rbac).
### Configuration
Identity provider configuration is done through the Bifrost UI:
1. Navigate to **Governance** → **User Provisioning** in the Bifrost dashboard
2. Select your identity provider (Okta or Microsoft Entra)
3. Enter the required credentials from your identity provider
4. Enable the provider and save
For detailed setup instructions, see the provider-specific guides:
- **[Setting up Okta](./setting-up-okta)**
- **[Setting up Microsoft Entra](./setting-up-entra)**
---
## User-Level Authentication & Budgeting
Enterprise Governance extends the hierarchical governance model to include individual user-level controls, providing granular access management and personalized budget allocation.
### User Management
**Enhanced Hierarchy:**
```
Customer (organization-level budget)
Team (department-level budget)
User (individual-level budget + authentication)
Virtual Key (API-level budget + rate limits)
```
**User Features:**
- **Individual Authentication** - SSO-based login credentials
- **Personal Budgets** - User-specific cost allocation
- **Access Controls** - Per-user model and provider restrictions
- **Usage Tracking** - Individual consumption monitoring
- **Audit Trails** - User-specific activity logging
### User Authentication Flow
**SSO Authentication:**
```bash
# 1. User visits Bifrost login page
# 2. Redirected to identity provider (Okta/Entra)
# 3. After successful authentication, redirected back with tokens
# 4. Use access token for API requests
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'
```
**Virtual Key with User Context:**
```bash
# Use virtual key with user tracking
curl -X POST http://localhost:8080/v1/chat/completions \
-H "x-bf-vk: vk-alice-personal" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'
```
---
## Compliance Framework
Enterprise Governance includes built-in compliance capabilities for major regulatory frameworks including **SOC 2 Type II**, **GDPR**, **ISO 27001**, and **HIPAA** compliance. These features provide automated compliance monitoring, policy enforcement, and audit trail generation to meet enterprise security and regulatory requirements.
---
## Audit Reports & Compliance Dashboards
Enterprise Governance provides comprehensive audit reporting and compliance dashboards for regulatory requirements and internal governance.
### Audit Report Types
**1. Access Audit Reports**
- User login/logout activities
- Failed authentication attempts
- Privilege escalation events
- Unusual access patterns
**2. Usage Audit Reports**
- API request tracking
- Model and provider usage
- Budget consumption patterns
- Rate limit violations
**3. Data Audit Reports**
- Data access and modification
- Data export activities
- Data deletion requests
- Consent management tracking
**4. Compliance Reports**
- SOC 2 Type II control evidence
- GDPR compliance status
- ISO 27001 risk assessments
- HIPAA safeguard compliance
### Report Generation
<Tabs group="audit-reports">
<Tab title="Web UI">
1. **Navigate to Audit Reports**
- Go to **Enterprise** → **Audit & Compliance**
- Select **Generate Report**
2. **Report Configuration**
**Report Type:**
- **Access Report**: Authentication and authorization events
- **Usage Report**: API consumption and cost analysis
- **Compliance Report**: Regulatory compliance status
- **Security Report**: Security events and incidents
**Date Range:**
- **Last 24 Hours**: Recent activity
- **Last 7 Days**: Weekly summary
- **Last 30 Days**: Monthly analysis
- **Custom Range**: Specific date range
**Filters:**
- **Users**: Specific users or all users
- **Teams**: Specific teams or all teams
- **Customers**: Specific customers or all customers
- **Event Types**: Filter by event categories
**Export Options:**
- **PDF**: Formatted compliance report
- **CSV**: Raw data for analysis
- **JSON**: Structured data export
</Tab>
<Tab title="API">
**Generate Access Audit Report:**
```bash
curl -X POST http://localhost:8080/api/enterprise/audit/reports \
-H "Content-Type: application/json" \
-d '{
"report_type": "access_audit",
"date_range": {
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z"
},
"filters": {
"users": ["user-alice-001", "user-bob-002"],
"event_types": ["login", "logout", "failed_login", "privilege_escalation"]
},
"format": "pdf",
"include_summary": true
}'
```
**Generate Usage Audit Report:**
```bash
curl -X POST http://localhost:8080/api/enterprise/audit/reports \
-H "Content-Type: application/json" \
-d '{
"report_type": "usage_audit",
"date_range": {
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z"
},
"filters": {
"customers": ["customer-corp"],
"models": ["gpt-4o", "claude-3-sonnet-20240229"],
"providers": ["openai", "anthropic"]
},
"format": "csv",
"include_cost_analysis": true
}'
```
**Generate Compliance Report:**
```bash
curl -X POST http://localhost:8080/api/enterprise/audit/reports \
-H "Content-Type: application/json" \
-d '{
"report_type": "compliance",
"compliance_framework": "soc2_type2",
"date_range": {
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z"
},
"control_objectives": ["security", "availability", "confidentiality"],
"format": "pdf",
"include_evidence": true
}'
```
</Tab>
</Tabs>
### Compliance Dashboards
**Real-Time Monitoring:**
- **Security Posture**: Current security status and alerts
- **Compliance Status**: Regulatory compliance health check
- **Risk Assessment**: Identified risks and mitigation status
- **Audit Trail**: Recent audit events and activities
**Dashboard Widgets:**
```bash
curl -X GET http://localhost:8080/api/enterprise/dashboard/compliance \
-H "Authorization: Bearer admin-token"
# Response includes:
{
"security_posture": {
"overall_score": 95,
"active_alerts": 2,
"failed_logins_24h": 5,
"privilege_escalations": 0
},
"compliance_status": {
"soc2_type2_compliance": "compliant",
"gdpr_compliance": "compliant",
"iso27001_compliance": "in_progress",
"hipaa_compliance": "not_applicable"
},
"risk_assessment": {
"high_risk_items": 0,
"medium_risk_items": 3,
"low_risk_items": 12,
"mitigation_progress": "85%"
},
"recent_activities": [
{
"timestamp": "2024-01-15T10:30:00Z",
"type": "user_login",
"user": "alice@company.com",
"status": "success"
}
]
}
```
### Automated Compliance Monitoring
**Continuous Monitoring:**
```bash
curl -X POST http://localhost:8080/api/enterprise/compliance/monitoring \
-H "Content-Type: application/json" \
-d '{
"monitoring_rules": [
{
"name": "Failed Login Monitoring",
"type": "security_event",
"condition": "failed_logins > 10 in 1h",
"action": "alert_security_team",
"severity": "high"
},
{
"name": "Data Export Monitoring",
"type": "data_access",
"condition": "data_export_size > 1GB",
"action": "require_approval",
"severity": "medium"
},
{
"name": "Budget Threshold Alert",
"type": "budget_usage",
"condition": "usage > 80% of budget",
"action": "notify_manager",
"severity": "low"
}
],
"notification_channels": {
"email": ["security@company.com", "compliance@company.com"],
"slack": "#security-alerts",
"webhook": "https://company.com/security-webhook"
}
}'
```
---
## Error Responses
Enterprise Governance extends standard governance errors with additional authentication and compliance-related responses:
**Authentication Errors:**
```json
{
"error": {
"type": "authentication_required",
"message": "SSO authentication required"
}
}
```
```json
{
"error": {
"type": "mfa_required",
"message": "Multi-factor authentication required"
}
}
```
**Authorization Errors:**
```json
{
"error": {
"type": "user_not_authorized",
"message": "User does not have permission to access this model"
}
}
```
**Compliance Errors:**
```json
{
"error": {
"type": "compliance_violation",
"message": "Request violates GDPR data minimization requirements"
}
}
```
---
## Next Steps
- **[Role-Based Access Control](./rbac)** - Manage roles and fine-grained permissions
- **[Setting up Okta](./setting-up-okta)** - Configure Okta as your identity provider
- **[Setting up Microsoft Entra](./setting-up-entra)** - Configure Microsoft Entra ID as your identity provider
- **[Core Governance](../features/governance)** - Understand base governance concepts
- **[Clustering](./clustering)** - Deploy enterprise governance across multiple nodes
- **[Vault Support](./vault-support)** - Secure credential management
- **[Custom Plugins](./custom-plugins)** - Extend enterprise governance capabilities

View File

@@ -0,0 +1,342 @@
---
title: "Audit Logs"
description: "Comprehensive security and compliance audit logging with detailed tracking of authentication, authorization, configuration changes, and data access for enterprise governance and regulatory requirements."
icon: "scroll"
---
## Overview
**Audit Logs** in Bifrost provide complete visibility into security-critical events, user activities, configuration changes, and data access patterns. Enterprise audit logging ensures compliance with regulatory requirements including SOC 2, GDPR, HIPAA, and ISO 27001 through comprehensive, immutable audit trails.
### Key Features
| Feature | Description |
|---------|-------------|
| **Immutable Logs** | Tamper-proof audit trails with cryptographic verification |
| **Real-Time Capture** | Instant logging of all security-relevant events |
| **Granular Filtering** | Query by user, action, resource, or time range |
| **Long-Term Retention** | Configurable retention policies for compliance |
| **SIEM Integration** | Export to Splunk, Datadog, Elastic, and more |
| **Alert Triggers** | Automated alerts on suspicious activities |
---
## What Gets Logged
### Authentication Events
- User login (successful/failed)
- User logout
- Session creation/expiration
- MFA verification
- Password changes
- Failed authentication attempts
- Account lockouts
- SSO redirects
### Authorization Events
- Model access attempts
- Provider access checks
- Virtual key usage
- Budget limit checks
- Rate limit violations
- Permission denials
### Configuration Changes
- Virtual key creation/modification/deletion
- Team/customer creation/updates
- User provisioning/deprovisioning
- Budget adjustments
- Rate limit changes
- Provider key updates
- Guardrail configuration changes
- SCIM/OIDC settings updates
### Data Access Events
- PII detection and handling
- Data export operations
- Log access and queries
- Sensitive configuration access
- API key exposure attempts
### Security Events
- Prompt injection attempts
- Jailbreak attempts
- Unusual access patterns
- Multiple failed authentication attempts
- API key abuse
- Rate limit violations
- Suspicious IP addresses
- Guardrail violations
---
## Configuration
### Basic Audit Logging Setup
<Tabs group="audit-config">
<Tab title="config.json">
```json
{
"audit_logs": {
"disabled": false,
"hmac_key": "env.AUDIT_HMAC_KEY",
"retention_days": 365
}
}
```
</Tab>
<Tab title="Environment Variables">
```bash
# Enable audit logging
BIFROST_AUDIT_LOGS_ENABLED=true
# Retention settings
BIFROST_AUDIT_RETENTION_DAYS=365
BIFROST_AUDIT_ARCHIVE_DAYS=90
# Event capture
BIFROST_AUDIT_AUTH_EVENTS=true
BIFROST_AUDIT_CONFIG_CHANGES=true
BIFROST_AUDIT_SECURITY_EVENTS=true
# Immutability
BIFROST_AUDIT_IMMUTABLE=true
```
</Tab>
</Tabs>
### Configuration Fields
| Field | Type | Description |
|-------|------|-------------|
| `disabled` | boolean | When `true`, audit logging is turned off. Default: `false`. |
| `hmac_key` | string | HMAC secret key used to sign audit events. Minimum 32 bytes. Supports `env.` prefix for environment variables (e.g. `env.AUDIT_HMAC_KEY`). |
| `retention_days` | integer | Days to retain audit log entries. `0` disables retention-based cleanup. |
---
## Querying Audit Logs
### API-Based Queries
**Query Authentication Events:**
```bash
curl -X GET "http://localhost:8080/api/audit-logs?event_type=authentication&start_date=2024-01-01&end_date=2024-01-31" \
-H "Authorization: Bearer admin-token"
```
**Query by User:**
```bash
curl -X GET "http://localhost:8080/api/audit-logs?user_id=user-alice-001&limit=100" \
-H "Authorization: Bearer admin-token"
```
**Query Failed Access Attempts:**
```bash
curl -X GET "http://localhost:8080/api/audit-logs?action=access_denied&severity=high" \
-H "Authorization: Bearer admin-token"
```
**Query Configuration Changes:**
```bash
curl -X GET "http://localhost:8080/api/audit-logs?event_type=configuration_change&resource_type=virtual_key" \
-H "Authorization: Bearer admin-token"
```
### Advanced Filtering
```bash
curl -X POST http://localhost:8080/api/audit-logs/query \
-H "Content-Type: application/json" \
-H "Authorization: Bearer admin-token" \
-d '{
"filters": {
"event_types": ["authentication", "authorization"],
"date_range": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
},
"actors": {
"user_ids": ["user-alice-001", "user-bob-002"],
"ip_addresses": ["203.0.113.0/24"]
},
"status": ["failed", "blocked"],
"severity": ["medium", "high", "critical"]
},
"sort": {
"field": "timestamp",
"order": "desc"
},
"limit": 1000,
"include_details": true
}'
```
### Response Format
```json
{
"total_count": 347,
"returned_count": 100,
"page": 1,
"audit_logs": [
{
"event_id": "evt_001",
"timestamp": "2024-01-15T10:30:00.123Z",
"event_type": "authentication",
"action": "user_login",
"status": "failed",
"severity": "medium",
"actor": {
"user_id": "user-alice-001",
"email": "alice@company.com",
"ip_address": "203.0.113.42"
},
"details": {
"auth_method": "password",
"failure_reason": "invalid_password",
"attempts_count": 3
},
"verification": {
"hash": "sha256:abc123...",
"verified": true
}
}
],
"next_page": "/api/enterprise/audit-logs?page=2"
}
```
---
## SIEM Integration
### Splunk Integration
```json
{
"audit_logs": {
"siem_integration": {
"splunk": {
"enabled": true,
"hec_endpoint": "https://splunk.company.com:8088/services/collector",
"hec_token": "${SPLUNK_HEC_TOKEN}",
"source_type": "bifrost:audit",
"index": "security",
"batch_size": 100,
"flush_interval": "10s"
}
}
}
}
```
### Datadog Integration
```json
{
"audit_logs": {
"siem_integration": {
"datadog": {
"enabled": true,
"api_key": "${DATADOG_API_KEY}",
"site": "datadoghq.com",
"service": "bifrost",
"tags": ["env:production", "team:security"]
}
}
}
}
```
### Elastic Security Integration
```json
{
"audit_logs": {
"siem_integration": {
"elastic": {
"enabled": true,
"endpoint": "https://elastic.company.com:9200",
"api_key": "${ELASTIC_API_KEY}",
"index": "bifrost-audit-logs",
"pipeline": "security-enrichment"
}
}
}
}
```
### Webhook Integration
```json
{
"audit_logs": {
"webhooks": {
"enabled": true,
"endpoints": [
{
"name": "security_incidents",
"url": "https://security.company.com/webhooks/audit",
"auth": {
"type": "bearer",
"token": "${WEBHOOK_AUTH_TOKEN}"
},
"filters": {
"event_types": ["security_incident"],
"severity": ["high", "critical"]
},
"retry": {
"max_attempts": 3,
"backoff": "exponential"
}
}
]
}
}
}
```
---
## Compliance Reporting
### Generate Audit Reports
```bash
curl -X POST http://localhost:8080/api/enterprise/audit-logs/reports \
-H "Content-Type: application/json" \
-H "Authorization: Bearer admin-token" \
-d '{
"report_type": "compliance_audit",
"compliance_framework": "soc2_type2",
"date_range": {
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-03-31T23:59:59Z"
},
"include_sections": [
"authentication_events",
"authorization_events",
"configuration_changes",
"security_incidents"
],
"format": "pdf",
"include_evidence": true
}'
```
### Report Types
| Report Type | Description | Use Case |
|------------|-------------|----------|
| **Access Audit** | All user authentication and access events | SOC 2, ISO 27001 |
| **Change Audit** | Configuration and permission changes | Change management |
| **Security Audit** | Security incidents and violations | Security reviews |
| **Compliance Report** | Framework-specific compliance evidence | Regulatory audits |
| **User Activity** | Individual user activity summary | HR investigations |

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
---
title: "Custom Plugins"
description: "Build and deploy enterprise-specific plugins to extend Bifrost's functionality with custom business logic, integrations, and workflow automation."
icon: "plug"
---
At Bifrost, we understand that every organization has unique requirements for their LLM infrastructure, workflows, and AI-specific business logic that can't always be addressed by off-the-shelf solutions. That's why we offer comprehensive custom plugin development services to help companies extend Bifrost's LLM gateway functionality with tailored solutions that perfectly fit their specific AI and machine learning needs.
Our expert team works closely with your organization to design, develop, and deploy custom plugins that integrate seamlessly with your LLM infrastructure and AI workflows. We handle everything from initial consultation to ongoing maintenance.
- **Custom AI Business Logic Implementation** - Embed your unique AI governance rules and LLM processing logic directly into Bifrost
- **LLM Provider Integrations** - Connect Bifrost with proprietary or specialized LLM providers and AI services
- **AI Workflow Automation** - Automate complex multi-step LLM processes specific to your AI use cases
- **AI Security & Compliance Extensions** - Implement custom AI safety policies, content filtering, and compliance requirements
- **LLM Performance Optimization** - Build plugins optimized for your specific LLM workloads and scaling requirements

View File

@@ -0,0 +1,548 @@
---
title: "Datadog"
description: "Native Datadog integration for APM traces, LLM Observability, and metrics"
icon: "dog"
---
## Overview
<Frame>
<img src="/media/dd-trace.png" alt="Datadog LLM Observability dashboard" />
</Frame>
The **Datadog plugin** provides native integration with the Datadog observability platform, offering three pillars of observability for your LLM operations:
- **APM Traces** - Distributed tracing via dd-trace-go v2 with W3C Trace Context support for end-to-end request visibility
- **LLM Observability** - Native Datadog LLM Obs integration for AI/ML-specific monitoring
- **Metrics** - Operational metrics via DogStatsD or the Metrics API
Unlike the [OTel plugin](/features/observability/otel) which sends generic OpenTelemetry data, the Datadog plugin leverages Datadog's native SDKs for richer integration with Datadog-specific features like LLM Observability dashboards and ML App grouping.
---
## Deployment Modes
<Frame>
<img src="/media/dd-mode.png" alt="Datadog LLM Observability dashboard" />
</Frame>
The plugin supports two deployment modes:
| Mode | Description | Requirements | Best For |
|------|-------------|--------------|----------|
| **Agent** (default) | Sends data through a local Datadog Agent | Datadog Agent running on host | Production deployments with existing agent infrastructure |
| **Agentless** | Sends data directly to Datadog APIs | API key only | Serverless, containers, or simplified deployments |
### Agent Mode
In agent mode, the plugin communicates with a locally running Datadog Agent:
- **APM Traces** → Agent at `localhost:8126`
- **Metrics** → DogStatsD at `localhost:8125`
The agent handles batching, retries, and provides lower latency. This is the recommended mode for production deployments where you already have the Datadog Agent installed.
### Agentless Mode
In agentless mode, the plugin sends data directly to Datadog's intake APIs:
- **APM Traces** → `https://trace.agent.{site}`
- **LLM Observability** → Direct API submission
- **Metrics** → Datadog Metrics API
This mode requires an API key but simplifies deployment by eliminating the need for a local agent. Ideal for serverless environments, Kubernetes pods, or quick testing.
---
## Configuration
### Required Fields
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `service_name` | `string` | No | `bifrost` | Service name displayed in Datadog APM |
| `ml_app` | `string` | No | (uses `service_name`) | ML application name for LLM Observability grouping |
| `agent_addr` | `string` | No | `localhost:8126` | Datadog Agent address (agent mode only) |
| `dogstatsd_addr` | `string` | No | `localhost:8125` | DogStatsD server address (agent mode only) |
| `env` | `string` | No | - | Environment tag (e.g., `production`, `staging`) |
| `version` | `string` | No | - | Service version tag |
| `custom_tags` | `object` | No | - | Additional tags for all traces and metrics |
| `enable_metrics` | `bool` | No | `true` | Enable metrics emission |
| `enable_traces` | `bool` | No | `true` | Enable APM traces |
| `enable_llm_obs` | `bool` | No | `true` | Enable LLM Observability |
| `agentless` | `bool` | No | `false` | Use agentless mode (direct API) |
| `api_key` | `EnvVar` | Agentless only | - | Datadog API key (supports `env.VAR_NAME`) |
| `site` | `string` | No | `datadoghq.com` | Datadog site/region |
### Environment Variable Substitution
The `api_key` and `custom_tags` fields support environment variable substitution using the `env.` prefix:
```json
{
"api_key": "env.DD_API_KEY",
"custom_tags": {
"team": "env.TEAM_NAME",
"cost_center": "env.COST_CENTER"
}
}
```
---
## Setup
<Tabs group="setup-method">
<Tab title="UI">
<Frame>
<img src="/media/dd-config-page.png" alt="Datadog LLM Observability dashboard" />
</Frame>
Configure the Datadog plugin through the Bifrost UI:
1. Navigate to **Settings** → **Plugins**
2. Enable the **Datadog** plugin
3. Configure the required fields based on your deployment mode
{/* Screenshot placeholder - user will add */}
</Tab>
<Tab title="Go SDK">
```go
package main
import (
"context"
bifrost "github.com/maximhq/bifrost/core"
"github.com/maximhq/bifrost/core/schemas"
"github.com/maximhq/bifrost/framework/modelcatalog"
datadog "github.com/maximhq/bifrost-enterprise/plugins/datadog"
)
func main() {
ctx := context.Background()
logger := schemas.NewLogger()
// Initialize model catalog (required for cost calculation)
modelCatalog := modelcatalog.NewModelCatalog(logger)
// Agent mode configuration
ddPlugin, err := datadog.Init(ctx, &datadog.Config{
ServiceName: "my-llm-service",
Env: "production",
Version: "1.0.0",
CustomTags: map[string]string{
"team": "platform",
},
}, logger, modelCatalog, "1.0.0")
if err != nil {
panic(err)
}
// Initialize Bifrost with the plugin
client, err := bifrost.Init(ctx, schemas.BifrostConfig{
Account: &yourAccount,
Plugins: []schemas.Plugin{ddPlugin},
})
if err != nil {
panic(err)
}
defer client.Shutdown()
// All requests are now traced to Datadog
}
```
For agentless mode:
```go
// Agentless mode configuration
enableAgentless := true
ddPlugin, err := datadog.Init(ctx, &datadog.Config{
ServiceName: "my-llm-service",
Env: "production",
Agentless: &enableAgentless,
APIKey: &schemas.EnvVar{EnvVarName: "DD_API_KEY"},
Site: "datadoghq.com",
}, logger, modelCatalog, "1.0.0")
```
</Tab>
<Tab title="config.json">
### Agent Mode (Minimal)
```json
{
"plugins": [
{
"enabled": true,
"name": "datadog",
"config": {
"service_name": "bifrost",
"env": "production"
}
}
]
}
```
### Agent Mode (Full Configuration)
```json
{
"plugins": [
{
"enabled": true,
"name": "datadog",
"config": {
"service_name": "my-llm-gateway",
"ml_app": "my-ml-application",
"agent_addr": "localhost:8126",
"dogstatsd_addr": "localhost:8125",
"env": "production",
"version": "1.2.3",
"custom_tags": {
"team": "platform",
"cost_center": "env.COST_CENTER"
},
"enable_metrics": true,
"enable_traces": true,
"enable_llm_obs": true
}
}
]
}
```
### Agentless Mode
```json
{
"plugins": [
{
"enabled": true,
"name": "datadog",
"config": {
"service_name": "my-llm-gateway",
"env": "production",
"agentless": true,
"api_key": "env.DD_API_KEY",
"site": "datadoghq.com"
}
}
]
}
```
Set the environment variable:
```bash
export DD_API_KEY="your-datadog-api-key"
```
</Tab>
</Tabs>
---
## Datadog Sites
The plugin supports all Datadog regional sites. Set the `site` field to match your Datadog account region:
| Site | Region | Value |
|------|--------|-------|
| US1 (default) | United States | `datadoghq.com` |
| US3 | United States | `us3.datadoghq.com` |
| US5 | United States | `us5.datadoghq.com` |
| EU1 | Europe | `datadoghq.eu` |
| AP1 | Asia Pacific (Japan) | `ap1.datadoghq.com` |
| AP2 | Asia Pacific (Australia) | `ap2.datadoghq.com` |
| US1-FED | US Government | `ddog-gov.com` |
<Note>
Ensure your API key corresponds to the selected site. API keys from one region will not work with another.
</Note>
---
## LLM Observability
<Frame>
<img src="/media/dd-llmobs.png" alt="Datadog LLM Observability dashboard" />
</Frame>
The Datadog plugin integrates with [Datadog LLM Observability](https://docs.datadoghq.com/llm_observability/) to provide AI/ML-specific monitoring capabilities.
### ML App Grouping
LLM traces are grouped under an **ML App** in Datadog. By default, this uses your `service_name`, but you can specify a dedicated ML App name:
```json
{
"service_name": "bifrost-gateway",
"ml_app": "customer-support-ai"
}
```
This allows you to:
- Group related LLM operations across multiple services
- Track costs and performance by application
- Apply ML-specific alerts and dashboards
### Session Tracking
The plugin supports session tracking via the `x-bf-session-id` header. Include this header in your requests to group related LLM calls into a conversation session:
```bash
curl -X POST https://your-bifrost-gateway/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "x-bf-session-id: user-123-session-456" \
-d '{...}'
```
Sessions appear in Datadog LLM Observability, allowing you to trace entire conversation flows.
### W3C Distributed Tracing
The plugin supports [W3C Trace Context](https://www.w3.org/TR/trace-context/) for distributed tracing across services. When your upstream service sends a `traceparent` header, Bifrost automatically links its spans as children of the parent trace.
```bash
curl -X POST https://your-bifrost-gateway/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" \
-d '{...}'
```
This enables:
- **End-to-end visibility** - See LLM calls in the context of your full application trace
- **Cross-service correlation** - Link frontend requests → backend services → Bifrost → LLM providers
- **Latency attribution** - Understand how LLM latency contributes to overall request time
The `traceparent` header format follows the W3C standard:
```
traceparent: {version}-{trace-id}-{parent-id}-{trace-flags}
```
All Datadog APM spans created by Bifrost will be linked to the parent span, appearing as children in the Datadog trace view.
### What's Captured
For each LLM operation, the plugin sends to LLM Observability:
- **Input/Output Messages** - Full conversation history with role attribution
- **Token Usage** - Input, output, and total token counts
- **Cost** - Calculated cost in USD based on model pricing
- **Latency** - Request duration and time-to-first-token for streaming
- **Model Info** - Provider, model name, and request parameters
- **Tool Calls** - Function/tool call details for agentic workflows
---
## Metrics Reference
The plugin emits the following metrics to Datadog:
| Metric | Type | Description | Tags |
|--------|------|-------------|------|
| `bifrost.requests.total` | Counter | Total LLM requests | provider, model, request_type |
| `bifrost.success.total` | Counter | Successful requests | provider, model, request_type |
| `bifrost.errors.total` | Counter | Failed requests | provider, model, request_type, reason |
| `bifrost.latency.seconds` | Histogram | Request latency distribution | provider, model, request_type |
| `bifrost.tokens.input` | Counter | Input/prompt tokens consumed | provider, model |
| `bifrost.tokens.output` | Counter | Output/completion tokens generated | provider, model |
| `bifrost.tokens.total` | Counter | Total tokens (input + output) | provider, model |
| `bifrost.cost.usd` | Gauge | Request cost in USD | provider, model |
| `bifrost.cache.hits` | Counter | Cache hits | provider, model, cache_type |
| `bifrost.stream.first_token_latency` | Histogram | Time to first token (streaming) | provider, model |
| `bifrost.stream.inter_token_latency` | Histogram | Inter-token latency (streaming) | provider, model |
### Custom Tags
All metrics include your configured `custom_tags` plus automatic tags for:
- `provider` - LLM provider (openai, anthropic, etc.)
- `model` - Model name
- `request_type` - Type of request (chat, embedding, etc.)
- `env` - Environment from configuration
---
## Captured Data
Each APM trace includes comprehensive LLM operation metadata:
### Span Attributes
- **Span Name** - Based on request type (`genai.chat`, `genai.embedding`, etc.)
- **Service Info** - `service.name`, `service.version`, `env`
- **Provider & Model** - `gen_ai.provider.name`, `gen_ai.request.model`
### Request Parameters
- Temperature, max_tokens, top_p, stop sequences
- Presence/frequency penalties
- Tool configurations and parallel tool calls
- Custom parameters via `ExtraParams`
### Input/Output Data
- Complete chat history with role-based messages
- Prompt text for completions
- Response content with role attribution
- Tool calls and results
- Reasoning and refusal content (when present)
### Performance Metrics
- Token usage (prompt, completion, total)
- Cost calculations in USD
- Latency and timing (start/end timestamps)
- Time to first token (streaming)
- Error details with status codes
### Bifrost Context
- Virtual key ID and name
- Selected key ID and name
- Team ID and name
- Customer ID and name
- Retry count and fallback index
---
## Supported Request Types
The Datadog plugin captures all Bifrost request types:
| Request Type | Span Name | LLM Obs Type |
|--------------|-----------|--------------|
| Chat Completion | `genai.chat` | LLM Span |
| Chat Completion (streaming) | `genai.chat` | LLM Span |
| Text Completion | `genai.text` | LLM Span |
| Text Completion (streaming) | `genai.text` | LLM Span |
| Embeddings | `genai.embedding` | Embedding Span |
| Speech Generation | `genai.speech` | Task Span |
| Speech Generation (streaming) | `genai.speech` | Task Span |
| Transcription | `genai.transcription` | Task Span |
| Transcription (streaming) | `genai.transcription` | Task Span |
| Responses API | `genai.responses` | LLM Span |
| Responses API (streaming) | `genai.responses` | LLM Span |
---
## When to Use
### Datadog Plugin
Choose the Datadog plugin when you:
- Use Datadog as your primary observability platform
- Want native LLM Observability integration with ML App grouping
- Need seamless correlation with existing Datadog APM traces via W3C distributed tracing
- Require Datadog-specific features like notebooks and dashboards
- Want session tracking for conversation flows
### vs. OTel Plugin
Use the [OTel plugin](/features/observability/otel) when you:
- Need multi-vendor observability (send to multiple backends)
- Are using Datadog via an OpenTelemetry Collector
- Want vendor flexibility to switch backends without code changes
- Prefer standardized OpenTelemetry semantic conventions
<Note>
You can use both plugins simultaneously if needed. The Datadog plugin provides native integration while OTel can send to additional backends.
</Note>
### vs. Built-in Observability
Use [Built-in Observability](/features/observability/default) for:
- Local development and testing
- Simple self-hosted deployments
- No external dependencies required
- Direct database access to logs
---
## Troubleshooting
### Agent Connectivity Issues
Verify the Datadog Agent is running and accessible:
```bash
# Check agent status
datadog-agent status
# Test APM endpoint
curl -v http://localhost:8126/info
# Test DogStatsD (should accept UDP packets)
echo "test.metric:1|c" | nc -u -w1 localhost 8125
```
### Agentless Mode Not Working
1. Verify your API key is valid:
```bash
curl -X GET "https://api.datadoghq.com/api/v1/validate" \
-H "DD-API-KEY: $DD_API_KEY"
```
2. Ensure the `site` matches your API key's region
3. Check that the API key environment variable is set:
```bash
echo $DD_API_KEY
```
### Missing Traces
1. Enable debug logging in Bifrost:
```bash
bifrost-http --log-level debug
```
2. Verify traces are enabled in your configuration:
```json
{
"enable_traces": true,
"enable_llm_obs": true
}
```
3. Check for errors in the Bifrost logs related to the Datadog plugin
### Missing Metrics
1. Verify DogStatsD is running (agent mode):
```bash
datadog-agent status | grep DogStatsD
```
2. Ensure metrics are enabled:
```json
{
"enable_metrics": true
}
```
3. For agentless mode, verify your API key has metrics submission permissions
### LLM Observability Not Appearing
1. LLM Observability requires `enable_llm_obs: true` (default)
2. Verify your Datadog plan includes LLM Observability
3. Check the ML App name in Datadog under **LLM Observability** → **Applications**
---
## Next Steps
- **[OTel Plugin](/features/observability/otel)** - OpenTelemetry integration for multi-vendor observability
- **[Built-in Observability](/features/observability/default)** - Local logging for development
- **[Telemetry](/features/telemetry)** - Prometheus metrics and dashboards

View File

@@ -0,0 +1,775 @@
---
title: "Guardrails"
description: "Enterprise-grade content safety and security validation with support for AWS Bedrock Guardrails, Azure Content Safety, GraySwan Cygnal, and Patronus AI for real-time input and output protection."
icon: "road-barrier"
---
## Overview
**Guardrails** in Bifrost provide enterprise-grade content safety, security validation, and policy enforcement for LLM requests and responses. The system validates inputs and outputs in real-time against your specified policies, ensuring responsible AI deployment with comprehensive protection against harmful content, prompt injection, PII leakage, and policy violations.
<Frame>
<img src="/media/guardrails/guardrails-overview.png" alt="Guardrails overview showing rules and profiles management" />
</Frame>
### Supported Providers
<CardGroup cols={2}>
<Card title="AWS Bedrock Guardrails" icon="aws" href="/integrations/guardrails/aws-bedrock">
Enterprise content filtering, PII detection, and prompt attack prevention.
</Card>
<Card title="Azure Content Safety" icon="microsoft" href="/integrations/guardrails/azure-content-safety">
Multi-modal content moderation with severity-based filtering.
</Card>
<Card title="GraySwan Cygnal" icon="shield-check" href="/integrations/guardrails/grayswan">
AI safety monitoring with natural language rule definitions.
</Card>
<Card title="Patronus AI" icon="brain" href="/integrations/guardrails/patronus-ai">
LLM security, hallucination detection, and safety evaluation.
</Card>
</CardGroup>
### Core Concepts
Bifrost Guardrails are built around two core concepts that work together to provide flexible and powerful content protection:
| Concept | Description |
|---------|-------------|
| **Rules** | Custom policies defined using CEL (Common Expression Language) that determine what content to validate and when. Rules can apply to inputs, outputs, or both, and can be linked to one or more profiles for evaluation. |
| **Profiles** | Configurations for external guardrail providers (AWS Bedrock, Azure Content Safety, GraySwan, Patronus AI). Profiles are reusable and can be shared across multiple rules. |
**How They Work Together:**
- **Profiles** define *how* content is evaluated using external provider capabilities
- **Rules** define *when* and *what* content gets evaluated using CEL expressions
- A single rule can use multiple profiles for layered protection
- Profiles can be reused across different rules for consistency
### Key Features
| Feature | Description |
|---------|-------------|
| **Multi-Provider Support** | AWS Bedrock, Azure Content Safety, GraySwan, and Patronus AI integration |
| **Dual-Stage Validation** | Guard both inputs (prompts) and outputs (responses) |
| **Real-Time Processing** | Synchronous and asynchronous validation modes |
| **CEL-Based Rules** | Define custom policies using Common Expression Language |
| **Reusable Profiles** | Configure providers once, use across multiple rules |
| **Sampling Control** | Apply rules to a percentage of requests for performance tuning |
| **Automatic Remediation** | Block, redact, or modify content based on policy |
| **Comprehensive Logging** | Detailed audit trails for compliance |
### Navigating Guardrails in the UI
Access Guardrails from the Bifrost dashboard:
| Page | Path | Description |
|------|------|-------------|
| **Configuration** | Guardrails > Configuration | Manage guardrail rules and their settings |
| **Providers** | Guardrails > Providers | Configure and manage guardrail profiles |
### Architecture
The following diagram illustrates how Rules and Profiles work together to validate LLM requests:
```mermaid
flowchart TB
subgraph request_flow [Request Flow]
Request[LLM Request] --> InputValidation[Input Validation]
InputValidation --> LLMProvider[LLM Provider]
LLMProvider --> OutputValidation[Output Validation]
OutputValidation --> Response[Response]
end
subgraph rules [Guardrail Rules]
Rule1[Rule: Block PII]
Rule2[Rule: Content Filter]
Rule3[Rule: Prompt Injection]
end
subgraph profiles [Guardrail Profiles]
Profile1[AWS Bedrock Profile]
Profile2[Azure Content Safety Profile]
Profile3[Patronus AI Profile]
Profile4[GraySwan Profile]
end
InputValidation --> Rule1
InputValidation --> Rule3
OutputValidation --> Rule2
Rule1 --> Profile1
Rule2 --> Profile2
Rule2 --> Profile3
Rule3 --> Profile1
```
**Flow Description:**
1. **Incoming Request** - LLM request arrives at Bifrost
2. **Input Validation** - Applicable rules evaluate the input using linked profiles
3. **LLM Processing** - If input passes, request is forwarded to the LLM provider
4. **Output Validation** - Response is evaluated by output rules using linked profiles
5. **Response** - Validated response is returned (or blocked/modified based on violations)
---
## Guardrail Rules
Guardrail Rules are custom policies that define when and how content validation occurs. Rules use CEL (Common Expression Language) expressions to evaluate requests and can be linked to one or more profiles for execution.
<Frame>
<img src="/media/guardrails/query-creation.png" alt="Guardrail rules list showing configured rules with status and actions" />
</Frame>
### Rule Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | integer | Yes | Unique identifier for the rule |
| `name` | string | Yes | Descriptive name for the rule |
| `description` | string | No | Explanation of what the rule does |
| `enabled` | boolean | Yes | Whether the rule is active |
| `cel_expression` | string | Yes | CEL expression for rule evaluation |
| `apply_to` | enum | Yes | When to apply: `input`, `output`, or `both` |
| `sampling_rate` | integer | No | Percentage of requests to evaluate (0-100) |
| `timeout` | integer | No | Execution timeout in milliseconds |
| `provider_config_ids` | array | No | IDs of profiles to use for evaluation |
### Creating Rules
<Tabs group="rules-config">
<Tab title="Web UI">
1. **Navigate to Rules**
- Go to **Guardrails** > **Configuration**
- Click **Add Rule**
<Frame>
<img src="/media/guardrails/cel-rule-builder.png" alt="Guardrail rules list showing configured rules with status and actions" />
</Frame>
2. **Configure Rule Settings**
**Basic Information:**
- **Name**: Enter a descriptive name (e.g., "Block PII in Prompts")
- **Description**: Explain the rule's purpose
- **Enabled**: Toggle to activate the rule
**Evaluation Settings:**
- **Apply To**: Select when to apply the rule
- `input` - Validate incoming prompts only
- `output` - Validate LLM responses only
- `both` - Validate both inputs and outputs
- **CEL Expression**: Define the validation logic
- **Sampling Rate**: Set percentage of requests to evaluate (default: 100%)
- **Timeout**: Set maximum execution time in milliseconds
3. **Link Profiles**
- Select one or more profiles to use for evaluation
- Rules will execute all linked profiles in sequence
4. **Save and Test**
- Click **Save Rule**
- Use the **Test** button to validate with sample content
</Tab>
<Tab title="API">
**Create a Guardrail Rule:**
```bash
curl -X POST http://localhost:8080/api/enterprise/guardrails/rules \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"name": "Block PII in Prompts",
"description": "Prevent PII from being sent to LLM providers",
"enabled": true,
"cel_expression": "request.messages.exists(m, m.role == \"user\")",
"apply_to": "input",
"sampling_rate": 100,
"timeout": 5000,
"provider_config_ids": [1, 2]
}'
```
**List All Rules:**
```bash
curl -X GET http://localhost:8080/api/enterprise/guardrails/rules \
-H "Content-Type: application/json"
# Response
{
"rules": [
{
"id": 1,
"name": "Block PII in Prompts",
"description": "Prevent PII from being sent to LLM providers",
"enabled": true,
"cel_expression": "request.messages.exists(m, m.role == \"user\")",
"apply_to": "input",
"sampling_rate": 100,
"timeout": 5000,
"provider_config_ids": [1, 2]
}
]
}
```
**Update a Rule:**
```bash
curl -X PUT http://localhost:8080/api/enterprise/guardrails/rules/1 \
-H "Content-Type: application/json" \
-d '{
"enabled": false,
"sampling_rate": 50
}'
```
**Delete a Rule:**
```bash
curl -X DELETE http://localhost:8080/api/enterprise/guardrails/rules/1
```
</Tab>
<Tab title="config.json">
```json
{
"guardrails_config": {
"guardrail_rules": [
{
"id": 1,
"name": "Block PII in Prompts",
"description": "Prevent PII from being sent to LLM providers",
"enabled": true,
"cel_expression": "request.messages.exists(m, m.role == \"user\")",
"apply_to": "input",
"sampling_rate": 100,
"timeout": 5000,
"provider_config_ids": [1, 2]
},
{
"id": 2,
"name": "Content Filter for Responses",
"description": "Filter harmful content from LLM responses",
"enabled": true,
"cel_expression": "true",
"apply_to": "output",
"sampling_rate": 100,
"timeout": 3000,
"provider_config_ids": [2]
},
{
"id": 3,
"name": "Prompt Injection Detection",
"description": "Detect and block prompt injection attempts",
"enabled": true,
"cel_expression": "request.messages.size() > 0",
"apply_to": "input",
"sampling_rate": 100,
"timeout": 2000,
"provider_config_ids": [1]
}
]
}
}
```
</Tab>
<Tab title="Helm">
```yaml
guardrails_config:
guardrail_rules:
- id: 1
name: "Block PII in Prompts"
description: "Prevent PII from being sent to LLM providers"
enabled: true
cel_expression: "request.messages.exists(m, m.role == 'user')"
apply_to: "input"
sampling_rate: 100
timeout: 5000
provider_config_ids: [1, 2]
- id: 2
name: "Content Filter for Responses"
description: "Filter harmful content from LLM responses"
enabled: true
cel_expression: "true"
apply_to: "output"
sampling_rate: 100
timeout: 3000
provider_config_ids: [2]
```
</Tab>
</Tabs>
### CEL Expression Examples
CEL (Common Expression Language) provides a powerful way to define rule conditions. Here are common patterns:
**Always Apply Rule:**
```cel
true
```
**Apply to User Messages Only:**
```cel
request.messages.exists(m, m.role == "user")
```
**Apply to Messages Containing Keywords:**
```cel
request.messages.exists(m, m.content.contains("confidential"))
```
**Apply Based on Model:**
```cel
request.model.startsWith("gpt-4")
```
**Apply to Long Prompts:**
```cel
request.messages.filter(m, m.role == "user").map(m, m.content.size()).sum() > 1000
```
**Combine Multiple Conditions:**
```cel
request.model.startsWith("gpt-4") && request.messages.exists(m, m.role == "user" && m.content.size() > 500)
```
### Linking Rules to Profiles
Rules can be linked to multiple profiles for comprehensive validation:
<Frame>
<img src="/media/guardrails/query-creation.png" alt="Rule configuration showing linked profiles" />
</Frame>
**Best Practices:**
- Link PII detection rules to profiles with PII capabilities (Bedrock, Patronus)
- Link content filtering rules to profiles with content safety features (Azure, Bedrock, GraySwan)
- Use GraySwan for custom natural language rules when you need flexible, readable policies
- Use multiple profiles for defense-in-depth (e.g., Bedrock + Patronus for PII, Azure + GraySwan for content)
- Set appropriate timeouts when using multiple profiles
---
## Managing Profiles
Profiles are reusable configurations for external guardrail providers. Each profile contains provider-specific settings including credentials, endpoints, and detection thresholds.
<Frame>
<img src="/media/guardrails/provider-aws-create.png" alt="Guardrail profiles list showing configured providers" />
</Frame>
### Profile Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `id` | integer | Yes | Unique identifier for the profile |
| `provider_name` | string | Yes | Provider type: `bedrock`, `azure`, `grayswan`, `patronus_ai` |
| `policy_name` | string | Yes | Descriptive name for the policy |
| `enabled` | boolean | Yes | Whether the profile is active |
| `config` | object | No | Provider-specific configuration |
### Creating Profiles
<Tabs group="profiles-config">
<Tab title="Web UI">
1. **Navigate to Providers**
- Go to **Guardrails** > **Providers**
- Click **Add Profile**
<Frame>
<img src="/media/guardrails/guardrails-rule-list-2.png" alt="Create guardrail profile form" />
</Frame>
2. **Select Provider Type**
- Choose from: AWS Bedrock, Azure Content Safety, GraySwan, or Patronus AI
3. **Configure Provider Settings**
- Enter credentials and endpoint information
- Configure detection thresholds and actions
- See provider-specific setup sections above for detailed configuration
4. **Save Profile**
- Click **Save Profile**
- The profile is now available for linking to rules
</Tab>
<Tab title="API">
**Create a Profile:**
```bash
curl -X POST http://localhost:8080/api/enterprise/guardrails/providers \
-H "Content-Type: application/json" \
-d '{
"id": 1,
"provider_name": "bedrock",
"policy_name": "PII Detection Profile",
"enabled": true,
"config": {
"access_key": "${AWS_ACCESS_KEY_ID}",
"secret_key": "${AWS_SECRET_ACCESS_KEY}",
"guardrail_arn": "arn:aws:bedrock:us-east-1:123456789:guardrail/abc123",
"guardrail_version": "1",
"region": "us-east-1"
}
}'
```
**List All Profiles:**
```bash
curl -X GET http://localhost:8080/api/enterprise/guardrails/providers \
-H "Content-Type: application/json"
# Response
{
"providers": [
{
"id": 1,
"provider_name": "bedrock",
"policy_name": "PII Detection Profile",
"enabled": true
},
{
"id": 2,
"provider_name": "azure",
"policy_name": "Content Safety Profile",
"enabled": true
}
]
}
```
**Update a Profile:**
```bash
curl -X PUT http://localhost:8080/api/enterprise/guardrails/providers/1 \
-H "Content-Type: application/json" \
-d '{
"enabled": false
}'
```
**Delete a Profile:**
```bash
curl -X DELETE http://localhost:8080/api/enterprise/guardrails/providers/1
```
</Tab>
<Tab title="config.json">
```json
{
"guardrails_config": {
"guardrail_providers": [
{
"id": 1,
"provider_name": "bedrock",
"policy_name": "PII Detection Profile",
"enabled": true,
"config": {
"access_key": "${AWS_ACCESS_KEY_ID}",
"secret_key": "${AWS_SECRET_ACCESS_KEY}",
"guardrail_arn": "arn:aws:bedrock:us-east-1:123456789:guardrail/abc123",
"guardrail_version": "1",
"region": "us-east-1"
}
},
{
"id": 2,
"provider_name": "azure",
"policy_name": "Content Safety Profile",
"enabled": true,
"config": {
"endpoint": "https://your-resource.cognitiveservices.azure.com/",
"api_key": "${AZURE_CONTENT_SAFETY_API_KEY}",
"analyze_enabled": true,
"analyze_severity_threshold": "medium",
"jailbreak_shield_enabled": true,
"indirect_attack_shield_enabled": true
}
},
{
"id": 3,
"provider_name": "grayswan",
"policy_name": "Custom Safety Rules",
"enabled": true,
"config": {
"api_key": "${GRAYSWAN_API_KEY}",
"violation_threshold": 0.5,
"reasoning_mode": "hybrid",
"rules": {
"no_pii": "Do not allow personally identifiable information",
"professional_tone": "Ensure responses maintain a professional tone"
}
}
},
{
"id": 4,
"provider_name": "patronus_ai",
"policy_name": "Hallucination Detection",
"enabled": true,
"config": {
"api_key": "${PATRONUS_API_KEY}",
"api_endpoint": "https://api.patronus.ai/v1"
}
}
]
}
}
```
</Tab>
<Tab title="Helm">
```yaml
guardrails_config:
guardrail_providers:
- id: 1
provider_name: "bedrock"
policy_name: "PII Detection Profile"
enabled: true
config:
guardrail_arn: "arn:aws:bedrock:us-east-1:123456789:guardrail/abc123"
guardrail_version: "1"
region: "us-east-1"
# AWS Authentication (choose one method):
# Option 1: Explicit credentials
access_key: "${AWS_ACCESS_KEY_ID}"
secret_key: "${AWS_SECRET_ACCESS_KEY}"
# Option 2: IAM Role - omit access_key and secret_key
# (Bifrost will use IAM credentials from the environment)
- id: 2
provider_name: "azure"
policy_name: "Content Safety Profile"
enabled: true
config:
endpoint: "https://your-resource.cognitiveservices.azure.com/"
api_key: "${AZURE_CONTENT_SAFETY_API_KEY}"
analyze_enabled: true
analyze_severity_threshold: "medium"
jailbreak_shield_enabled: true
- id: 3
provider_name: "grayswan"
policy_name: "Custom Safety Rules"
enabled: true
config:
api_key: "${GRAYSWAN_API_KEY}"
violation_threshold: 0.5
reasoning_mode: "hybrid"
rules:
no_pii: "Do not allow personally identifiable information"
professional_tone: "Ensure responses maintain a professional tone"
- id: 4
provider_name: "patronus_ai"
policy_name: "Hallucination Detection"
enabled: true
config:
api_endpoint: "https://api.patronus.ai/v1"
```
</Tab>
</Tabs>
### Provider Capabilities
Each provider offers different capabilities. Choose profiles based on your validation needs:
| Capability | AWS Bedrock | Azure Content Safety | GraySwan | Patronus AI |
|------------|-------------|---------------------|----------|-------------|
| PII Detection | Yes | No | No | Yes |
| Content Filtering | Yes | Yes | Yes | Yes |
| Prompt Injection | Yes | Yes | Yes | Yes |
| Hallucination Detection | No | No | No | Yes |
| Toxicity Screening | Yes | Yes | Yes | Yes |
| Custom Policies | Yes | Yes | Yes | Yes |
| Custom Natural Language Rules | No | No | Yes | No |
| Image Support | Yes | No | No | No |
| IPI Detection | No | Yes | Yes | No |
| Mutation Detection | No | No | Yes | No |
### Best Practices
**Profile Organization:**
- Create separate profiles for different use cases (PII, content filtering, etc.)
- Use descriptive policy names that indicate the profile's purpose
- Keep credentials secure using environment variables
**Performance Considerations:**
- Enable only the profiles you need to minimize latency
- Use sampling rates on rules for high-traffic endpoints
- Set appropriate timeouts to prevent slow requests
**Security:**
- Store API keys and credentials in environment variables or secrets managers
- Regularly rotate credentials
- Use least-privilege IAM roles for AWS Bedrock
---
## Using Guardrails in Requests
### Attaching Guardrails to API Calls
Once configured, attach guardrails to your LLM requests using custom headers:
**Single Guardrail:**
```bash
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-bf-guardrail-id: bedrock-prod-guardrail" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Help me with this task"
}
]
}'
```
**Multiple Guardrails (Sequential):**
```bash
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "x-bf-guardrail-ids: bedrock-prod-guardrail,azure-content-safety-001" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Help me with this task"
}
]
}'
```
**Guardrail Configuration in Request:**
```bash
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Help me with this task"
}
],
"bifrost_config": {
"guardrails": {
"input": ["bedrock-prod-guardrail"],
"output": ["patronus-ai-001"],
"async": false
}
}
}'
```
### Guardrail Response Handling
**Successful Validation (200):**
```json
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1699564800,
"model": "gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "I'd be happy to help you with your task..."
},
"finish_reason": "stop"
}
],
"extra_fields": {
"guardrails": {
"input_validation": {
"guardrail_id": "bedrock-prod-guardrail",
"status": "passed",
"violations": [],
"processing_time_ms": 245
},
"output_validation": {
"guardrail_id": "patronus-ai-001",
"status": "passed",
"violations": [],
"processing_time_ms": 312
}
}
}
}
```
**Validation Failure - Blocked (446):**
```json
{
"error": {
"message": "Request blocked by guardrails",
"type": "guardrail_violation",
"code": 446,
"details": {
"guardrail_id": "bedrock-prod-guardrail",
"validation_stage": "input",
"violations": [
{
"type": "PII",
"category": "SSN",
"severity": "HIGH",
"action": "block",
"text_excerpt": "My SSN is ***-**-****"
},
{
"type": "prompt_injection",
"severity": "CRITICAL",
"action": "block",
"confidence": 0.95
}
],
"processing_time_ms": 198
}
}
}
```
**Validation Warning - Logged (246):**
```json
{
"id": "chatcmpl-def456",
"object": "chat.completion",
"created": 1699564800,
"model": "gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Response with redacted content..."
},
"finish_reason": "stop"
}
],
"bifrost_metadata": {
"guardrails": {
"output_validation": {
"guardrail_id": "azure-content-safety-001",
"status": "warning",
"violations": [
{
"type": "profanity",
"severity": "LOW",
"action": "redact",
"modifications": 2
}
],
"processing_time_ms": 187
}
}
}
}
```

View File

@@ -0,0 +1,108 @@
---
title: "In-VPC Deployments"
description: "Deploy Bifrost within your private cloud infrastructure with VPC isolation, custom networking, and enhanced security controls for enterprise environments."
icon: "cloud"
---
In-VPC (Virtual Private Cloud) deployments allow you to run Bifrost entirely within your private cloud infrastructure, providing maximum security, compliance, and control over your AI gateway deployment.
## Supported Cloud Providers
Bifrost supports INVPC deployments across all major cloud providers:
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 my-6">
<div className="flex items-center gap-2 p-3 border rounded-lg">
<span>Google Cloud Platform</span>
</div>
<div className="flex items-center gap-2 p-3 border rounded-lg">
<span>Amazon Web Services</span>
</div>
<div className="flex items-center gap-2 p-3 border rounded-lg">
<span>Microsoft Azure</span>
</div>
<div className="flex items-center gap-2 p-3 border rounded-lg">
<span>Cloudflare</span>
</div>
<div className="flex items-center gap-2 p-3 border rounded-lg">
<span>Vercel</span>
</div>
</div>
## Architecture Benefits
### Security & Compliance
- **Network Isolation**: Complete isolation within your VPC with no external network dependencies
- **Data Sovereignty**: All data processing occurs within your controlled environment
- **Compliance Ready**: Meets requirements for HIPAA, SOC2, GDPR, and other regulatory frameworks
- **Zero Trust Architecture**: Implements principle of least privilege with granular access controls
### Performance & Reliability
- **Low Latency**: Direct communication between services within your network
- **High Availability**: Multi-zone deployment with automatic failover capabilities
- **Guaranteed Uptime**: 99.95% SLA with comprehensive monitoring and alerting
### Control & Customization
- **Custom Networking**: Configure subnets, routing, and security groups to your specifications
- **Resource Management**: Full control over compute, storage, and network resources
- **Scaling Policies**: Define auto-scaling rules based on your usage patterns
## Service Level Agreement
### Availability Commitment
- **Uptime Guarantee**: 99.95% monthly uptime for all core components
- **Downtime Calculation**: `(Total Minutes - Downtime Minutes) / Total Minutes × 100`
- **Partial Downtime**: Reduced functionality counted as 50% downtime
### Core Components Covered
The following components are monitored for SLA compliance:
- Gateway instance
- Log ingestion pipeline
### Exclusions
SLA excludes downtime due to:
- Scheduled maintenance (14-day advance notice)
- Downstream provider incidents
- Client hardware/software/network issues
- Third-party AI provider outages
- Client misuse or unauthorized modifications
## Support & Maintenance
### Technical Support
- **24/7 Critical Support**: Available for core component issues
- **Multiple Channels**: Platform, email (contact@getmaxim.ai), or Slack Connect
- **Audit Trail**: Detailed logs for any data access during troubleshooting
### Maintenance Windows
- **Scheduled Maintenance**: 14-day advance notice for major updates
- **Security Patches**: Immediate or 14-day delayed application (your choice)
- **Continuous Updates**: Regular feature improvements with 7-day advance notice
## Getting Started
### Prerequisites
- VPC with appropriate CIDR ranges
- Kubernetes cluster (GKE, EKS, or AKS)
- Container registry access
- DNS configuration for internal routing
### Deployment Process
1. **Infrastructure Setup**: Configure VPC, subnets, and security groups
2. **Cluster Preparation**: Set up Kubernetes cluster with required permissions
3. **Bifrost Installation**: Deploy using provided Helm charts or manifests
4. **Configuration**: Apply your specific settings and integrations
5. **Validation**: Run connectivity and performance tests
6. **Go Live**: Begin routing production traffic
## Cost Optimization
### Resource Sizing
- **Development**: 2 vCPU, 4GB RAM minimum
- **Production**: 4+ vCPU, 8GB+ RAM recommended
- **High Availability**: Multi-zone deployment with load balancing
### Scaling Strategies
- **Horizontal Pod Autoscaling**: Based on CPU/memory utilization
- **Vertical Pod Autoscaling**: Automatic resource adjustment
- **Cluster Autoscaling**: Node pool expansion/contraction

View File

@@ -0,0 +1,348 @@
---
title: "Log Exports"
description: "Export and analyze request logs, traces, and telemetry data from Bifrost with enterprise-grade data export capabilities for compliance, monitoring, and analytics."
icon: "download"
---
# Log Exports
Bifrost Enterprise provides comprehensive log export capabilities, allowing you to automatically export request logs, traces, and telemetry data to various storage systems and data lakes on configurable schedules.
## Overview
The log export system enables:
- **Scheduled Exports**: Daily, weekly, or monthly automated exports
- **Multiple Destinations**: Object stores, data warehouses, and data lakes
- **Format Flexibility**: JSON, CSV, Parquet, and custom formats
- **Filtering & Transformation**: Export specific data subsets with custom transformations
- **Compliance**: Meet data retention and audit requirements
## Supported Export Destinations
### Object Storage
#### Amazon S3
```json
{
"export": {
"destination": "s3",
"config": {
"bucket": "bifrost-logs",
"region": "us-west-2",
"prefix": "logs/{year}/{month}/{day}/",
"credentials": {
"access_key_id": "${AWS_ACCESS_KEY_ID}",
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}"
}
}
}
}
```
#### Google Cloud Storage
```json
{
"export": {
"destination": "gcs",
"config": {
"bucket": "bifrost-logs",
"prefix": "logs/{year}/{month}/{day}/",
"credentials": {
"service_account_key": "${GCP_SERVICE_ACCOUNT_KEY}"
}
}
}
}
```
#### Azure Blob Storage
```json
{
"export": {
"destination": "azure_blob",
"config": {
"container": "bifrost-logs",
"account_name": "${AZURE_ACCOUNT_NAME}",
"account_key": "${AZURE_ACCOUNT_KEY}",
"prefix": "logs/{year}/{month}/{day}/"
}
}
}
```
### Data Warehouses & Lakes
#### Snowflake
```json
{
"export": {
"destination": "snowflake",
"config": {
"account": "your-account.snowflakecomputing.com",
"database": "BIFROST_LOGS",
"schema": "PUBLIC",
"table": "request_logs",
"warehouse": "COMPUTE_WH",
"credentials": {
"username": "${SNOWFLAKE_USERNAME}",
"password": "${SNOWFLAKE_PASSWORD}"
}
}
}
}
```
#### Amazon Redshift
```json
{
"export": {
"destination": "redshift",
"config": {
"cluster": "bifrost-cluster",
"database": "bifrost_logs",
"schema": "public",
"table": "request_logs",
"region": "us-west-2",
"credentials": {
"username": "${REDSHIFT_USERNAME}",
"password": "${REDSHIFT_PASSWORD}"
}
}
}
}
```
#### Google BigQuery
```json
{
"export": {
"destination": "bigquery",
"config": {
"project_id": "your-project-id",
"dataset": "bifrost_logs",
"table": "request_logs",
"credentials": {
"service_account_key": "${GCP_SERVICE_ACCOUNT_KEY}"
}
}
}
}
```
## Export Schedules
### Daily Exports
```json
{
"export": {
"schedule": "daily",
"time": "02:00",
"timezone": "UTC"
}
}
```
### Weekly Exports
```json
{
"export": {
"schedule": "weekly",
"day": "sunday",
"time": "03:00",
"timezone": "UTC"
}
}
```
### Monthly Exports
```json
{
"export": {
"schedule": "monthly",
"day": 1,
"time": "04:00",
"timezone": "UTC"
}
}
```
## Export Configuration
### Complete Export Configuration Example
```json
{
"log_exports": {
"enabled": true,
"exports": [
{
"name": "daily_s3_export",
"enabled": true,
"schedule": {
"frequency": "daily",
"time": "02:00",
"timezone": "UTC"
},
"destination": {
"type": "s3",
"config": {
"bucket": "bifrost-logs-prod",
"region": "us-west-2",
"prefix": "daily-exports/{year}/{month}/{day}/",
"credentials": {
"access_key_id": "${AWS_ACCESS_KEY_ID}",
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}"
}
}
},
"data": {
"format": "parquet",
"compression": "gzip",
"include": [
"request_logs",
"response_logs",
"error_logs"
],
"filters": {
"date_range": "last_24_hours",
"status_codes": [200, 400, 401, 403, 404, 500]
}
}
},
{
"name": "weekly_bigquery_export",
"enabled": true,
"schedule": {
"frequency": "weekly",
"day": "sunday",
"time": "03:00",
"timezone": "UTC"
},
"destination": {
"type": "bigquery",
"config": {
"project_id": "your-analytics-project",
"dataset": "bifrost_analytics",
"table": "weekly_logs",
"credentials": {
"service_account_key": "${GCP_SERVICE_ACCOUNT_KEY}"
}
}
},
"data": {
"format": "json",
"include": [
"request_logs",
"metrics",
"traces"
],
"transformations": [
{
"type": "aggregate",
"group_by": ["provider", "model", "customer_id"],
"metrics": ["total_requests", "avg_latency", "error_rate"]
}
]
}
}
]
}
}
```
## Data Formats
### JSON Format
```json
{
"timestamp": "2024-01-15T10:30:00Z",
"request_id": "req_123456789",
"customer_id": "cust_abc123",
"provider": "openai",
"model": "gpt-4",
"endpoint": "/v1/chat/completions",
"method": "POST",
"status_code": 200,
"latency_ms": 1250,
"input_tokens": 100,
"output_tokens": 150,
"cost_usd": 0.0045
}
```
### CSV Format
```csv
timestamp,request_id,customer_id,provider,model,endpoint,method,status_code,latency_ms,input_tokens,output_tokens,cost_usd
2024-01-15T10:30:00Z,req_123456789,cust_abc123,openai,gpt-4,/v1/chat/completions,POST,200,1250,100,150,0.0045
```
### Parquet Schema
```
message log_record {
required int64 timestamp;
required binary request_id (UTF8);
required binary customer_id (UTF8);
required binary provider (UTF8);
required binary model (UTF8);
required binary endpoint (UTF8);
required binary method (UTF8);
required int32 status_code;
required int32 latency_ms;
optional int32 input_tokens;
optional int32 output_tokens;
optional double cost_usd;
}
```
## Data Filtering & Transformation
### Filtering Options
```json
{
"filters": {
"date_range": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
},
"providers": ["openai", "anthropic", "azure"],
"models": ["gpt-4", "claude-3-sonnet"],
"status_codes": [200, 201, 400, 401, 403, 404, 500],
"customers": ["cust_123", "cust_456"],
"min_latency_ms": 100,
"max_latency_ms": 10000,
"has_errors": true
}
}
```
### Transformation Options
```json
{
"transformations": [
{
"type": "aggregate",
"group_by": ["provider", "model", "date"],
"metrics": [
"count",
"avg_latency",
"p95_latency",
"total_tokens",
"total_cost",
"error_rate"
]
},
{
"type": "anonymize",
"fields": ["customer_id", "request_id"],
"method": "hash"
},
{
"type": "enrich",
"add_fields": {
"export_timestamp": "${EXPORT_TIMESTAMP}",
"export_version": "${EXPORT_VERSION}"
}
}
]
}
```

View File

@@ -0,0 +1,189 @@
---
title: "MCP with Federated Auth"
description: "Transform your existing private enterprise APIs into LLM-ready MCP tools using federated authentication without writing a single line of code"
icon: "screwdriver-wrench"
---
Transform your existing private enterprise APIs into LLM-ready MCP tools instantly. Add your APIs along with authentication information, and Bifrost dynamically syncs user authentication to allow these existing APIs to be used as MCP tools.
## Supported Import Methods
Add your existing APIs to Bifrost using any of these methods:
<Tabs>
<Tab title="Postman Collection">
Import your existing Postman collections directly into Bifrost. All request configurations, headers, and parameters are preserved.
```json
{
"info": {
"name": "Enterprise API Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Get User Profile",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "{{req.header.authorization}}",
"type": "text"
}
],
"url": {
"raw": "https://api.company.com/users/profile",
"host": ["api", "company", "com"],
"path": ["users", "profile"]
}
}
}
]
}
```
</Tab>
<Tab title="OpenAPI Spec">
Use your existing OpenAPI 3.0+ specifications. Bifrost automatically converts them into MCP-compatible tools.
```yaml
openapi: 3.0.0
info:
title: Enterprise API
version: 1.0.0
paths:
/users/profile:
get:
summary: Get user profile
security:
- BearerAuth: []
parameters:
- name: Authorization
in: header
schema:
type: string
example: "{{req.header.authorization}}"
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
```
</Tab>
<Tab title="cURL Commands">
Convert your existing cURL commands directly into MCP tools.
```bash
curl -X GET "https://api.company.com/users/profile" \
-H "Authorization: {{req.header.authorization}}" \
-H "Content-Type: application/json"
```
</Tab>
<Tab title="Built-in UI">
Use Bifrost's intuitive UI to manually configure your API endpoints with the same ease as Postman.
1. Set HTTP method and URL
2. Configure headers with variable substitution
3. Define request body (if needed)
4. Test the endpoint
5. Deploy as MCP tool
</Tab>
</Tabs>
## What Happens Next
Once you upload your API specifications, Bifrost automatically:
- **Syncs authentication systems** from your existing APIs
- **Converts endpoints** into MCP-compatible tools
- **Maintains security** using your current auth infrastructure
- **Makes APIs available** to LLMs instantly
## Supported Authentication Types
Bifrost automatically handles all common authentication patterns:
- **Bearer Tokens** (JWT, OAuth)
- **API Keys** (headers, query parameters)
- **Custom Headers** (tenant IDs, user tokens)
- **Basic Auth** and other standard methods
## Real-World Use Cases
### Enterprise CRM Integration
Transform your Salesforce, HubSpot, or custom CRM APIs:
```json
{
"name": "Get Customer Data",
"method": "GET",
"url": "https://api.company.com/crm/customers/{{req.body.customer_id}}",
"headers": {
"Authorization": "{{req.header.authorization}}",
"X-Tenant-ID": "{{req.header.x-tenant-id}}"
}
}
```
### Internal Microservices
Make your internal microservices LLM-accessible:
```yaml
paths:
/internal/user-service/profile:
get:
parameters:
- name: Authorization
in: header
schema:
type: string
default: "{{req.header.authorization}}"
- name: X-Service-Token
in: header
schema:
type: string
default: "{{env.INTERNAL_SERVICE_TOKEN}}"
```
### Database APIs
Connect to your database APIs securely:
```http
POST https://db-api.company.com/query
Content-Type: application/json
Authorization: {{req.header.authorization}}
X-Database-Name: {{req.header.x-database}}
{
"query": "SELECT * FROM users WHERE tenant_id = '{{req.body.tenant_id}}'",
"limit": 100
}
```
## Security Benefits
### 1. **Zero Trust Architecture**
- Authentication happens at the edge (your existing systems)
- Bifrost never stores or caches authentication credentials
- Each request is authenticated independently
### 2. **Existing Security Policies**
- Leverage your current RBAC (Role-Based Access Control)
- Maintain existing audit trails
- No changes to security infrastructure required
### 3. **Granular Access Control**
- Different users get different API access based on their credentials
- Tenant isolation maintained through existing headers
- API rate limiting and quotas preserved
### 4. **Compliance Friendly**
- No sensitive data passes through Bifrost permanently
- Existing compliance frameworks remain intact
- Audit trails maintained in your systems

227
docs/enterprise/rbac.mdx Normal file
View File

@@ -0,0 +1,227 @@
---
title: "Role-Based Access Control"
description: "Manage user access with fine-grained permissions across Bifrost resources using roles and permissions."
icon: "user-shield"
---
## Overview
Role-Based Access Control (RBAC) in Bifrost Enterprise provides fine-grained access management for your organization. RBAC allows you to define roles with specific permissions, controlling what users can view, create, update, or delete across all Bifrost resources.
**Key Benefits:**
- **Principle of Least Privilege** - Grant users only the permissions they need
- **Centralized Access Management** - Manage all permissions from a single interface
- **Audit-Ready** - Track who has access to what for compliance requirements
- **Flexible Role Design** - Use system roles or create custom roles for your organization
RBAC integrates seamlessly with [User Provisioning (SCIM)](./user-provisioning), automatically assigning roles based on your IdP groups and claims.
---
## Roles & Permissions
Navigate to **Governance** → **Roles & Permissions** in the Bifrost dashboard to manage roles.
<Frame>
<img src="/media/rbac/rbac-list.png" alt="Roles & Permissions management interface showing system roles" />
</Frame>
### System Roles
Bifrost includes three pre-configured system roles that cover common access patterns:
| Role | Permissions | Description |
|------|-------------|-------------|
| **Admin** | 42 | Full access to all resources and operations |
| **Developer** | 27 | CRUD access to technical resources, view access to logs and cluster |
| **Viewer** | 14 | Read-only access to all resources |
System roles cannot be deleted, but their permissions can be customized to fit your organization's needs.
### Custom Roles
Create custom roles when system roles don't match your organizational structure. Custom roles are useful for:
- **Specialized Teams** - Create roles for QA, Security, or Compliance teams
- **Project-Based Access** - Limit access to specific resources per project
- **Temporary Access** - Grant limited permissions for contractors or auditors
**To create a custom role:**
1. Click **Add Role** in the top-right corner
2. Enter a **Role Name** (e.g., "Auditor", "QA Team")
3. Add a **Description** explaining the role's purpose
4. Click **Create Role**
5. Assign permissions using the Manage Permissions dialog
---
## Resources & Operations
RBAC permissions are defined as combinations of **Resources** and **Operations**.
### Protected Resources
Bifrost protects access to the following resources:
| Resource | Description |
|----------|-------------|
| **Logs** | Request and response logs |
| **ModelProvider** | AI model provider configurations |
| **Observability** | Monitoring and metrics dashboards |
| **Plugins** | Plugin configurations and management |
| **VirtualKeys** | Virtual key management |
| **UserProvisioning** | User and group provisioning settings |
| **Users** | User account management |
| **AuditLogs** | Audit trail and compliance logs |
| **GuardrailsConfig** | Guardrail configurations |
| **GuardrailRules** | Individual guardrail rules |
| **Cluster** | Cluster configuration and nodes |
| **Settings** | Workspace settings |
| **MCPGateway** | MCP Gateway configurations |
| **AdaptiveRouter** | Adaptive routing settings |
### Operations
Each resource supports up to four operations:
| Operation | Description |
|-----------|-------------|
| **View** | Read-only access to view the resource |
| **Create** | Ability to create new instances of the resource |
| **Update** | Ability to modify existing resources |
| **Delete** | Ability to remove resources |
---
## Managing Permissions
To assign or modify permissions for a role:
1. Navigate to **Governance** → **Roles & Permissions**
2. Click the **menu icon** (•••) on the role you want to modify
3. Select **Manage Permissions**
<Frame>
<img src="/media/rbac/rbac-edit-role.png" alt="Manage Permissions dialog showing resource-based permission assignment" />
</Frame>
The Manage Permissions dialog provides a two-panel interface:
**Left Panel - Resources:**
- Lists all available resources
- Shows the count of enabled permissions per resource (e.g., "4/4 permissions")
- Click a resource to view its permissions
**Right Panel - Permissions:**
- Displays available operations for the selected resource
- Toggle switches to enable/disable each permission
- Shows operation descriptions for clarity
### Assigning Permissions
1. Select a **Resource** from the left panel
2. Toggle the **operations** you want to enable for this role
3. Repeat for other resources as needed
4. Click **Save Permissions** to apply changes
The footer shows the total permissions count (e.g., "42 of 42 permissions selected") to help track the role's access level.
---
## Best Practices
### Role Design
- **Start with System Roles** - Use Admin, Developer, and Viewer as templates
- **Follow Least Privilege** - Only grant permissions that are necessary
- **Document Role Purpose** - Use clear descriptions to explain each role's intent
- **Review Regularly** - Audit role assignments quarterly
### Permission Strategies
**For Development Teams:**
```
Developer role + specific resource access based on team focus
- Frontend team: VirtualKeys (View), Logs (View), Observability (View)
- Backend team: ModelProvider (CRUD), Plugins (CRUD), Logs (View)
```
**For Security/Compliance Teams:**
```
Custom "Auditor" role with:
- AuditLogs (View)
- Logs (View)
- GuardrailsConfig (View)
- Users (View)
```
**For Operations Teams:**
```
Custom "Ops" role with:
- Cluster (CRUD)
- Observability (View)
- Logs (View)
- Settings (View, Update)
```
---
## Integration with Identity Providers
When using [User Provisioning (SCIM)](./user-provisioning) with Okta, Entra, Zitadel, Keycloak, or Google Workspace, roles can be automatically assigned based on:
- **IdP Groups** - Map identity provider groups to Bifrost roles
- **App Roles** - Sync application roles from your IdP
- **Claims** - Use custom claims to determine role assignment
Users authenticated via SSO receive their role assignments automatically on first login, with permissions synchronized on each session.
---
## API Access
Roles and permissions can also be managed via the API:
**List all roles:**
```bash
curl -X GET http://localhost:8080/api/roles \
-H "Authorization: Bearer <admin_token>"
```
**Get role permissions:**
```bash
curl -X GET http://localhost:8080/api/roles/{role_id}/permissions \
-H "Authorization: Bearer <admin_token>"
```
**Update role permissions:**
```bash
curl -X PUT http://localhost:8080/api/roles/{role_id}/permissions \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"permission_ids": [1, 2, 3, 4, 5]
}'
```
**Create a custom role:**
```bash
curl -X POST http://localhost:8080/api/roles \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Auditor",
"description": "Read-only access for compliance auditing"
}'
```
---
## Next Steps
- **[Setting up Okta](./setting-up-okta)** - Configure Okta for SSO with role sync
- **[Setting up Microsoft Entra](./setting-up-entra)** - Configure Entra ID for SSO with role sync
- **[Audit Logs](./audit-logs)** - Track permission usage and access patterns
- **[Advanced Governance](./advanced-governance)** - Learn about the complete governance framework

View File

@@ -0,0 +1,392 @@
---
title: "Setting up Microsoft Entra"
description: "Step-by-step guide to configure Microsoft Entra ID (Azure AD) as your identity provider for Bifrost Enterprise SSO authentication."
icon: "microsoft"
---
## Overview
This guide walks you through configuring Microsoft Entra ID (formerly Azure Active Directory) as your identity provider for Bifrost Enterprise. After completing this setup, your users will be able to sign in to Bifrost using their Microsoft credentials, with roles and team memberships automatically synchronized.
## Prerequisites
- A Microsoft Azure account with access to Entra ID (Azure AD)
- Admin access to create app registrations
- Bifrost Enterprise deployed and accessible
- The redirect URI for your Bifrost instance (e.g., `https://your-bifrost-domain.com/login`)
---
## Step 1: Register an Application
1. Sign in to the [Azure Portal](https://portal.azure.com)
2. Navigate to **Microsoft Entra ID** (or **Azure Active Directory**)
3. Go to **App registrations**
4. Click **New registration**
Configure the registration:
| Field | Value |
|-------|-------|
| **Name** | Bifrost Enterprise |
| **Supported account types** | Accounts in this organizational directory only (Single tenant) |
| **Redirect URI** | Web: `https://your-bifrost-domain.com/login` |
5. Click **Register**
<Tip>
You can add an app icon to make the application easily recognizable. The Bifrost logo is available at: [https://www.getmaxim.ai/bifrost/bifrost-logo-only.png](https://www.getmaxim.ai/bifrost/bifrost-logo-only.png)
</Tip>
6. After registration, note down the following from the **Overview** page:
<Frame>
<img src="/media/user-provisioning/entra-app-information.png" alt="Entra App Registration Overview" />
</Frame>
| Value | Where to Find |
|-------|---------------|
| **Application (client) ID** | Overview → Essentials |
| **Directory (tenant) ID** | Overview → Essentials |
---
## Step 2: Create App Roles (Optional)
<Note>
This step is optional. You can create custom roles if thats the preferred way. Or you can map any attribute to role/team/business unit. Role mapping is required step.
</Note>
Configure roles in Entra that map to Bifrost's role hierarchy (Admin, Developer, Viewer).
1. In your app registration, go to **App roles**
2. Click **Create app role**
3. Create the following three roles:
<Frame>
<img src="/media/user-provisioning/entra-create-app-roles.png" alt="Entra App Roles configuration" />
</Frame>
### Viewer Role
| Field | Value |
|-------|-------|
| **Display name** | Viewer |
| **Allowed member types** | Users/Groups |
| **Value** | `viewer` |
| **Description** | Viewer role on Bifrost |
| **State** | Enabled |
### Developer Role
| Field | Value |
|-------|-------|
| **Display name** | Developer |
| **Allowed member types** | Users/Groups |
| **Value** | `developer` |
| **Description** | Developer role on Bifrost |
| **State** | Enabled |
### Admin Role
| Field | Value |
|-------|-------|
| **Display name** | Admin |
| **Allowed member types** | Users/Groups |
| **Value** | `admin` |
| **Description** | Admin role on Bifrost |
| **State** | Enabled |
---
## Step 3: Enable Assignment Required
To control which users can access Bifrost, enable assignment requirement on the Enterprise Application.
1. Go to **Enterprise applications** (from the main Entra ID menu)
2. Find and select **Bifrost Enterprise**
3. Go to **Properties**
<Frame>
<img src="/media/user-provisioning/entra-enable-assignment.png" alt="Entra Enterprise Application Properties" />
</Frame>
4. Set **Assignment required?** to **Yes**
5. Set **Enabled for users to sign-in?** to **Yes**
6. Click **Save**
---
## Step 4: Create a Client Secret
Bifrost requires a client secret for OAuth authentication.
1. Go back to **App registrations** → **Bifrost Enterprise**
2. Navigate to **Certificates & secrets**
3. Click **New client secret**
<Frame>
<img src="/media/user-provisioning/entra-create-client-secret.png" alt="Entra Enterprise Client Secrets" />
</Frame>
| Field | Value |
|-------|-------|
| **Description** | Bifrost Enterprise Secret |
| **Expires** | Choose based on your security policy (e.g., 24 months) |
4. Click **Add**
5. **Copy the secret value immediately** - it won't be shown again!
<Warning>
Store the client secret securely. You'll need it for the Bifrost configuration.
</Warning>
---
## Step 5: Configure API Permissions
Ensure your application has the necessary permissions.
<Frame>
<img src="/media/user-provisioning/entra-api-permissions.png" alt="Entra Enterprise API Permissions" />
</Frame>
1. In your app registration, go to **API permissions**
2. Click **Add a permission**
3. Select **Microsoft Graph**
4. Choose **Delegated permissions**
5. Add the following permissions:
- `openid`
- `profile`
- `email`
- `offline_access` (for refresh tokens)
6. In addition to above roles, following 4 roles are required
- `User.Read`
- `User.Read.All`
- `GroupMember.Read.All`
- `Group.Read.All`
7. Click **Add permissions**
8. If required by your organization, click **Grant admin consent for [Your Organization]**
---
## Step 6: Configure Token Claims (Optional)
<Note>
Groups and other attributes are required in the claim when you configure their mapping in Bifrost.
</Note>
By default, Entra includes the `roles` claim when app roles are assigned. To include group memberships for team synchronization:
1. Go to **Token configuration**
2. Click **Add groups claim**
3. Select:
- **Security groups** or **Groups assigned to the application**
- For token type, enable **ID** and **Access**
4. Click **Add**
---
## Step 7: Assign Users and Roles
<Frame>
<img src="/media/user-provisioning/entra-user-assignments.png" alt="Entra User Assignments" />
</Frame>
1. Go to **Enterprise applications** → **Bifrost Enterprise**
2. Navigate to **Users and groups**
3. Click **Add user/group**
4. Select users or groups
5. Select the appropriate role (Admin, Developer, or Viewer)
6. Click **Assign**
<Tip>
You can assign roles to groups for easier management. All users in a group will inherit the assigned role.
</Tip>
---
## Step 8: Configure App Manifest
<Frame>
<img src="/media/user-provisioning/entra-app-manifest.png" alt="Microsoft entra app manifest"/>
</Frame>
You will need to make 2 changes in the app manifest
```json
"requestedAccessTokenVersion": 2
```
and
```json
"optionalClaims": {
"idToken": [
{
"name": "roles",
"source": null,
"essential": false,
"additionalProperties": []
},
{
"name": "groups",
"source": null,
"essential": false,
"additionalProperties": ["cloud_displayname", "sam_account_name"]
}
],
"accessToken": [],
"saml2Token": []
}
```
## Step 9: Configure Bifrost
Now configure Bifrost to use Microsoft Entra as the identity provider.
### Using the Bifrost UI
<Frame>
<img src="/media/user-provisioning/entra-form.png" alt="Create token dialog in Okta" />
</Frame>
1. Navigate to **Governance** → **User Provisioning** in your Bifrost dashboard
2. Select **Microsoft Entra** as the SCIM Provider
3. Enter the following configuration:
| Field | Value |
|-------|-------|
| **Client ID** | Application (client) ID from Azure |
| **Tenant ID** | Directory (tenant) ID from Azure |
| **Client Secret** | The secret you created in Step 4 |
| **Audience** | Your Client ID (optional, defaults to Client ID) |
| **App ID URI** | `api://{client-id}` (optional, for v1.0 tokens) |
5. **Verify** configuration and see if you get any errors. Make sure you get no errors/warnings.
6. Toggle **Enabled** to activate the provider
7. Click **Save Configuration**
<Warning>
After saving, you'll need to restart your Bifrost server for the changes to take effect.
</Warning>
### Configuration Reference
| Field | Required | Description |
|-------|----------|-------------|
| `tenantId` | Yes | Azure Directory (tenant) ID |
| `clientId` | Yes | Application (client) ID |
| `clientSecret` | Yes | Client secret for OAuth authentication |
| `audience` | No | JWT audience for validation (defaults to clientId) |
| `attributeRoleMappings` | Yes | Ordered list of attribute→role mappings. First match wins. |
| `attributeTeamMappings` | No | Attribute→team mappings (all matches apply). |
| `attributeBusinessUnitMappings` | No | Attribute→business-unit mappings (all matches apply). |
---
### Attribute Mappings
Attribute mappings let you translate Okta claim values into Bifrost roles, teams, or business units without restructuring your Okta claims. Bifrost supports three mapping types:
- **`attributeRoleMappings`**: map a claim value to a Bifrost role (Admin, Developer, Viewer, or a custom role)
- **`attributeTeamMappings`**: map a claim value to a Bifrost team
- **`attributeBusinessUnitMappings`**: map a claim value to a Bifrost business unit
These mappings work with any Okta claim — the `groups` claim from Step 5, the custom `role` claim from Step 4, or any other claim your authorization server includes in the token (e.g., `department`, `organization`).
To configure attribute mappings:
1. In the User Provisioning configuration, scroll down to **Attribute Mappings**
2. Click **Add Mapping** under the relevant mapping type (Role, Team, or Business Unit)
3. Enter the **Attribute** (the claim name from the token), the **Value** to match, and the target **Role**, **Team**, or **Business Unit**
4. Repeat for each rule you need
<Frame>
<img
src="/media/user-provisioning/attribute-to-entity-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
<Note>
When you mark value as "*" - the claim value is mapped as is to the entity name. Values comparisons are case-insensitive.
</Note>
### Custom attribute mapping
You can also map any custom attributes to any entity (role, team or business unit). Make sure these are configured to send back to Bifrost in token configuration.
<Frame>
<img
src="/media/user-provisioning/custom-attribute-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
#### Evaluation rules
- **Role mappings**: Ordered, first match wins. If no rule matches, users are not allowed to login into the system.
- **Team and business unit mappings**: All matching rules apply — users can be placed on multiple teams and business units simultaneously.
- **Claim values**: Can be strings, arrays, or nested objects. Bifrost resolves dotted paths (e.g., `realm_access.roles`).
<Note>
If a user matches multiple role mapping rules, the highest privilege role is assigned. If no
mapping matches, the first user to sign in receives the **Admin** role, and subsequent users receive the **Viewer**
role.
</Note>
5. Click **Save Configuration**
---
## Testing the Integration
1. Open your Bifrost dashboard in a new browser or incognito window
2. You should be redirected to Entra for authentication
3. Log in with an assigned user
4. After successful authentication, you'll be redirected back to Bifrost
5. Verify the user appears in the Bifrost users list with the correct role
---
## Troubleshooting
### User not redirected to Microsoft login
- Verify the SCIM provider is enabled in Bifrost
- Check that the Bifrost server was restarted after configuration
- Ensure the Tenant ID and Client ID are correct
### "AADSTS50011: The reply URL does not match"
- Verify the redirect URI in your app registration exactly matches your Bifrost login URL
- Ensure there are no trailing slashes or protocol mismatches (http vs https)
### "AADSTS7000215: Invalid client secret"
- Regenerate the client secret in Azure
- Ensure you're using the secret **Value**, not the secret ID
- Check for any leading/trailing whitespace when copying
### Token validation errors
- Ensure the Tenant ID matches your Azure directory
- Verify the Client ID is correct
- Check that the app registration is in the same tenant as your users
---
## Next Steps
- **[User Provisioning (SCIM)](./user-provisioning)** - Overview of SCIM in Bifrost and alternative identity providers
- **[Advanced Governance](./advanced-governance)** - Learn about user budgets and compliance features
- **[Role-Based Access Control](./advanced-governance#role-hierarchy)** - Understand the Admin, Developer, Viewer hierarchy
- **[Audit Logs](./audit-logs)** - Monitor user authentication and activity

View File

@@ -0,0 +1,232 @@
---
title: "Setting up Google Workspace"
description: "Step-by-step guide to configure Google Workspace as your identity provider for Bifrost Enterprise SSO and Directory-based user provisioning."
icon: "google"
---
## Overview
This guide walks you through configuring **Google Workspace** as your identity provider for Bifrost Enterprise. The integration has two pieces:
1. **OAuth 2.0 login** — users sign in to Bifrost with their Google Workspace accounts via a Google OAuth Client ID.
2. **Directory API provisioning (optional)** — a Google **service account** with domain-wide delegation lets Bifrost list users and groups from the Workspace directory for bulk import and team sync.
You can run login-only (no service account) or full provisioning (with service account + domain-wide delegation).
## Prerequisites
- A Google Workspace domain with **Super Admin** access to the Admin console
- A Google Cloud project where you can create OAuth clients and service accounts
- Bifrost Enterprise deployed and accessible
- The redirect URI for your Bifrost instance (e.g. `https://your-bifrost-domain.com/login`)
- Bifrost [roles](./rbac) created for the roles you plan to map
---
## Step 1: Configure the OAuth consent screen
1. In the Google Cloud Console, go to **APIs & Services → OAuth consent screen**.
<Frame>
<img src="/media/user-provisioning/gws-apis-and-services.png" alt="Google OAuth consent screen configuration" />
</Frame>
2. Choose **Internal** if you only want Workspace users, or **External** otherwise.
3. Fill in App name, support email, and developer contact.
4. Add the scopes: `openid`, `profile`, `email`.
5. Save.
---
## Step 2: Create an OAuth Client ID
1. Open **APIs & Services → Credentials → Create credentials → OAuth client ID**.
<Frame>
<img src="/media/user-provisioning/gws-auth-client-creation.png" alt="Creating a Google OAuth Web Application Client ID" />
</Frame>
2. Configure:
| Field | Value |
| --- | --- |
| **Application type** | Web application |
| **Name** | Bifrost Enterprise |
| **Authorized JavaScript origins** | `https://your-bifrost-domain.com` |
| **Authorized redirect URIs** | `https://your-bifrost-domain.com/login` |
3. Save and copy the **Client ID** and **Client Secret**.
---
## Step 3: (Optional) Create a service account for Directory API access
Skip this section if you only want SSO login without directory-based user import.
1. Go to **IAM & Admin → Service Accounts → Create service account**.
<Frame>
<img src="/media/user-provisioning/gws-service-account-id.png" alt="Creating a Google service account" />
</Frame>
2. Give it a name (e.g. `bifrost-provisioning`). You can skip the "Grant this service account access to project" step — no GCP IAM roles are required; access is granted via domain-wide delegation in Step 5.
3. Open the service account → **Keys → Add Key → Create new key → JSON**. Download and store the JSON file securely.
4. From the service account **Details** tab, copy the **Unique ID** (a numeric value, **not** the email or OAuth Client ID).
---
## Step 4: Enable the Admin SDK API
If you're using the service account path:
1. Open **APIs & Services → Library**.
2. Search for **Admin SDK API** and click **Enable**.
---
## Step 5: Set up domain-wide delegation
1. In the [Google Admin Console](https://admin.google.com), go to **Security → Access and data control → API controls → Manage Domain Wide Delegation**.
<Frame>
<img src="/media/user-provisioning/gws-domain-wide-delegation.png" alt="Google Workspace Domain-Wide Delegation configuration" />
</Frame>
2. Click **Add new**.
3. Enter the service account's **Unique ID** (from Step 3).
4. Add these OAuth scopes (copy the full URLs, comma-separated):
```
https://www.googleapis.com/auth/admin.directory.user.readonly,
https://www.googleapis.com/auth/admin.directory.group.readonly,
https://www.googleapis.com/auth/admin.directory.group.member.readonly
```
5. **Authorize**.
<Note>
Domain-wide delegation requires impersonating an admin user. Pick an admin email that will persist (e.g. a dedicated `sso-admin@company.com`) — Bifrost uses this as the **Admin Email** in configuration.
</Note>
---
## Step 6: Configure Bifrost
### Using the Bifrost dashboard
1. In Bifrost, go to **Governance → User Provisioning**.
2. Select **Google Workspace** as the SCIM Provider.
3. Fill in the fields:
| Field | Value |
| --- | --- |
| **Domain** | Your Google Workspace primary domain (e.g. `company.com`) |
| **Client ID** | OAuth Client ID from Step 2 |
| **Client Secret** | OAuth Client Secret from Step 2 |
| **Audience** | Optional override (defaults to Client ID) |
| **Admin Email** | Admin user to impersonate for Directory API (Step 5) |
| **Service Account Source** | Choose one: Paste JSON / Environment variable / File path |
| **Service Account JSON / Env Var / File** | The value for the chosen source |
<Frame>
<img src="/media/user-provisioning/gws-form.png" alt="Bifrost Google Workspace configuration form" />
</Frame>
4. Click **Verify** — Bifrost validates the OAuth client and, if a service account is provided, attempts a Directory API impersonation to confirm delegation is working.
5. Configure **Attribute → Role / Team / Business Unit** mappings to map groups or organizational units to Bifrost roles and teams.
6. Toggle **Enabled** and click **Save Configuration**.
### Using `config.json`
```json
{
"scim_config": {
"enabled": true,
"provider": "google",
"config": {
"domain": "company.com",
"clientId": "123-abc.apps.googleusercontent.com",
"clientSecret": "${GOOGLE_WORKSPACE_CLIENT_SECRET}",
"adminEmail": "sso-admin@company.com",
"serviceAccountEnvVar": "GOOGLE_SA_JSON",
"teamIdsField": "groups"
}
}
}
```
Pick one of the three service-account sources: `serviceAccountJson` (raw JSON string), `serviceAccountEnvVar` (env var name holding the JSON), or `serviceAccountFile` (absolute path to the key file).
### Custom attribute mapping
You can also map any custom attributes to any entity (role, team or business unit). Make sure these are configured to send back to Bifrost in token configuration.
<Frame>
<img
src="/media/user-provisioning/custom-attribute-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
### Configuration reference
| Field | Required | Description |
| --- | --- | --- |
| `domain` | Yes | Google Workspace primary domain (e.g. `company.com`). |
| `clientId` | Yes | OAuth 2.0 Web Client ID from Step 2. |
| `clientSecret` | Yes | Client Secret — required for token revocation and for confidential server-side flows. |
| `audience` | No | Expected JWT audience. Defaults to `clientId`. |
| `adminEmail` | Yes | Workspace admin to impersonate via domain-wide delegation. Required when any service-account field is set. |
| `serviceAccountJson` | One of 3 | Raw JSON string of the service account key. |
| `serviceAccountEnvVar` | One of 3 | Name of the environment variable containing the JSON. |
| `serviceAccountFile` | One of 3 | Absolute path to the JSON key file on the Bifrost host. |
| `attributeRoleMappings` | Yes | Ordered list of attribute→role mappings. |
| `attributeTeamMappings` | No | Attribute→team mappings (all matches apply). |
| `attributeBusinessUnitMappings` | No | Attribute→business-unit mappings (all matches apply). |
<Warning>
Bifrost rejects configs that set a service-account credential source without `adminEmail` — domain-wide delegation cannot work without an impersonation subject.
</Warning>
---
## Testing the Integration
1. Open the Bifrost dashboard in an incognito window.
2. You're redirected to `accounts.google.com`; sign in with a Workspace user.
3. Verify you land on the Bifrost dashboard and appear under **Governance → Users**.
4. If provisioning is configured, open **Governance → User Provisioning → Import Users**, filter by a Workspace group, click **Preview**, and confirm users show up.
---
## Troubleshooting
### `admin_policy_enforced` or `access_denied` during OAuth
- The Workspace admin has blocked third-party OAuth apps. In the Admin Console, go to **Security → Access and data control → API controls** and allow the Bifrost OAuth client.
### `unauthorized_client: Client is unauthorized to retrieve access tokens`
- The service account Unique ID and scopes in **Domain-Wide Delegation** don't match. Re-enter the Unique ID (the numeric value from the service account's **Details** tab, not the OAuth client ID).
### `Not Authorized to access this resource/api` from Directory API
- The impersonated `adminEmail` is missing the **User Management Admin** role. Promote them in Admin Console → Admin roles.
- The Admin SDK API is not enabled on the Cloud project.
### Users see a consent prompt every login
- On the OAuth consent screen, ensure the app is **Published** (or **Internal** for Workspace-only apps) so it doesn't stay in testing mode.
### `domain_mismatch`
- The primary domain in the Workspace does not match the `domain` field. Use the primary domain, not an alias.
---
## Next Steps
- [User Provisioning overview](./user-provisioning) — capabilities, attribute mappings, bulk import
- [Role-Based Access Control](./rbac) — configure custom roles before mapping
- [Audit Logs](./audit-logs) — track authentication events

View File

@@ -0,0 +1,237 @@
---
title: "Setting up Keycloak"
description: "Step-by-step guide to configure a self-hosted Keycloak realm as your identity provider for Bifrost Enterprise SSO and user provisioning."
icon: "lock"
---
## Overview
This guide walks you through configuring [Keycloak](https://www.keycloak.org) as your identity provider for Bifrost Enterprise. Keycloak uses standard OIDC with JWKS-based JWT validation, and Bifrost uses the same client for both user login and Admin REST API access (via the Service Account of a confidential client).
After completing this guide, users will sign in with their Keycloak credentials and admins can bulk-import users and groups via the Keycloak Admin REST API.
## Prerequisites
- A running Keycloak server (self-hosted or cloud) with admin access to a realm
- Bifrost Enterprise deployed and accessible
- The redirect URI for your Bifrost instance (e.g. `https://your-bifrost-domain.com/login`)
- Bifrost [roles](./rbac) created for the roles you plan to map
---
## Step 1: Create a Client
1. In the Keycloak Admin Console, select your realm and go to **Clients → Create client**.
<Frame>
<img src="/media/user-provisioning/keycloak-create-client.png" alt="Creating a client in Keycloak" />
</Frame>
2. Configure the client:
| Field | Value |
| --- | --- |
| **Client type** | OpenID Connect |
| **Client ID** | `bifrost` (or your preferred identifier) |
| **Name** | `Bifrost Enterprise` |
3. On the **Capability config** step enable:
- **Client authentication** (makes it a confidential client)
- **Standard flow** (Authorization Code)
- **Service accounts roles** (required for Admin REST API access)
<Frame>
<img src="/media/user-provisioning/keycloak-capability-config.png" alt="Keycloak client capability configuration" />
</Frame>
4. On the **Login settings** step set:
| Field | Value |
| --- | --- |
| **Valid redirect URIs** | `https://your-bifrost-domain.com/login` |
| **Valid post logout redirect URIs** | `https://your-bifrost-domain.com` |
| **Web origins** | `https://your-bifrost-domain.com` |
5. **Save** the client.
---
## Step 2: Copy the client credentials
1. Open the client and go to the **Credentials** tab.
2. Copy the **Client Secret**.
<Frame>
<img src="/media/user-provisioning/keycloak-client-credentials.png" alt="Keycloak client credentials tab" />
</Frame>
---
## Step 3: Configure role and group mappers
Keycloak does not include realm roles or full group paths in tokens by default. Add two mappers on the client's dedicated scope.
1. Open the client → **Client Scopes** tab → click the client's `-dedicated` scope.
2. Click **Add mapper → By configuration**.
### Group Membership mapper
<Frame>
<img src="/media/user-provisioning/keycloak-group-mapper.png" alt="Group Membership mapper configuration" />
</Frame>
| Field | Value |
| --- | --- |
| **Mapper Type** | Group Membership |
| **Name** | `groups` |
| **Token Claim Name** | `groups` |
| **Full group path** | **On** |
| **Add to ID token** | **On** |
| **Add to access token** | **On** |
| **Add to userinfo** | **On** |
<Note>
Bifrost uses full group paths for consistent matching across SSO and bulk provisioning flows — keep **Full group path** enabled.
</Note>
### Realm Roles mapper
| Field | Value |
| --- | --- |
| **Mapper Type** | User Realm Role |
| **Name** | `realm_roles` |
| **Token Claim Name** | `realm_access.roles` |
| **Claim JSON Type** | String |
| **Multivalued** | **On** |
| **Add to ID token** | **On** |
| **Add to access token** | **On** |
---
## Step 4: Assign Admin REST API permissions
The same client runs both authentication and provisioning. Grant it read access to the realm so it can list users and groups.
1. Open the client → **Service accounts roles** tab.
2. Click **Assign role** and select:
- `realm-management` → **view-users** (required)
- `realm-management` → **view-realm** (recommended, enables group and role listing)
- `realm-management` → **query-groups** (optional, for group filters)
<Frame>
<img src="/media/user-provisioning/keycloak-service-account-roles.png" alt="Keycloak service account roles" />
</Frame>
---
## Step 5: Create realm roles and groups
Create the roles and groups you plan to map into Bifrost.
1. **Realm → Realm roles → Create role** for each role (e.g. `bifrost-admin`, `bifrost-developer`, `bifrost-viewer`).
2. **Realm → Groups → Create group** for each team you want to sync (e.g. `/platform`, `/data-science`).
3. Assign users to the appropriate roles and groups under **Users → your user → Role mapping** / **Groups**.
---
## Step 6: Configure Bifrost
### Using the Bifrost dashboard
1. In Bifrost, go to **Governance → User Provisioning**.
2. Select **Keycloak** as the SCIM Provider.
3. Fill in the fields:
| Field | Value |
| --- | --- |
| **Server URL** | `https://keycloak.company.com` (no `/realms/...` suffix) |
| **Realm** | Your realm name (e.g. `master`, `bifrost-prod`) |
| **Client ID** | Client ID from Step 1 |
| **Client Secret** | Client Secret from Step 2 |
| **Audience** | Optional — defaults to Client ID |
| **Team IDs Field** | Leave as `groups` (default) or change if you used a different mapper name |
4. Click **Verify** — Bifrost connects to Keycloak's JWKS and Admin REST API to confirm the client and service-account roles.
5. Configure **Attribute → Role / Team / Business Unit** mappings if needed.
6. Toggle **Enabled** and click **Save Configuration**.
<Frame>
<img src="/media/user-provisioning/keycloak-bifrost-config.png" alt="Bifrost Keycloak configuration form" />
</Frame>
### Using `config.json`
```json
{
"scim_config": {
"enabled": true,
"provider": "keycloak",
"config": {
"serverUrl": "https://keycloak.company.com",
"realm": "bifrost-prod",
"clientId": "bifrost",
"clientSecret": "${KEYCLOAK_CLIENT_SECRET}",
"teamIdsField": "groups"
}
}
}
```
### Configuration reference
| Field | Required | Description |
| --- | --- | --- |
| `serverUrl` | Yes | Base URL of the Keycloak server. Must be a valid URL (e.g. `https://keycloak.company.com`) and must **not** include `/realms/...`. |
| `realm` | Yes | Realm name. |
| `clientId` | Yes | Client ID created in Step 1. |
| `clientSecret` | Yes | Client secret — required because the client is confidential. |
| `audience` | No | Expected JWT audience. Defaults to `clientId`. |
| `teamIdsField` | No | JWT claim for group IDs. Defaults to `groups`. |
| `attributeRoleMappings` | No | Ordered list of attribute→role mappings. |
| `attributeTeamMappings` | No | Attribute→team mappings (all matches apply). |
| `attributeBusinessUnitMappings` | No | Attribute→business-unit mappings (all matches apply). |
---
## Testing the Integration
1. Open the Bifrost dashboard in an incognito window.
2. You'll be redirected to Keycloak's login page.
3. Sign in with a Keycloak user that has one of the roles you mapped.
4. Verify the user appears under **Governance → Users** with the expected role and teams.
5. From **Governance → User Provisioning → Import Users**, verify the service account can list users.
---
## Troubleshooting
### `serverUrl must not include /realms/{realm}`
The `serverUrl` field is the base Keycloak URL. Set the realm in the separate **Realm** field. Example: `https://keycloak.company.com` + realm `bifrost-prod` — **not** `https://keycloak.company.com/realms/bifrost-prod`.
### Users redirected back to login
- Confirm the client's **Valid redirect URIs** exactly match your Bifrost login URL (trailing slash matters).
- Verify the client is **Enabled** in Keycloak.
### Roles not appearing in the token
- Check that the **User Realm Role** mapper adds to both ID and Access tokens.
- Use `Evaluate` on the client scope to preview the token a user would receive.
### Service account cannot list users
- Confirm `realm-management → view-users` is assigned under **Service accounts roles**.
- If you enabled **Authorization** on the client, service account tokens may not work — disable Authorization (fine-grained authz) for this client.
### `jwks keys not found`
- Make sure the server URL is reachable from Bifrost. The JWKS endpoint is `{serverUrl}/realms/{realm}/protocol/openid-connect/certs`.
---
## Next Steps
- [User Provisioning overview](./user-provisioning) — capabilities, attribute mappings, bulk import
- [Role-Based Access Control](./rbac) — configure custom roles before mapping
- [Audit Logs](./audit-logs) — track authentication events

View File

@@ -0,0 +1,365 @@
---
title: "Setting up Okta"
description: "Step-by-step guide to configure Okta as your identity provider for Bifrost Enterprise SSO authentication."
icon: "o"
---
## Overview
This guide walks you through configuring Okta as your identity provider for Bifrost Enterprise. After completing this setup, your users will be able to sign in to Bifrost using their Okta credentials, with roles and team memberships automatically synchronized.
## Prerequisites
- An Okta organization with admin access
- Bifrost Enterprise deployed and accessible
- The redirect URI for your Bifrost instance (e.g., `https://your-bifrost-domain.com/login`)
- Ensure you have created all the [roles in Bifrost](/enterprise/rbac) that you are aiming to map to with Okta.
---
## Step 1: Create an OIDC Application
1. Log in to the **Okta Admin Console**
2. Navigate to **Applications** → **Applications**
3. Click **Create App Integration**
<Frame>
<img src="/media/user-provisioning/okta-create-app.png" alt="Okta Applications page" />
</Frame>
4. In the dialog, select:
- **Sign-in method**: OIDC - OpenID Connect
- **Application type**: Web Application
<Frame>
<img src="/media/user-provisioning/okta-app-configuration.png" alt="Create new app integration dialog" />
</Frame>
5. Click **Next** to continue
---
## Step 2: Configure Application Settings
Configure the following settings for your application:
<Frame>
<img src="/media/user-provisioning/okta-app-integration-main-page.png" alt="New Web App Integration settings" />
</Frame>
**General Settings:**
- **App integration name**: `Bifrost Enterprise`
- **Logo** (optional): You can upload the Bifrost logo from [https://www.getmaxim.ai/bifrost/bifrost-logo-only.png](https://www.getmaxim.ai/bifrost/bifrost-logo-only.png)
**Grant type:**
- Enable **Authorization Code**
- Enable **Refresh Token**
**Sign-in redirect URIs:**
- Add your Bifrost login callback URL: `https://your-bifrost-domain.com/login`
**Sign-out redirect URIs (Optional):**
- Add your Bifrost base URL: `https://your-bifrost-domain.com`
**Assignments:**
- Choose **Skip group assignment for now** (we'll configure this later)
6. Click **Save** to create the application
7. After saving, note down the following from the **General** tab:
- **Client ID**
- **Client Secret** (click to reveal)
---
## Step 3: Create Custom Role Attribute (Optional)
<Note>
You can map any attribute (include custom roles/groups) to assign roles to users. You can learn more about
[RBAC](/enterprise/rbac) docs.
</Note>
To map Okta users to Bifrost roles (Admin, Developer, Viewer), you need to create a custom attribute.
1. Navigate to **Directory** → **Profile Editor**
<Frame>
<img src="/media/user-provisioning/okta-profile-editor-screen.png" alt="Okta Profile Editor" />
</Frame>
2. Click on your application's user profile (e.g., **Bifrost Enterprise User**)
3. Click **Add Attribute**
4. Configure the attribute:
<Frame>
<img src="/media/user-provisioning/okta-custom-attribute-creation.png" alt="Add custom attribute for bifrostRole" />
</Frame>
| Field | Value |
| --------------------- | ----------------------------------------------------------- |
| **Data type** | string |
| **Display name** | bifrostRole |
| **Variable name** | bifrostRole |
| **Enum** | Check "Define enumerated list of values" |
| **Attribute members** | Admin → `admin`, Developer → `developer`, Viewer → `viewer` |
| **Attribute type** | Personal |
5. Click **Save**
---
## Step 4: Add Role Claim to Tokens (If you have added custom role attribute)
Configure the authorization server to include the role in the access token.
1. Navigate to **Security** → **API** → **Authorization Servers**
2. Click on your authorization server (e.g., **default**)
3. Go to the **Claims** tab
4. Click **Add Claim**
<Frame>
<img src="/media/user-provisioning/okta-claim-addition.png" alt="Add role claim" />
</Frame>
Configure the claim:
| Field | Value |
| ------------------------- | -------------------- |
| **Name** | `role` |
| **Include in token type** | Access Token, Always |
| **Value type** | Expression |
| **Value** | `user.bifrostRole` |
| **Include in** | Any scope |
5. Click **Create**
<Note>
If you named your custom attribute differently, update the Value expression accordingly (e.g.,
`user.yourAttributeName`).
</Note>
---
## Step 5: Configure Groups
Bifrost can automatically sync Okta groups for two purposes:
- **Team synchronization** — Groups are synced as Bifrost teams
- **Role mapping** — Groups can be mapped to Bifrost roles (Admin, Developer, Viewer) using Group-to-Role Mappings in the Bifrost UI.
### Create Groups in Okta
1. Navigate to **Directory** → **Groups**
<Frame>
<img src="/media/user-provisioning/okta-groups-page.png" alt="Okta Groups page" />
</Frame>
2. Click **Add group**
3. Create groups that correspond to your teams or roles (e.g., `bifrost-staging-admins`, `bifrost-staging-viewers`)
<Frame>
<img src="/media/user-provisioning/okta-create-groups.png" alt="Groups created in Okta" />
</Frame>
<Note>
Use a consistent naming convention for your groups. This makes it easier to configure group filters and role mappings
later.
</Note>
### Add Groups Claim to Tokens
This approach adds the groups claim through your authorization server, providing more flexibility for complex configurations.
1. Navigate to **Security** → **API** → **Authorization Servers**
2. Select your authorization server (e.g., **default**)
3. Go to the **Claims** tab
4. Click **Add Claim**
Configure the groups claim:
| Field | Value |
| ------------------------- | ----------------------------------------------------------- |
| **Name** | `groups` |
| **Include in token type** | ID Token, Always |
| **Value type** | Groups |
| **Filter** | Matches regex: `.*` (or specify a prefix like `bifrost-.*`) |
| **Include in** | Any scope |
5. Click **Create**
---
## Step 6: Assign Users to the Application
1. Navigate to your application's **Assignments** tab
<Frame>
<img src="/media/user-provisioning/okta-assign-users.png" alt="Application Assignments tab" />
</Frame>
2. Click **Assign** → **Assign to People** or **Assign to Groups**
### For Assigning Roles (If step 3 and step 4 are followed)
For each user, set their **bifrostRole** (if you are planning to do role-level mapping):
<Frame>
<img src="/media/user-provisioning/okta-assign-custom-role.png" alt="Assign custom role to user" />
</Frame>
4. Click **Save and Go Back**
---
## Step 7: Create API token for bulk user and team sync
To create an API token, navigate to **Security** → **API** → **Tokens**.
<Frame>
<img src="/media/user-provisioning/okta-tokens-screen.png" alt="Okta API tokens screen" />
</Frame>
1. Click on "Create token"
<Frame>
<img src="/media/user-provisioning/okta-create-token-form.png" alt="Create token dialog in Okta" />
</Frame>
2. Copy token to be used in the next step.
## Step 8: Configure Bifrost
Now configure Bifrost to use Okta as the identity provider.
### Using the Bifrost UI
<Frame>
<img src="/media/user-provisioning/okta-form.png" alt="Create token dialog in Okta" />
</Frame>
1. Navigate to **Governance** → **User Provisioning** in your Bifrost dashboard
2. Select **Okta** as the SCIM Provider
3. Enter the following configuration:
| Field | Value |
| ----------------- | -------------------------------------------------------------------- |
| **Client ID** | Your Okta application Client ID |
| **Issuer URL** | Issuer URL |
| **Audience** | Your API audience (e.g., `api://default` or custom) |
| **Client Secret** | Your Okta application Client Secret (optional, for token revocation) |
4. **Verify** configuration and see if you get any errors. Make sure you get no errors/warnings.
5. Toggle **Enabled** to activate the provider
6. Click **Save Configuration**
<Warning>
After saving, you'll need to restart your Bifrost server for the changes to take effect.
</Warning>
### Attribute Mappings
Attribute mappings let you translate Okta claim values into Bifrost roles, teams, or business units without restructuring your Okta claims. Bifrost supports three mapping types:
- **`attributeRoleMappings`**: map a claim value to a Bifrost role (Admin, Developer, Viewer, or a custom role)
- **`attributeTeamMappings`**: map a claim value to a Bifrost team
- **`attributeBusinessUnitMappings`**: map a claim value to a Bifrost business unit
These mappings work with any Okta claim — the `groups` claim from Step 5, the custom `role` claim from Step 4, or any other claim your authorization server includes in the token (e.g., `department`, `organization`).
To configure attribute mappings:
1. In the User Provisioning configuration, scroll down to **Attribute Mappings**
2. Click **Add Mapping** under the relevant mapping type (Role, Team, or Business Unit)
3. Enter the **Attribute** (the claim name from the token), the **Value** to match, and the target **Role**, **Team**, or **Business Unit**
4. Repeat for each rule you need
<Frame>
<img
src="/media/user-provisioning/attribute-to-entity-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
<Note>
When you mark value as "*" - the claim value is mapped as is to the entity name. Values comparisons are case-insensitive.
</Note>
### Custom attribute mapping
You can also map any custom attributes to any entity (role, team or business unit). Make sure these are configured to send back to Bifrost in token configuration.
<Frame>
<img
src="/media/user-provisioning/custom-attribute-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
#### Evaluation rules
- **Role mappings**: Ordered, first match wins. If no rule matches, users are not allowed to login into the system.
- **Team and business unit mappings**: All matching rules apply — users can be placed on multiple teams and business units simultaneously.
- **Claim values**: Can be strings, arrays, or nested objects. Bifrost resolves dotted paths (e.g., `realm_access.roles`).
5. Click **Save Configuration**
<Warning>After saving, you'll need to restart your Bifrost server for the changes to take effect.</Warning>
### Configuration Reference
| Field | Required | Description |
| ------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `issuerUrl` | Yes | Okta authorization server URL (e.g., `https://your-domain.okta.com/oauth2/default`) |
| `clientId` | Yes | Application Client ID from Okta |
| `clientSecret` | Yes | Application Client Secret (enables token revocation) |
| `audience` | Yes | API audience identifier from your authorization server |
| `attributeRoleMappings` | Yes | Ordered list of attribute→role mappings. First match wins. |
| `attributeTeamMappings` | No | Attribute→team mappings (all matches apply). |
| `attributeBusinessUnitMappings` | No | Attribute→business-unit mappings (all matches apply). |
---
## Testing the Integration
1. Open your Bifrost dashboard in a new browser or incognito window
2. You should be redirected to Okta for authentication
3. Log in with an assigned user
4. After successful authentication, you'll be redirected back to Bifrost
5. Verify the user appears in the Bifrost users list with the correct role
---
## Troubleshooting
### User not redirected to Okta
- Verify the SCIM provider is enabled in Bifrost
- Check that the Bifrost server was restarted after configuration
- Ensure the Issuer URL is correct and accessible
### Attribute mapping is not working
- Verify that token configuration includes all the attributes used for mapping.
### Token refresh failing
- Ensure the **Refresh Token** grant type is enabled for your application
- Verify the `offline_access` scope is included in your authorization requests
---
## Next Steps
- **[User Provisioning (SCIM)](./user-provisioning)** - Overview of SCIM in Bifrost and alternative identity providers
- **[Advanced Governance](./advanced-governance)** - Learn about user budgets and compliance features
- **[Role-Based Access Control](./advanced-governance#role-hierarchy)** - Understand the Admin, Developer, Viewer hierarchy
- **[Audit Logs](./audit-logs)** - Monitor user authentication and activity

View File

@@ -0,0 +1,246 @@
---
title: "Setting up Zitadel"
description: "Step-by-step guide to configure Zitadel (cloud or self-hosted) as your identity provider for Bifrost Enterprise SSO and user provisioning."
icon: "cloud"
---
## Overview
This guide walks you through configuring [Zitadel](https://zitadel.com) as your identity provider for Bifrost Enterprise. Zitadel uses standard OIDC with JWKS-based JWT validation, plus a separate **service account** for user provisioning (Zitadel web applications cannot perform the `client_credentials` grant — a dedicated service account is required for directory-level reads).
After completing this guide users will sign in to Bifrost with their Zitadel credentials, and admins can bulk-import users and teams from the Zitadel Management API.
## Prerequisites
- A Zitadel instance (cloud at `*.zitadel.cloud` or self-hosted) with admin access
- An existing Zitadel **Project** in the organization you want to connect
- Bifrost Enterprise deployed and accessible
- The redirect URI for your Bifrost instance (e.g. `https://your-bifrost-domain.com/login`)
- Bifrost [roles](./rbac) created for the roles you plan to map (Admin, Developer, Viewer, or custom)
---
## Step 1: Create a Web Application
The Web Application is what end users log in through.
1. Open the Zitadel Console and choose **Projects → your project → New Application**.
<Frame>
<img src="/media/user-provisioning/zitadel-create-app.png" alt="Creating a new application in Zitadel" />
</Frame>
2. Configure the application:
| Field | Value |
| --- | --- |
| **Type** | Web |
| **Authentication method** | PKCE (recommended) or Basic |
| **Redirect URI** | `https://your-bifrost-domain.com/login` |
| **Post logout URI** | `https://your-bifrost-domain.com` |
3. After creating the app, note the **Client ID** from the application detail page.
<Frame>
<img src="/media/user-provisioning/zitadel-client-id.png" alt="Zitadel application Client ID" />
</Frame>
4. If you chose a confidential authentication method, also copy the **Client Secret** (shown once).
---
## Step 2: Enable role claims on the project (Optional)
<Note>
In Bifrost, you can map any attribute to role. If you decide to map Zitadel project roles, then follow step 2 and step 3.
</Note>
Zitadel only emits role claims in access tokens when the project is configured to assert them.
1. Open **Projects → your project → General**.
2. Enable **Assert Roles on Authentication**.
3. Enable **Check Authorization on Authentication** if you want to enforce that every user has at least one project role.
<Frame>
<img src="/media/user-provisioning/zitadel-assert-roles.png" alt="Assert Roles on Authentication toggle in Zitadel" />
</Frame>
4. Note the **Project ID** — you'll need it for the Bifrost config so Bifrost can resolve the correct project roles.
<Note>
Without **Assert Roles on Authentication**, the token will not contain role claims and every user will fall back to the default role (Viewer, or Admin for the first signin).
</Note>
---
## Step 3: Create project roles (Optional)
<Frame>
<img src="/media/user-provisioning/zitadel-project-roles.png" alt="Create project roles in Zitadel" />
</Frame>
1. In the same project, open the **Roles** tab and create a role for each Bifrost role you plan to map. Common pattern:
2. Authorize users to the relevant roles via **Users → Roles**.
<Frame>
<img src="/media/user-provisioning/zitadel-user-role-assignment.png" alt="Create project roles in Zitadel" />
</Frame>
---
## Step 4: Create a service account for provisioning
Web apps in Zitadel cannot use the `client_credentials` grant. Bifrost needs a dedicated service account to list users via the Management API.
1. Navigate to **Users → Service Accounts → New**.
<Frame>
<img src="/media/user-provisioning/zitadel-service-account-create.png" alt="Creating a service account in Zitadel" />
</Frame>
2. Name it (e.g. `bifrost-provisioning`) and create it.
3. Open the service account → **Actions → Generate Client Secret**.
<Frame>
<img src="/media/user-provisioning/zitadel-service-account-key.png" alt="Creating a service account in Zitadel" />
</Frame>
4. **Copy the Client ID and Client Secret immediately** — the secret is shown only once.
<Warning>
Store the service account Client Secret in your password manager. It cannot be retrieved after this screen.
</Warning>
5. Grant the service account **IAM_USER_READ** (or **Org Owner** if you want broader visibility):
- Organization → **Managers → Add Manager** → select the service account → role `IAM_USER_READ`.
<Frame>
<img src="/media/user-provisioning/zitadel-service-account-role.png" alt="Assigning IAM_USER_READ to the service account" />
</Frame>
---
## Step 5: App token settings
1. Change **Auth Token Type** to JWT.
2. Enable roles and profile info in ID token.
<Frame>
<img src="/media/user-provisioning/zitadel-token-settings.png" alt="Assigning IAM_USER_READ to the service account" />
</Frame>
## Step 6: Configure Bifrost
### Using the Bifrost dashboard
1. In Bifrost, go to **Governance → User Provisioning**.
2. Select **Zitadel** as the SCIM Provider.
3. Fill in the fields:
| Field | Value |
| --- | --- |
| **Domain** | Your Zitadel host, e.g. `my-instance.zitadel.cloud` or `auth.company.com` (no scheme, no path) |
| **Project ID** | The project ID from Step 2 |
| **Client ID** | Web Application Client ID from Step 1 |
| **Client Secret** | Web Application Client Secret from Step 1 (optional for PKCE) |
| **Audience** | Optional access-token audience override |
| **Service Account Client ID** | From Step 4 |
| **Service Account Client Secret** | From Step 4 |
4. Click **Verify** — Bifrost connects to Zitadel's JWKS and service account token endpoints to confirm the credentials.
5. Configure **Attribute → Role / Team / Business Unit** mappings if you need to translate project roles or metadata into Bifrost roles.
6. Toggle **Enabled** and click **Save Configuration**.
<Frame>
<img src="/media/user-provisioning/zitadel-form.png" alt="Creating a service account in Zitadel" />
</Frame>
### Using `config.json`
```json
{
"scim_config": {
"enabled": true,
"provider": "zitadel",
"config": {
"domain": "my-instance.zitadel.cloud",
"projectId": "123456789012345678",
"clientId": "123456789012345678@my-project",
"clientSecret": "${ZITADEL_CLIENT_SECRET}",
"serviceAccountClientId": "987654321098765432@my-project",
"serviceAccountClientSecret": "${ZITADEL_SA_CLIENT_SECRET}",
"teamIdsField": "groups"
}
}
}
```
### Custom attribute mapping
You can also map any custom attributes to any entity (role, team or business unit). Make sure these are configured to send back to Bifrost in token configuration.
<Frame>
<img
src="/media/user-provisioning/custom-attribute-mapping.png"
alt="Attribute Mappings configuration in Bifrost"
/>
</Frame>
### Configuration reference
| Field | Required | Description |
| --- | --- | --- |
| `domain` | Yes | Zitadel instance host (no scheme). Examples: `my-instance.zitadel.cloud`, `auth.company.com`. |
| `clientId` | Yes | Client ID of the Web Application used for user login. |
| `clientSecret` | Yes | Web Application secret. Omit for PKCE-only flows. |
| `projectId` | Yes | Required to resolve project-scoped role claims and sync role grants. |
| `audience` | No | Override the expected JWT `aud` claim. |
| `serviceAccountClientId` | Yes | Service account used to list users via the Management API. |
| `serviceAccountClientSecret` | Yes | Service account secret (shown once in Zitadel). |
| `attributeRoleMappings` | Yes | Ordered list of attribute→role mappings. |
| `attributeTeamMappings` | No | Attribute→team mappings (all matches apply). |
| `attributeBusinessUnitMappings` | No | Attribute→business-unit mappings (all matches apply). |
---
## Testing the Integration
1. Open the Bifrost dashboard in an incognito window.
2. You'll be redirected to Zitadel. Sign in with a user who has a project authorization.
3. On successful login you return to Bifrost and appear in **Governance → Users** with the correct role.
4. From **Governance → User Provisioning → Import Users**, verify you can preview and import additional users via the service account.
---
## Troubleshooting
### `role claims missing in token`
- Enable **Assert Roles on Authentication** on the project (Step 2).
- Ensure the user has an active authorization for the project.
### `invalid audience` when validating the JWT
- Check the `audience` field in the Bifrost config. It must match the `aud` claim issued by Zitadel. Leaving it empty uses the default (the project's resource owner).
### Service account cannot list users
- Confirm the service account has **IAM_USER_READ** or **Org Owner** role in the organization.
- Regenerate the client secret if you've lost it — the original secret cannot be retrieved.
### Redirect URI mismatch
- Zitadel requires an exact string match. Check for trailing slashes and `http` vs `https`.
---
## Next Steps
- [User Provisioning overview](./user-provisioning) — capabilities, attribute mappings, bulk import
- [Role-Based Access Control](./rbac) — configure custom roles before mapping
- [Audit Logs](./audit-logs) — track authentication events

View File

@@ -0,0 +1,197 @@
---
title: "User Provisioning (SCIM)"
description: "Authenticate users, sync teams, and provision roles and business units from your identity provider using SCIM-backed OAuth 2.0 / OIDC flows."
icon: "users-gear"
---
## Overview
Bifrost Enterprise uses **SCIM-backed identity provisioning** to connect your organization's identity provider to Bifrost. A single configuration gives you:
- **Single sign-on (SSO)** via OAuth 2.0 / OIDC with JWKS-based JWT validation
- **Automatic role assignment** using custom claims, app roles, or group-to-role mappings
- **Team synchronization** from IdP groups into Bifrost teams
- **Business unit mapping** from IdP attributes to Bifrost business units
- **Bulk user provisioning** with filter-preview before import
- **Silent token refresh** using server-stored refresh tokens
Once configured, users sign in to Bifrost with their corporate credentials and inherit the right [role and permissions](./rbac) immediately — no manual account creation.
<Frame>
<img src="/media/user-provisioning/scim-overview.png" alt="User Provisioning overview in Bifrost dashboard" />
</Frame>
---
## Supported Identity Providers
Pick your IdP to follow a step-by-step setup guide. All providers share the same Bifrost configuration surface — the only difference is how the OAuth client and role/group claims are created on the provider side.
<CardGroup cols={3}>
<Card title="Okta" icon="o" href="/enterprise/setting-up-okta">
OIDC with Org or Custom Authorization Servers, plus group-to-role mapping and API tokens for bulk user sync.
</Card>
<Card title="Microsoft Entra" icon="microsoft" href="/enterprise/setting-up-entra">
Entra ID (Azure AD) with app roles, group claims, and v1.0 / v2.0 token support.
</Card>
<Card title="Zitadel" icon="cloud" href="/enterprise/setting-up-zitadel">
Cloud or self-hosted Zitadel with project-scoped role claims and service-account-based provisioning.
</Card>
<Card title="Google Workspace" icon="google" href="/enterprise/setting-up-google-workspace">
Google Workspace domains with OAuth login plus optional Directory API sync via a service account.
</Card>
</CardGroup>
---
## How it works
<Frame>
<img src="/media/user-provisioning/scim-flow.png" alt="SCIM authentication and provisioning flow" />
</Frame>
1. **Login** — Bifrost redirects unauthenticated users to the provider's authorization endpoint (Authorization Code flow).
2. **Token exchange** — on callback, Bifrost exchanges the code for an access token and refresh token, stores them in an `HttpOnly` cookie / server session, and validates the JWT against the provider's JWKS.
3. **Identity extraction** — configurable JWT claims (`userIdField`, `rolesField`, `teamIdsField`) are mapped to a Bifrost user, role, and teams. Provider-specific app roles or custom attributes override claim lookup.
4. **Attribute mapping** — optional `attributeRoleMappings`, `attributeTeamMappings`, and `attributeBusinessUnitMappings` translate arbitrary claim values (e.g., a department string or Okta group name) into Bifrost roles, teams, or business units.
5. **Bulk import** — admins can preview users matching a filter and bulk-import them via the dashboard, which calls the provider's user directory API.
6. **Silent refresh** — when the access token expires, Bifrost uses the stored refresh token to mint a new one without requiring re-login.
---
## Capabilities
| Capability | Description |
| --- | --- |
| **OAuth 2.0 / OIDC SSO** | Authorization Code + PKCE with configurable scopes (`openid profile email offline_access`). |
| **JWKS validation** | JWTs are validated against the provider's published JWKS keys; configuration is cached and auto-refreshed. |
| **Role mapping** | Map from a claim value (string or array) to Admin / Developer / Viewer or a custom role. Highest-privilege wins when multiple match. |
| **Team mapping** | Map multiple claim values to Bifrost teams in a single pass (a user can belong to many teams). |
| **Business unit mapping** | Same as team mapping but scoped to business units. |
| **Provisioning preview** | Preview up to 50 users matching filters (groups, roles, departments) before importing. |
| **Bulk import** | Import matched users into Bifrost with role + team + BU assignments applied. |
| **Team sync** | Sync IdP groups as Bifrost teams with a single action. |
| **Business unit sync** | Sync IdP organizational units as Bifrost business units. |
| **Deprovisioning** | Re-running import reconciles removed users and updates role / team assignments. |
| **API key pass-through** | Requests using Bifrost API keys (`bfst-*`) bypass SCIM middleware so inference traffic is not affected. |
---
## Configuration reference
All providers share the same outer config shape in `config.json`:
```json
{
"scim_config": {
"enabled": true,
"provider": "okta | entra | zitadel | keycloak | google",
"config": {
"...": "provider-specific fields — see each IdP guide"
}
}
}
```
Shared fields across providers:
| Field | Required | Description |
| --- | --- | --- |
| `clientId` | Yes | OAuth client ID from the identity provider. |
| `clientSecret` | Usually | Client secret. Required for confidential clients and (where applicable) token revocation. |
| `audience` | Optional | JWT audience to validate against. Defaults vary per provider. |
| `attributeRoleMappings` | Optional | Ordered list of `{ attribute, value, role }` rules evaluated top-to-bottom. |
| `attributeTeamMappings` | Optional | List of `{ attribute, value, team }` rules (all matches apply). |
| `attributeBusinessUnitMappings` | Optional | List of `{ attribute, value, businessUnit }` rules (all matches apply). |
Provider-specific fields (domain, tenant ID, server URL, service-account credentials) are documented in each IdP's setup guide.
<Note>
Changing `scim_config` at runtime through the UI is applied after saving. For file-based configuration, restart the Bifrost server to pick up changes.
</Note>
---
## Configuring from the dashboard
1. Navigate to **Governance → User Provisioning** in the Bifrost dashboard.
2. Select your identity provider from the **SCIM Provider** dropdown.
3. Fill in the provider-specific fields. Required fields are marked and validated on **Verify**.
<Frame>
<img src="/media/user-provisioning/scim-provider-select.png" alt="Selecting a SCIM provider in the Bifrost dashboard" />
</Frame>
4. Click **Verify** to test credentials end-to-end. Bifrost will reach the provider's JWKS / directory endpoint and report any failures.
5. Configure **Attribute → Role / Team / Business Unit** mappings as needed.
6. Toggle **Enabled** and click **Save Configuration**.
<Warning>
After enabling a new provider, the next dashboard load redirects to your IdP for login. Test in an incognito window first to avoid being locked out of your current session.
</Warning>
---
## Attribute mappings
Attribute mappings let you translate claim values into Bifrost roles, teams, or business units without forcing your IdP admins to restructure claim names.
<Frame>
<img src="/media/user-provisioning/scim-attribute-mapping.png" alt="Preview of users matching an import filter" />
</Frame>
Each mapping is an ordered rule:
```json
{
"attribute": "department",
"value": "Engineering",
"role": "developer"
}
```
Rules are evaluated top-to-bottom:
- **Role mappings** — first match wins. Set a fallback with `"attribute": "*"` at the end.
- **Team mappings** and **business unit mappings** — all matching rules apply, so a user with `department=Platform` and `group=sre` can be placed on multiple teams.
Claim values can be strings, arrays, or nested objects — Bifrost resolves dotted paths (e.g., `realm_access.roles`).
---
## Bulk user provisioning
Once SCIM is enabled, import users in bulk from your IdP:
1. Go to **Governance → User Provisioning → Import Users**.
2. Select a filter — groups, roles, departments, or a custom query depending on provider support.
3. Click **Preview** to see up to 50 matching users.
4. Click **Import** to create them in Bifrost with role / team / BU assignments applied.
<Frame>
<img src="/media/user-provisioning/scim-import-preview.png" alt="Preview of users matching an import filter" />
</Frame>
Re-running an import reconciles existing users — role and team changes in the IdP are reflected on the next import.
---
## Troubleshooting
| Symptom | Likely cause |
| --- | --- |
| Access denied: no application role or group mapping is assigned to this user. | Make sure you have assigned user to the Bifrost IdP application and they have a valid group/attribute mapping to role in Bifrost |
| Redirect loop on login | Make sure you have restarted pods/Bifrost instance after changing SCIM configuration, or check for a redirect URI mismatch. Exact string match required — check trailing slashes and `http` vs `https`. |
| `invalid audience` | `audience` field does not match the access token's `aud` claim. Use the same value your IdP issues. |
| Empty roles / teams | Claim mapping is off. Verify the JWT at [jwt.io](https://jwt.io) and check `rolesField` / `teamIdsField`. |
| Token refresh failing | `offline_access` scope missing or refresh token revoked. Re-enable the scope and re-authenticate. |
| First user gets Admin | By design — if no matching role mapping applies, the first user is promoted to Admin so they can finish configuration. Subsequent users default to Viewer. |
Provider-specific troubleshooting lives in each IdP's guide.
---
## Related
- [Role-Based Access Control](./rbac) — permissions model and custom roles
- [Advanced Governance](./advanced-governance) — budgets, limits, and compliance
- [Audit Logs](./audit-logs) — track authentication events and role changes