Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions event-gateway/gateway-controller/cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,11 @@ func main() {
policyDefinitions[key] = def
}

// Built early so the startup rehydration below can use it too.
policyVersionResolver := utils.NewLoadedPolicyVersionResolver(policyDefinitions)

if err := hydrateStoredConfigsFromDatabaseOnStartup(
configStore, db, &cfg.Router, policyDefinitions, log,
configStore, db, &cfg.Router, policyDefinitions, policyVersionResolver, log,
cfg.Controller.Server.SkipInvalidDeploymentsOnStartup,
); err != nil {
log.Error("Failed to hydrate stored configurations required for startup", slog.Any("error", err))
Expand Down Expand Up @@ -427,7 +430,6 @@ func main() {
policyManager := policyxds.NewPolicyManager(policySnapshotManager, log)
policyManager.SetRuntimeStore(runtimeStore)

policyVersionResolver := utils.NewLoadedPolicyVersionResolver(policyDefinitions)
restTransformer := transform.NewRestAPITransformer(&cfg.Router, cfg, policyDefinitions)
llmTransformer := transform.NewLLMTransformer(configStore, db, &cfg.Router, cfg, policyDefinitions, policyVersionResolver)
transformerRegistry := transform.NewRegistry(restTransformer, llmTransformer)
Expand Down Expand Up @@ -482,7 +484,7 @@ func main() {
validator.SetPolicyValidator(policyValidator)

apiSvc := utils.NewAPIDeploymentService(configStore, db, snapshotManager, validator, &cfg.Router, eventHubInstance, gatewayID, secretsService)
mcpSvc := utils.NewMCPDeploymentService(configStore, db, snapshotManager, policyManager, policyValidator, eventHubInstance, gatewayID, secretsService)
mcpSvc := utils.NewMCPDeploymentService(configStore, db, snapshotManager, policyManager, policyValidator, eventHubInstance, gatewayID, secretsService, policyVersionResolver)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
llmSvc := utils.NewLLMDeploymentService(configStore, db, snapshotManager, lazyResourceXDSManager, templateDefinitions, apiSvc, &cfg.Router, policyVersionResolver, policyValidator)

cpClient := controlplane.NewClient(
Expand Down Expand Up @@ -534,7 +536,7 @@ func main() {
evtListener := coreeventlistener.NewEventListener(
eventHubInstance, configStore, db, snapshotManager, subscriptionSnapshotManager,
apiKeyXDSManager, lazyResourceXDSManager, policyManager, &cfg.Router, log, cfg,
policyDefinitions, secretsService,
policyDefinitions, secretsService, policyVersionResolver,
)
if webhookSecretService != nil {
evtListener.SetWebhookSecretHandler(eventlistener.NewWebhookSecretHandler(db, encryptionProviderManager, webhookSecretStore, webhookSecretSnapshotManager, log))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func hydrateStoredConfigsFromDatabaseOnStartup(
db storage.Storage,
routerConfig *config.RouterConfig,
policyDefinitions map[string]models.PolicyDefinition,
policyVersionResolver utils.PolicyVersionResolver,
log *slog.Logger,
skipInvalidDeployments bool,
) error {
Expand All @@ -53,7 +54,9 @@ func hydrateStoredConfigsFromDatabaseOnStartup(
"stored MCP proxy configuration",
log,
skipInvalidDeployments,
utils.HydrateStoredMCPConfig,
func(cfg *models.StoredConfig) error {
return utils.HydrateStoredMCPConfig(cfg, policyVersionResolver)
},
); err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions gateway/build-manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ policies:
- name: nvidia-nemoguard-content-safety
version: v0.9.0
pipPackage: git+https://github.com/wso2/gateway-controllers.git@policies/nvidia-nemoguard-content-safety/v0.9.0#subdirectory=policies/nvidia-nemoguard-content-safety
- name: oauth2-generator
version: v0.9.0
gomodule: github.com/wso2/gateway-controllers/policies/oauth2-generator@v0
- name: opaque-token-auth
version: v1.0.1
gomodule: github.com/wso2/gateway-controllers/policies/opaque-token-auth@v1
Expand Down
2 changes: 2 additions & 0 deletions gateway/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ policies:
gomodule: github.com/wso2/gateway-controllers/policies/model-weighted-round-robin@v1
- name: nvidia-nemoguard-content-safety
pipPackage: github.com/wso2/gateway-controllers/policies/nvidia-nemoguard-content-safety@v0
- name: oauth2-generator
gomodule: github.com/wso2/gateway-controllers/policies/oauth2-generator@v0
- name: opaque-token-auth
gomodule: github.com/wso2/gateway-controllers/policies/opaque-token-auth@v1
- name: openai-to-anthropic-transformer
Expand Down
130 changes: 119 additions & 11 deletions gateway/gateway-controller/api/management-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4425,19 +4425,74 @@ components:
properties:
type:
type: string
enum: [ api-key, other, none ]
enum: [ api-key, oauth2, other, none ]
description: >
"api-key" attaches the built-in set-headers policy by
default (overridable via policyName) and accepts either the
generic policyParams bucket or its own deprecated header/value
fields below. "oauth2" attaches the built-in oauth2-generator
policy by default (overridable via policyName) and always
requires policyParams - there is no typed-field fallback for
it. "other" attaches any policy by name - policyName and
policyParams are both required in that case, since there is
no built-in default or typed-field fallback for a
non-built-in auth scheme. "none": no upstream authentication -
the gateway attaches no auth policy of its own; auth (if any)
is handled entirely by user-attached policies elsewhere.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
policyName:
type: string
description: >
Name of the policy that implements this upstream auth.
Optional for "api-key"/"oauth2" (defaults to the built-in
policy for that type - api-key -> set-headers, oauth2 ->
oauth2-generator); set it to point at your own fork or a
newer major version's replacement instead. Required when
type is "other".
policyVersion:
type: string
pattern: '^v\d+$'
description: >
Major version of policyName to attach (e.g. "v1"), same
format and resolution rules as Policy.version. Optional -
defaults to the highest version available in the gateway
image when omitted. If set, it must match a version
actually loaded in this gateway build, or config validation
fails.
policyParams:
type: object
additionalProperties: true
description: >
Parameters passed verbatim to policyName (or the built-in
default for type). Required when type is "oauth2" or
"other" - oauth2 has no typed fields at all, only this
bucket (e.g. {tokenEndpoint: ..., clientId: ...,
clientSecret: ...} for the token-endpoint path, or
{bearerToken: ...} for a directly-supplied credential).
For "api-key", optional: replaces the deprecated header/value
fields below when set; do not set both at once.
header:
type: string
deprecated: true
description: >
Deprecated: use policyParams (e.g. {request: {headers:
[{name: ..., value: ...}]}} - the set-headers policy's own
param shape) instead. HTTP header to set on outbound
requests. Applies when type is api-key. Still honored when
policyParams is omitted, for backward compatibility.
value:
type: string
deprecated: true
writeOnly: true
description: >
Upstream credential. Write-only: accepted on create/update and
never returned by the management API on a read, for any role.
Supply either a literal value or a secret reference (e.g. a
`secret` template expression); either way the field is omitted
from management API response bodies. An update that omits it
inherits the stored value; set `type: none` to remove auth.
Deprecated: use policyParams instead. Upstream credential.
Applies when type is api-key. Still honored when policyParams
is omitted, for backward compatibility. Write-only: accepted
on create/update and never returned by the management API on
a read, for any role. Supply either a literal value or a
secret reference (e.g. a `secret` template expression);
either way the field is omitted from management API response
bodies. An update that omits it inherits the stored value;
set `type: none` to remove auth.

LLMUpstreamAuth:
type: object
Expand All @@ -4446,16 +4501,69 @@ components:
properties:
type:
type: string
enum: [ api-key, other, none ]
enum: [ api-key, oauth2, other, none ]
description: >
"api-key" attaches the built-in set-headers policy by default
(overridable via policyName) and accepts either the generic
policyParams bucket or its own deprecated header/value fields
below. "oauth2" attaches the built-in oauth2-generator policy
by default (overridable via policyName) and always requires
policyParams - there is no typed-field fallback for it. "other"
attaches any policy by name - policyName and policyParams are
both required in that case, since there is no built-in default
or typed-field fallback for a non-built-in auth scheme. "none":
no upstream authentication - the gateway attaches no auth policy
of its own; auth (if any) is handled entirely by user-attached
policies elsewhere.
policyName:
type: string
description: >
Name of the policy that implements this upstream auth. Optional
for "api-key"/"oauth2" (defaults to the built-in policy for that
type - api-key -> set-headers, oauth2 -> oauth2-generator); set
it to point at your own fork or a newer major version's
replacement instead. Required when type is "other".
policyVersion:
type: string
pattern: '^v\d+$'
description: >
Major version of policyName to attach (e.g. "v1"), same format
and resolution rules as Policy.version. Optional - defaults to
the highest version available in the gateway image when
omitted. If set, it must match a version actually loaded in
this gateway build, or config validation fails.
policyParams:
type: object
additionalProperties: true
description: >
Parameters passed verbatim to policyName (or the built-in
default for type). Required when type is "oauth2" or "other" -
oauth2 has no typed fields at all, only this bucket (e.g.
{tokenEndpoint: ..., clientId: ..., clientSecret: ...} for the
token-endpoint path, or {bearerToken: ...} for a
directly-supplied credential). For "api-key", optional:
replaces the deprecated header/value fields below when set; do
not set both at once.
header:
type: string
deprecated: true
description: >
Deprecated: use policyParams (e.g. {request: {headers: [{name:
..., value: ...}]}} - the set-headers policy's own param shape)
instead. HTTP header to set on outbound requests. Applies when
type is api-key. Still honored when policyParams is omitted,
for backward compatibility.
value:
type: string
deprecated: true
writeOnly: true
description: >
Upstream credential. Write-only: accepted on create/update and never
returned by the management API on a read, for any role. An update that
omits it inherits the stored value; set `type: none` to remove auth.
Deprecated: use policyParams instead. Upstream credential.
Applies when type is api-key. Still honored when policyParams is
omitted, for backward compatibility. Write-only: accepted on
create/update and never returned by the management API on a
read, for any role. An update that omits it inherits the stored
value; set `type: none` to remove auth.

LLMProxyProvider:
type: object
Expand Down
8 changes: 6 additions & 2 deletions gateway/gateway-controller/cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ func main() {
policyDefinitions[key] = def
}

// Built early so the startup rehydration below can use it too.
policyVersionResolver := utils.NewLoadedPolicyVersionResolver(policyDefinitions)

// MCP proxies and LLM artifacts are stored in source form and need to be
// rehydrated into their derived RestAPI representations before startup
// snapshot and policy work.
Expand All @@ -345,6 +348,7 @@ func main() {
db,
&cfg.Router,
policyDefinitions,
policyVersionResolver,
log,
cfg.Controller.Server.SkipInvalidDeploymentsOnStartup,
); err != nil {
Expand Down Expand Up @@ -427,7 +431,6 @@ func main() {
policyManager.SetRuntimeStore(runtimeStore)

// Build transformer registry for StoredConfig → RuntimeDeployConfig conversion
policyVersionResolver := utils.NewLoadedPolicyVersionResolver(policyDefinitions)
restTransformer := transform.NewRestAPITransformer(&cfg.Router, cfg, policyDefinitions)
llmTransformer := transform.NewLLMTransformer(configStore, db, &cfg.Router, cfg, policyDefinitions, policyVersionResolver)
transformerRegistry := transform.NewRegistry(restTransformer, llmTransformer)
Expand Down Expand Up @@ -520,7 +523,7 @@ func main() {
validator.SetPolicyValidator(policyValidator)

apiSvc := utils.NewAPIDeploymentService(configStore, db, snapshotManager, validator, &cfg.Router, eventHubInstance, gatewayID, secretsService)
mcpSvc := utils.NewMCPDeploymentService(configStore, db, snapshotManager, policyManager, policyValidator, eventHubInstance, gatewayID, secretsService)
mcpSvc := utils.NewMCPDeploymentService(configStore, db, snapshotManager, policyManager, policyValidator, eventHubInstance, gatewayID, secretsService, policyVersionResolver)
llmSvc := utils.NewLLMDeploymentService(configStore, db, snapshotManager, lazyResourceXDSManager, templateDefinitions,
apiSvc, &cfg.Router, policyVersionResolver, policyValidator)

Expand Down Expand Up @@ -604,6 +607,7 @@ func main() {
cfg,
policyDefinitions,
secretsService,
policyVersionResolver,
)
if err := evtListener.Start(); err != nil {
log.Error("Failed to start event listener", slog.Any("error", err))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func hydrateStoredConfigsFromDatabaseOnStartup(
db storage.Storage,
routerConfig *config.RouterConfig,
policyDefinitions map[string]models.PolicyDefinition,
policyVersionResolver utils.PolicyVersionResolver,
log *slog.Logger,
skipInvalidDeployments bool,
) error {
Expand All @@ -30,7 +31,9 @@ func hydrateStoredConfigsFromDatabaseOnStartup(
"stored MCP proxy configuration",
log,
skipInvalidDeployments,
utils.HydrateStoredMCPConfig,
func(cfg *models.StoredConfig) error {
return utils.HydrateStoredMCPConfig(cfg, policyVersionResolver)
},
); err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func TestHydrateStoredConfigsFromDatabaseOnStartup_FailsFastByDefault(t *testing
nil,
nil,
nil,
nil,
newDiscardLogger(),
false,
)
Expand All @@ -230,6 +231,7 @@ func TestHydrateStoredConfigsFromDatabaseOnStartup_SkipsInvalidConfigsWhenEnable
nil,
nil,
nil,
nil,
newDiscardLogger(),
true,
)
Expand Down
2 changes: 1 addition & 1 deletion gateway/gateway-controller/pkg/api/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func NewAPIServer(
parser := config.NewParser()
httpClient := &http.Client{Timeout: 10 * time.Second}
routerConfig := &systemConfig.Router
mcpDeploymentService := utils.NewMCPDeploymentService(store, db, snapshotManager, policyManager, policyValidator, eventHub, gatewayID, secretService)
mcpDeploymentService := utils.NewMCPDeploymentService(store, db, snapshotManager, policyManager, policyValidator, eventHub, gatewayID, secretService, policyVersionResolver)

server := &APIServer{
store: store,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ func createTestAPIServerWithDB(db storage.Storage) *APIServer {

deploymentService := utils.NewAPIDeploymentService(store, db, nil, validator, routerCfg, hub, gatewayID, nil)
server.deploymentService = deploymentService
server.mcpDeploymentService = utils.NewMCPDeploymentService(store, db, nil, nil, nil, hub, gatewayID, nil)
server.mcpDeploymentService = utils.NewMCPDeploymentService(store, db, nil, nil, nil, hub, gatewayID, nil, nil)
server.llmDeploymentService = utils.NewLLMDeploymentService(
store,
db,
Expand Down Expand Up @@ -1367,7 +1367,7 @@ func createTestMCPStoredConfig(t *testing.T, id, handle, displayName, version, c
UpdatedAt: time.Now(),
}

require.NoError(t, utils.HydrateStoredMCPConfig(cfg))
require.NoError(t, utils.HydrateStoredMCPConfig(cfg, nil))
return cfg
}

Expand All @@ -1382,7 +1382,7 @@ func attachTestEventHub(server *APIServer, hub eventhub.EventHub, gatewayID stri
server.deploymentService = utils.NewAPIDeploymentService(server.store, server.db, server.snapshotManager, server.validator, server.routerConfig, hub, gatewayID, nil)
server.apiKeyService = utils.NewAPIKeyService(server.store, server.db, server.apiKeyXDSManager, &server.systemConfig.APIKey, hub, gatewayID)
server.subscriptionResourceService = utils.NewSubscriptionResourceService(server.db, server.subscriptionSnapshotUpdater, hub, gatewayID)
server.mcpDeploymentService = utils.NewMCPDeploymentService(server.store, server.db, server.snapshotManager, server.policyManager, policyValidator, hub, gatewayID, nil)
server.mcpDeploymentService = utils.NewMCPDeploymentService(server.store, server.db, server.snapshotManager, server.policyManager, policyValidator, hub, gatewayID, nil, policyVersionResolver)
server.llmDeploymentService = utils.NewLLMDeploymentService(
server.store,
server.db,
Expand Down
Loading
Loading