mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
refactor(access): migrate to SDKConfig for authentication and provider management
- Replaced `config.Config` with `SDKConfig` in authentication and provider logic for consistency with SDK changes. - Updated provider registration, reconciliation, and build functions to align with the `SDKConfig` structure. - Refactored related imports and handlers to support the new configuration approach. - Improved clarity and reduced redundancy in API key synchronization and provider initialization.
This commit is contained in:
@@ -6,18 +6,20 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
|
||||
sdkConfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
// ReconcileProviders builds the desired provider list by reusing existing providers when possible
|
||||
// and creating or removing providers only when their configuration changed. It returns the final
|
||||
// ordered provider slice along with the identifiers of providers that were added, updated, or
|
||||
// removed compared to the previous configuration.
|
||||
func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (result []Provider, added, updated, removed []string, err error) {
|
||||
func ReconcileProviders(oldCfg, newCfg *config.Config, existing []access.Provider) (result []access.Provider, added, updated, removed []string, err error) {
|
||||
if newCfg == nil {
|
||||
return nil, nil, nil, nil, nil
|
||||
}
|
||||
|
||||
existingMap := make(map[string]Provider, len(existing))
|
||||
existingMap := make(map[string]access.Provider, len(existing))
|
||||
for _, provider := range existing {
|
||||
if provider == nil {
|
||||
continue
|
||||
@@ -28,11 +30,11 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
oldCfgMap := accessProviderMap(oldCfg)
|
||||
newEntries := collectProviderEntries(newCfg)
|
||||
|
||||
result = make([]Provider, 0, len(newEntries))
|
||||
result = make([]access.Provider, 0, len(newEntries))
|
||||
finalIDs := make(map[string]struct{}, len(newEntries))
|
||||
|
||||
isInlineProvider := func(id string) bool {
|
||||
return strings.EqualFold(id, config.DefaultAccessProviderName)
|
||||
return strings.EqualFold(id, sdkConfig.DefaultAccessProviderName)
|
||||
}
|
||||
appendChange := func(list *[]string, id string) {
|
||||
if isInlineProvider(id) {
|
||||
@@ -58,7 +60,7 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
}
|
||||
}
|
||||
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
provider, buildErr := access.BuildProvider(providerCfg, &newCfg.SDKConfig)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
@@ -76,7 +78,7 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
}
|
||||
|
||||
if len(result) == 0 && len(newCfg.APIKeys) > 0 {
|
||||
config.SyncInlineAPIKeys(newCfg, newCfg.APIKeys)
|
||||
sdkConfig.SyncInlineAPIKeys(&newCfg.SDKConfig, newCfg.APIKeys)
|
||||
if providerCfg := newCfg.ConfigAPIKeyProvider(); providerCfg != nil {
|
||||
key := providerIdentifier(providerCfg)
|
||||
if key != "" {
|
||||
@@ -86,7 +88,7 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
if existingProvider, okExisting := existingMap[key]; okExisting {
|
||||
result = append(result, existingProvider)
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
provider, buildErr := access.BuildProvider(providerCfg, &newCfg.SDKConfig)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
@@ -98,7 +100,7 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
result = append(result, provider)
|
||||
}
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
provider, buildErr := access.BuildProvider(providerCfg, &newCfg.SDKConfig)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
@@ -110,7 +112,7 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
result = append(result, provider)
|
||||
}
|
||||
} else {
|
||||
provider, buildErr := buildProvider(providerCfg, newCfg)
|
||||
provider, buildErr := access.BuildProvider(providerCfg, &newCfg.SDKConfig)
|
||||
if buildErr != nil {
|
||||
return nil, nil, nil, nil, buildErr
|
||||
}
|
||||
@@ -144,8 +146,8 @@ func ReconcileProviders(oldCfg, newCfg *config.Config, existing []Provider) (res
|
||||
return result, added, updated, removed, nil
|
||||
}
|
||||
|
||||
func accessProviderMap(cfg *config.Config) map[string]*config.AccessProvider {
|
||||
result := make(map[string]*config.AccessProvider)
|
||||
func accessProviderMap(cfg *config.Config) map[string]*sdkConfig.AccessProvider {
|
||||
result := make(map[string]*sdkConfig.AccessProvider)
|
||||
if cfg == nil {
|
||||
return result
|
||||
}
|
||||
@@ -170,8 +172,8 @@ func accessProviderMap(cfg *config.Config) map[string]*config.AccessProvider {
|
||||
return result
|
||||
}
|
||||
|
||||
func collectProviderEntries(cfg *config.Config) []*config.AccessProvider {
|
||||
entries := make([]*config.AccessProvider, 0, len(cfg.Access.Providers))
|
||||
func collectProviderEntries(cfg *config.Config) []*sdkConfig.AccessProvider {
|
||||
entries := make([]*sdkConfig.AccessProvider, 0, len(cfg.Access.Providers))
|
||||
if cfg == nil {
|
||||
return entries
|
||||
}
|
||||
@@ -187,7 +189,7 @@ func collectProviderEntries(cfg *config.Config) []*config.AccessProvider {
|
||||
return entries
|
||||
}
|
||||
|
||||
func providerIdentifier(provider *config.AccessProvider) string {
|
||||
func providerIdentifier(provider *sdkConfig.AccessProvider) string {
|
||||
if provider == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -198,13 +200,13 @@ func providerIdentifier(provider *config.AccessProvider) string {
|
||||
if typ == "" {
|
||||
return ""
|
||||
}
|
||||
if strings.EqualFold(typ, config.AccessProviderTypeConfigAPIKey) {
|
||||
return config.DefaultAccessProviderName
|
||||
if strings.EqualFold(typ, sdkConfig.AccessProviderTypeConfigAPIKey) {
|
||||
return sdkConfig.DefaultAccessProviderName
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
func providerConfigEqual(a, b *config.AccessProvider) bool {
|
||||
func providerConfigEqual(a, b *sdkConfig.AccessProvider) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == nil && b == nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
sdkConfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
// Generic helpers for list[string]
|
||||
@@ -106,13 +107,13 @@ func (h *Handler) deleteFromStringList(c *gin.Context, target *[]string, after f
|
||||
// api-keys
|
||||
func (h *Handler) GetAPIKeys(c *gin.Context) { c.JSON(200, gin.H{"api-keys": h.cfg.APIKeys}) }
|
||||
func (h *Handler) PutAPIKeys(c *gin.Context) {
|
||||
h.putStringList(c, func(v []string) { config.SyncInlineAPIKeys(h.cfg, v) }, nil)
|
||||
h.putStringList(c, func(v []string) { sdkConfig.SyncInlineAPIKeys(&h.cfg.SDKConfig, v) }, nil)
|
||||
}
|
||||
func (h *Handler) PatchAPIKeys(c *gin.Context) {
|
||||
h.patchStringList(c, &h.cfg.APIKeys, func() { config.SyncInlineAPIKeys(h.cfg, h.cfg.APIKeys) })
|
||||
h.patchStringList(c, &h.cfg.APIKeys, func() { sdkConfig.SyncInlineAPIKeys(&h.cfg.SDKConfig, h.cfg.APIKeys) })
|
||||
}
|
||||
func (h *Handler) DeleteAPIKeys(c *gin.Context) {
|
||||
h.deleteFromStringList(c, &h.cfg.APIKeys, func() { config.SyncInlineAPIKeys(h.cfg, h.cfg.APIKeys) })
|
||||
h.deleteFromStringList(c, &h.cfg.APIKeys, func() { sdkConfig.SyncInlineAPIKeys(&h.cfg.SDKConfig, h.cfg.APIKeys) })
|
||||
}
|
||||
|
||||
// generative-language-api-key
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/access"
|
||||
managementHandlers "github.com/router-for-me/CLIProxyAPI/v6/internal/api/handlers/management"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/middleware"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
@@ -25,8 +26,8 @@ import (
|
||||
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers/claude"
|
||||
gemini2 "github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers/gemini"
|
||||
openai2 "github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers/openai"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers/gemini"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers/openai"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -224,11 +225,11 @@ func NewServer(cfg *config.Config, authManager *auth.Manager, accessManager *sdk
|
||||
// setupRoutes configures the API routes for the server.
|
||||
// It defines the endpoints and associates them with their respective handlers.
|
||||
func (s *Server) setupRoutes() {
|
||||
openaiHandlers := openai2.NewOpenAIAPIHandler(s.handlers)
|
||||
geminiHandlers := gemini2.NewGeminiAPIHandler(s.handlers)
|
||||
geminiCLIHandlers := gemini2.NewGeminiCLIAPIHandler(s.handlers)
|
||||
openaiHandlers := openai.NewOpenAIAPIHandler(s.handlers)
|
||||
geminiHandlers := gemini.NewGeminiAPIHandler(s.handlers)
|
||||
geminiCLIHandlers := gemini.NewGeminiCLIAPIHandler(s.handlers)
|
||||
claudeCodeHandlers := claude.NewClaudeCodeAPIHandler(s.handlers)
|
||||
openaiResponsesHandlers := openai2.NewOpenAIResponsesAPIHandler(s.handlers)
|
||||
openaiResponsesHandlers := openai.NewOpenAIResponsesAPIHandler(s.handlers)
|
||||
|
||||
// OpenAI compatible API routes
|
||||
v1 := s.engine.Group("/v1")
|
||||
@@ -469,7 +470,7 @@ func (s *Server) watchKeepAlive() {
|
||||
// that routes to different handlers based on the User-Agent header.
|
||||
// If User-Agent starts with "claude-cli", it routes to Claude handler,
|
||||
// otherwise it routes to OpenAI handler.
|
||||
func (s *Server) unifiedModelsHandler(openaiHandler *openai2.OpenAIAPIHandler, claudeHandler *claude.ClaudeCodeAPIHandler) gin.HandlerFunc {
|
||||
func (s *Server) unifiedModelsHandler(openaiHandler *openai.OpenAIAPIHandler, claudeHandler *claude.ClaudeCodeAPIHandler) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
userAgent := c.GetHeader("User-Agent")
|
||||
|
||||
@@ -552,7 +553,7 @@ func (s *Server) applyAccessConfig(oldCfg, newCfg *config.Config) {
|
||||
return
|
||||
}
|
||||
existing := s.accessManager.Providers()
|
||||
providers, added, updated, removed, err := sdkaccess.ReconcileProviders(oldCfg, newCfg, existing)
|
||||
providers, added, updated, removed, err := access.ReconcileProviders(oldCfg, newCfg, existing)
|
||||
if err != nil {
|
||||
log.Errorf("failed to reconcile request auth providers: %v", err)
|
||||
return
|
||||
|
||||
@@ -31,12 +31,6 @@ type Config struct {
|
||||
// UsageStatisticsEnabled toggles in-memory usage aggregation; when false, usage data is discarded.
|
||||
UsageStatisticsEnabled bool `yaml:"usage-statistics-enabled" json:"usage-statistics-enabled"`
|
||||
|
||||
// APIKeys is a list of keys for authenticating clients to this proxy server.
|
||||
APIKeys []string `yaml:"api-keys" json:"api-keys"`
|
||||
|
||||
// Access holds request authentication provider configuration.
|
||||
Access AccessConfig `yaml:"auth" json:"auth"`
|
||||
|
||||
// QuotaExceeded defines the behavior when a quota is exceeded.
|
||||
QuotaExceeded QuotaExceeded `yaml:"quota-exceeded" json:"quota-exceeded"`
|
||||
|
||||
@@ -62,38 +56,6 @@ type Config struct {
|
||||
GeminiWeb GeminiWebConfig `yaml:"gemini-web" json:"gemini-web"`
|
||||
}
|
||||
|
||||
// AccessConfig groups request authentication providers.
|
||||
type AccessConfig struct {
|
||||
// Providers lists configured authentication providers.
|
||||
Providers []AccessProvider `yaml:"providers" json:"providers"`
|
||||
}
|
||||
|
||||
// AccessProvider describes a request authentication provider entry.
|
||||
type AccessProvider struct {
|
||||
// Name is the instance identifier for the provider.
|
||||
Name string `yaml:"name" json:"name"`
|
||||
|
||||
// Type selects the provider implementation registered via the SDK.
|
||||
Type string `yaml:"type" json:"type"`
|
||||
|
||||
// SDK optionally names a third-party SDK module providing this provider.
|
||||
SDK string `yaml:"sdk,omitempty" json:"sdk,omitempty"`
|
||||
|
||||
// APIKeys lists inline keys for providers that require them.
|
||||
APIKeys []string `yaml:"api-keys,omitempty" json:"api-keys,omitempty"`
|
||||
|
||||
// Config passes provider-specific options to the implementation.
|
||||
Config map[string]any `yaml:"config,omitempty" json:"config,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
// AccessProviderTypeConfigAPIKey is the built-in provider validating inline API keys.
|
||||
AccessProviderTypeConfigAPIKey = "config-api-key"
|
||||
|
||||
// DefaultAccessProviderName is applied when no provider name is supplied.
|
||||
DefaultAccessProviderName = "config-inline"
|
||||
)
|
||||
|
||||
// GeminiWebConfig nests Gemini Web related options under 'gemini-web'.
|
||||
type GeminiWebConfig struct {
|
||||
// Context enables JSON-based conversation reuse.
|
||||
@@ -232,43 +194,6 @@ func LoadConfig(configFile string) (*Config, error) {
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
// SyncInlineAPIKeys updates the inline API key provider and top-level APIKeys field.
|
||||
func SyncInlineAPIKeys(cfg *Config, keys []string) {
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
cloned := append([]string(nil), keys...)
|
||||
cfg.APIKeys = cloned
|
||||
if provider := cfg.ConfigAPIKeyProvider(); provider != nil {
|
||||
if provider.Name == "" {
|
||||
provider.Name = DefaultAccessProviderName
|
||||
}
|
||||
provider.APIKeys = cloned
|
||||
return
|
||||
}
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, AccessProvider{
|
||||
Name: DefaultAccessProviderName,
|
||||
Type: AccessProviderTypeConfigAPIKey,
|
||||
APIKeys: cloned,
|
||||
})
|
||||
}
|
||||
|
||||
// ConfigAPIKeyProvider returns the first inline API key provider if present.
|
||||
func (c *Config) ConfigAPIKeyProvider() *AccessProvider {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
for i := range c.Access.Providers {
|
||||
if c.Access.Providers[i].Type == AccessProviderTypeConfigAPIKey {
|
||||
if c.Access.Providers[i].Name == "" {
|
||||
c.Access.Providers[i].Name = DefaultAccessProviderName
|
||||
}
|
||||
return &c.Access.Providers[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func syncInlineAccessProvider(cfg *Config) {
|
||||
if cfg == nil {
|
||||
return
|
||||
@@ -277,9 +202,9 @@ func syncInlineAccessProvider(cfg *Config) {
|
||||
if len(cfg.APIKeys) == 0 {
|
||||
return
|
||||
}
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, AccessProvider{
|
||||
Name: DefaultAccessProviderName,
|
||||
Type: AccessProviderTypeConfigAPIKey,
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, config.AccessProvider{
|
||||
Name: config.DefaultAccessProviderName,
|
||||
Type: config.AccessProviderTypeConfigAPIKey,
|
||||
APIKeys: append([]string(nil), cfg.APIKeys...),
|
||||
})
|
||||
return
|
||||
@@ -289,9 +214,9 @@ func syncInlineAccessProvider(cfg *Config) {
|
||||
if len(cfg.APIKeys) == 0 {
|
||||
return
|
||||
}
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, AccessProvider{
|
||||
Name: DefaultAccessProviderName,
|
||||
Type: AccessProviderTypeConfigAPIKey,
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, config.AccessProvider{
|
||||
Name: config.DefaultAccessProviderName,
|
||||
Type: config.AccessProviderTypeConfigAPIKey,
|
||||
APIKeys: append([]string(nil), cfg.APIKeys...),
|
||||
})
|
||||
return
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
type provider struct {
|
||||
@@ -18,7 +18,7 @@ func init() {
|
||||
sdkaccess.RegisterProvider(config.AccessProviderTypeConfigAPIKey, newProvider)
|
||||
}
|
||||
|
||||
func newProvider(cfg *config.AccessProvider, _ *config.Config) (sdkaccess.Provider, error) {
|
||||
func newProvider(cfg *config.AccessProvider, _ *config.SDKConfig) (sdkaccess.Provider, error) {
|
||||
name := cfg.Name
|
||||
if name == "" {
|
||||
name = config.DefaultAccessProviderName
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||
)
|
||||
|
||||
// Provider validates credentials for incoming requests.
|
||||
@@ -23,7 +23,7 @@ type Result struct {
|
||||
}
|
||||
|
||||
// ProviderFactory builds a provider from configuration data.
|
||||
type ProviderFactory func(cfg *config.AccessProvider, root *config.Config) (Provider, error)
|
||||
type ProviderFactory func(cfg *config.AccessProvider, root *config.SDKConfig) (Provider, error)
|
||||
|
||||
var (
|
||||
registryMu sync.RWMutex
|
||||
@@ -40,7 +40,7 @@ func RegisterProvider(typ string, factory ProviderFactory) {
|
||||
registryMu.Unlock()
|
||||
}
|
||||
|
||||
func buildProvider(cfg *config.AccessProvider, root *config.Config) (Provider, error) {
|
||||
func BuildProvider(cfg *config.AccessProvider, root *config.SDKConfig) (Provider, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("access: nil provider config")
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func buildProvider(cfg *config.AccessProvider, root *config.Config) (Provider, e
|
||||
}
|
||||
|
||||
// BuildProviders constructs providers declared in configuration.
|
||||
func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
func BuildProviders(root *config.SDKConfig) ([]Provider, error) {
|
||||
if root == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
if providerCfg.Type == "" {
|
||||
continue
|
||||
}
|
||||
provider, err := buildProvider(providerCfg, root)
|
||||
provider, err := BuildProvider(providerCfg, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,7 +77,7 @@ func BuildProviders(root *config.Config) ([]Provider, error) {
|
||||
if len(providers) == 0 && len(root.APIKeys) > 0 {
|
||||
config.SyncInlineAPIKeys(root, root.APIKeys)
|
||||
if providerCfg := root.ConfigAPIKeyProvider(); providerCfg != nil {
|
||||
provider, err := buildProvider(providerCfg, root)
|
||||
provider, err := BuildProvider(providerCfg, root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func (b *Builder) Build() (*Service, error) {
|
||||
if accessManager == nil {
|
||||
accessManager = sdkaccess.NewManager()
|
||||
}
|
||||
providers, err := sdkaccess.BuildProviders(b.cfg)
|
||||
providers, err := sdkaccess.BuildProviders(&b.cfg.SDKConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/access"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/api"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
geminiwebclient "github.com/router-for-me/CLIProxyAPI/v6/internal/provider/gemini-web"
|
||||
@@ -115,7 +116,7 @@ func (s *Service) refreshAccessProviders(cfg *config.Config) {
|
||||
s.cfgMu.RUnlock()
|
||||
|
||||
existing := s.accessManager.Providers()
|
||||
providers, added, updated, removed, err := sdkaccess.ReconcileProviders(oldCfg, cfg, existing)
|
||||
providers, added, updated, removed, err := access.ReconcileProviders(oldCfg, cfg, existing)
|
||||
if err != nil {
|
||||
log.Errorf("failed to reconcile request auth providers: %v", err)
|
||||
return
|
||||
|
||||
@@ -11,4 +11,79 @@ type SDKConfig struct {
|
||||
|
||||
// RequestLog enables or disables detailed request logging functionality.
|
||||
RequestLog bool `yaml:"request-log" json:"request-log"`
|
||||
|
||||
// APIKeys is a list of keys for authenticating clients to this proxy server.
|
||||
APIKeys []string `yaml:"api-keys" json:"api-keys"`
|
||||
|
||||
// Access holds request authentication provider configuration.
|
||||
Access AccessConfig `yaml:"auth" json:"auth"`
|
||||
}
|
||||
|
||||
// AccessConfig groups request authentication providers.
|
||||
type AccessConfig struct {
|
||||
// Providers lists configured authentication providers.
|
||||
Providers []AccessProvider `yaml:"providers" json:"providers"`
|
||||
}
|
||||
|
||||
// AccessProvider describes a request authentication provider entry.
|
||||
type AccessProvider struct {
|
||||
// Name is the instance identifier for the provider.
|
||||
Name string `yaml:"name" json:"name"`
|
||||
|
||||
// Type selects the provider implementation registered via the SDK.
|
||||
Type string `yaml:"type" json:"type"`
|
||||
|
||||
// SDK optionally names a third-party SDK module providing this provider.
|
||||
SDK string `yaml:"sdk,omitempty" json:"sdk,omitempty"`
|
||||
|
||||
// APIKeys lists inline keys for providers that require them.
|
||||
APIKeys []string `yaml:"api-keys,omitempty" json:"api-keys,omitempty"`
|
||||
|
||||
// Config passes provider-specific options to the implementation.
|
||||
Config map[string]any `yaml:"config,omitempty" json:"config,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
// AccessProviderTypeConfigAPIKey is the built-in provider validating inline API keys.
|
||||
AccessProviderTypeConfigAPIKey = "config-api-key"
|
||||
|
||||
// DefaultAccessProviderName is applied when no provider name is supplied.
|
||||
DefaultAccessProviderName = "config-inline"
|
||||
)
|
||||
|
||||
// SyncInlineAPIKeys updates the inline API key provider and top-level APIKeys field.
|
||||
func SyncInlineAPIKeys(cfg *SDKConfig, keys []string) {
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
cloned := append([]string(nil), keys...)
|
||||
cfg.APIKeys = cloned
|
||||
if provider := cfg.ConfigAPIKeyProvider(); provider != nil {
|
||||
if provider.Name == "" {
|
||||
provider.Name = DefaultAccessProviderName
|
||||
}
|
||||
provider.APIKeys = cloned
|
||||
return
|
||||
}
|
||||
cfg.Access.Providers = append(cfg.Access.Providers, AccessProvider{
|
||||
Name: DefaultAccessProviderName,
|
||||
Type: AccessProviderTypeConfigAPIKey,
|
||||
APIKeys: cloned,
|
||||
})
|
||||
}
|
||||
|
||||
// ConfigAPIKeyProvider returns the first inline API key provider if present.
|
||||
func (c *SDKConfig) ConfigAPIKeyProvider() *AccessProvider {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
for i := range c.Access.Providers {
|
||||
if c.Access.Providers[i].Type == AccessProviderTypeConfigAPIKey {
|
||||
if c.Access.Providers[i].Name == "" {
|
||||
c.Access.Providers[i].Name = DefaultAccessProviderName
|
||||
}
|
||||
return &c.Access.Providers[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user