Skip to content

Commit 75f7f35

Browse files
committed
feat: adds enforce SCIM auth config option
1 parent 0ebc0c2 commit 75f7f35

File tree

8 files changed

+113
-78
lines changed

8 files changed

+113
-78
lines changed

framework/configstore/clientconfig.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type ClientConfig struct {
4545
LogRetentionDays int `json:"log_retention_days" validate:"min=1"` // Number of days to retain logs (minimum 1 day)
4646
EnableGovernance bool `json:"enable_governance"` // Enable governance on all requests
4747
EnforceGovernanceHeader bool `json:"enforce_governance_header"` // Enforce governance on all requests
48+
EnforceSCIMAuth bool `json:"enforce_scim_auth"` // Enforce SCIM auth on inference endpoints (enterprise only)
4849
AllowDirectKeys bool `json:"allow_direct_keys"` // Allow direct keys to be used for requests
4950
AllowedOrigins []string `json:"allowed_origins,omitempty"` // Additional allowed origins for CORS and WebSocket (localhost is always allowed)
5051
AllowedHeaders []string `json:"allowed_headers,omitempty"` // Additional allowed headers for CORS and WebSocket
@@ -100,6 +101,12 @@ func (c *ClientConfig) GenerateClientConfigHash() (string, error) {
100101
hash.Write([]byte("enforceGovernanceHeader:false"))
101102
}
102103

104+
if c.EnforceSCIMAuth {
105+
hash.Write([]byte("enforceSCIMAuth:true"))
106+
} else {
107+
hash.Write([]byte("enforceSCIMAuth:false"))
108+
}
109+
103110
if c.AllowDirectKeys {
104111
hash.Write([]byte("allowDirectKeys:true"))
105112
} else {

framework/configstore/migrations.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ func triggerMigrations(ctx context.Context, db *gorm.DB) error {
250250
if err := migrationAddRateLimitToTeamsAndCustomers(ctx, db); err != nil {
251251
return err
252252
}
253+
if err := migrationAddEnforceSCIMAuthColumn(ctx, db); err != nil {
254+
return err
255+
}
253256
return nil
254257
}
255258

@@ -3409,3 +3412,34 @@ func migrationAddRateLimitToTeamsAndCustomers(ctx context.Context, db *gorm.DB)
34093412
}
34103413
return nil
34113414
}
3415+
3416+
// migrationAddEnforceSCIMAuthColumn adds the enforce_scim_auth column to the client config table
3417+
func migrationAddEnforceSCIMAuthColumn(ctx context.Context, db *gorm.DB) error {
3418+
m := migrator.New(db, migrator.DefaultOptions, []*migrator.Migration{{
3419+
ID: "add_enforce_scim_auth_column",
3420+
Migrate: func(tx *gorm.DB) error {
3421+
tx = tx.WithContext(ctx)
3422+
migrator := tx.Migrator()
3423+
if !migrator.HasColumn(&tables.TableClientConfig{}, "enforce_scim_auth") {
3424+
if err := migrator.AddColumn(&tables.TableClientConfig{}, "enforce_scim_auth"); err != nil {
3425+
return err
3426+
}
3427+
}
3428+
return nil
3429+
},
3430+
Rollback: func(tx *gorm.DB) error {
3431+
tx = tx.WithContext(ctx)
3432+
migrator := tx.Migrator()
3433+
if migrator.HasColumn(&tables.TableClientConfig{}, "enforce_scim_auth") {
3434+
if err := migrator.DropColumn(&tables.TableClientConfig{}, "enforce_scim_auth"); err != nil {
3435+
return err
3436+
}
3437+
}
3438+
return nil
3439+
},
3440+
}})
3441+
if err := m.Migrate(); err != nil {
3442+
return fmt.Errorf("error running enforce SCIM auth column migration: %s", err.Error())
3443+
}
3444+
return nil
3445+
}

framework/configstore/rdb.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func (s *RDBConfigStore) UpdateClientConfig(ctx context.Context, config *ClientC
4646
LogRetentionDays: config.LogRetentionDays,
4747
EnableGovernance: config.EnableGovernance,
4848
EnforceGovernanceHeader: config.EnforceGovernanceHeader,
49+
EnforceSCIMAuth: config.EnforceSCIMAuth,
4950
AllowDirectKeys: config.AllowDirectKeys,
5051
PrometheusLabels: config.PrometheusLabels,
5152
AllowedOrigins: config.AllowedOrigins,
@@ -208,6 +209,7 @@ func (s *RDBConfigStore) GetClientConfig(ctx context.Context) (*ClientConfig, er
208209
LogRetentionDays: dbConfig.LogRetentionDays,
209210
EnableGovernance: dbConfig.EnableGovernance,
210211
EnforceGovernanceHeader: dbConfig.EnforceGovernanceHeader,
212+
EnforceSCIMAuth: dbConfig.EnforceSCIMAuth,
211213
AllowDirectKeys: dbConfig.AllowDirectKeys,
212214
AllowedOrigins: dbConfig.AllowedOrigins,
213215
AllowedHeaders: dbConfig.AllowedHeaders,

framework/configstore/tables/clientconfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type TableClientConfig struct {
2222
LogRetentionDays int `gorm:"default:365" json:"log_retention_days" validate:"min=1"` // Number of days to retain logs (minimum 1 day)
2323
EnableGovernance bool `gorm:"" json:"enable_governance"`
2424
EnforceGovernanceHeader bool `gorm:"" json:"enforce_governance_header"`
25+
EnforceSCIMAuth bool `gorm:"default:false" json:"enforce_scim_auth"`
2526
AllowDirectKeys bool `gorm:"" json:"allow_direct_keys"`
2627
MaxRequestBodySizeMB int `gorm:"default:100" json:"max_request_body_size_mb"`
2728
MCPAgentDepth int `gorm:"default:10" json:"mcp_agent_depth"`

transports/bifrost-http/handlers/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ func (h *ConfigHandler) updateConfig(ctx *fasthttp.RequestCtx) {
346346
}
347347
updatedConfig.AllowDirectKeys = payload.ClientConfig.AllowDirectKeys
348348

349+
if payload.ClientConfig.EnforceSCIMAuth != currentConfig.EnforceSCIMAuth {
350+
restartReasons = append(restartReasons, "Enforce SCIM auth on inference")
351+
}
352+
updatedConfig.EnforceSCIMAuth = payload.ClientConfig.EnforceSCIMAuth
353+
349354
// Only update MaxRequestBodySizeMB if explicitly provided (> 0) to avoid clearing stored value
350355
if payload.ClientConfig.MaxRequestBodySizeMB > 0 {
351356
if payload.ClientConfig.MaxRequestBodySizeMB != currentConfig.MaxRequestBodySizeMB {

ui/app/workspace/config/views/securityView.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,9 @@ export default function SecurityView() {
8181

8282
const enforceVirtualKeyChanged = localConfig.enforce_governance_header !== config.enforce_governance_header;
8383
const allowDirectKeysChanged = localConfig.allow_direct_keys !== config.allow_direct_keys;
84+
const enforceSCIMAuthChanged = localConfig.enforce_scim_auth !== config.enforce_scim_auth;
8485

85-
return originsChanged || headersChanged || authChanged || enforceVirtualKeyChanged || allowDirectKeysChanged;
86+
return originsChanged || headersChanged || authChanged || enforceVirtualKeyChanged || allowDirectKeysChanged || enforceSCIMAuthChanged;
8687
}, [config, localConfig, authConfig, bifrostConfig]);
8788

8889
const needsRestart = useMemo(() => {
@@ -96,7 +97,9 @@ export default function SecurityView() {
9697
const serverHeaders = config.allowed_headers?.slice().sort().join(",");
9798
const headersChanged = localHeaders !== serverHeaders;
9899

99-
return originsChanged || headersChanged;
100+
const enforceSCIMAuthChanged = localConfig.enforce_scim_auth !== config.enforce_scim_auth;
101+
102+
return originsChanged || headersChanged || enforceSCIMAuthChanged;
100103
}, [config, localConfig]);
101104

102105
const handleAllowedOriginsChange = useCallback((value: string) => {
@@ -268,6 +271,25 @@ export default function SecurityView() {
268271
/>
269272
</div>
270273
)}
274+
{/* Enforce SCIM Auth on Inference (Enterprise Only) */}
275+
{IS_ENTERPRISE && (
276+
<div className="flex items-center justify-between space-x-2 rounded-lg border p-4">
277+
<div className="space-y-0.5">
278+
<label htmlFor="enforce-scim-auth" className="text-sm font-medium">
279+
Enforce SCIM Auth on Inference
280+
</label>
281+
<p className="text-muted-foreground text-sm">
282+
Require authentication (API keys or SCIM/OAuth tokens) for all inference endpoints. When enabled, unauthenticated requests
283+
to chat completions, embeddings, etc. will be rejected.
284+
</p>
285+
</div>
286+
<Switch
287+
id="enforce-scim-auth"
288+
checked={localConfig.enforce_scim_auth}
289+
onCheckedChange={(checked) => handleConfigChange("enforce_scim_auth", checked)}
290+
/>
291+
</div>
292+
)}
271293
{/* Allow Direct API Keys */}
272294
<div className="flex items-center justify-between space-x-2 rounded-lg border p-4">
273295
<div className="space-y-0.5">

ui/lib/types/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ export interface CoreConfig {
388388
log_retention_days: number;
389389
enable_governance: boolean;
390390
enforce_governance_header: boolean;
391+
enforce_scim_auth: boolean;
391392
allow_direct_keys: boolean;
392393
allowed_origins: string[];
393394
allowed_headers: string[];
@@ -410,6 +411,7 @@ export const DefaultCoreConfig: CoreConfig = {
410411
log_retention_days: 365,
411412
enable_governance: true,
412413
enforce_governance_header: false,
414+
enforce_scim_auth: false,
413415
allow_direct_keys: false,
414416
allowed_origins: [],
415417
max_request_body_size_mb: 100,

0 commit comments

Comments
 (0)