package config import ( "encoding/json" "errors" "github.com/higress-group/wasm-go/pkg/log" "github.com/tidwall/gjson" ) // validAlgorithms allowed_algorithms 配置中允许的算法 var validAlgorithms = map[string]bool{ "hmac-sha1": true, "hmac-sha256": true, "hmac-sha512": true, } type HmacAuthConfig struct { Consumers []Consumer `json:"consumers" yaml:"consumers"` GlobalAuth *bool `json:"global_auth,omitempty" yaml:"global_auth,omitempty"` AllowedAlgorithms []string `json:"allowed_algorithms,omitempty" yaml:"allowed_algorithms,omitempty"` ClockSkew int `json:"clock_skew,omitempty" yaml:"clock_skew,omitempty"` SignedHeaders []string `json:"signed_headers,omitempty" yaml:"signed_headers,omitempty"` ValidateRequestBody bool `json:"validate_request_body,omitempty" yaml:"validate_request_body,omitempty"` HideCredentials bool `json:"hide_credentials,omitempty" yaml:"hide_credentials,omitempty"` AnonymousConsumer string `json:"anonymous_consumer,omitempty" yaml:"anonymous_consumer,omitempty"` Allow []string `json:"allow,omitempty" yaml:"allow,omitempty"` // RuleSet 插件是否至少在一个 domain 或 route 上生效 RuleSet bool `json:"-" yaml:"-"` } type Consumer struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` AccessKey string `json:"access_key" yaml:"access_key"` SecretKey string `json:"secret_key" yaml:"secret_key"` } func ParseGlobalConfig(jsonData gjson.Result, global *HmacAuthConfig) error { log.Debug("global config") global.RuleSet = false // 处理 consumers 配置 consumers := jsonData.Get("consumers") if !consumers.Exists() { return errors.New("consumers is required") } if len(consumers.Array()) == 0 { return errors.New("consumers cannot be empty") } accessKeyMap := make(map[string]string) for _, item := range consumers.Array() { ak := item.Get("access_key") if !ak.Exists() || ak.String() == "" { return errors.New("consumer access_key is required") } sk := item.Get("secret_key") if !sk.Exists() || sk.String() == "" { return errors.New("consumer secret_key is required") } if _, ok := accessKeyMap[ak.String()]; ok { return errors.New("duplicate consumer access_key: " + ak.String()) } consumer := Consumer{ AccessKey: ak.String(), SecretKey: sk.String(), } name := item.Get("name") if name.Exists() && name.String() != "" { consumer.Name = name.String() } else { // 如果没有提供 name,则使用 access_key 作为 name consumer.Name = ak.String() } global.Consumers = append(global.Consumers, consumer) accessKeyMap[ak.String()] = ak.String() } // 处理 global_auth 配置 globalAuth := jsonData.Get("global_auth") if globalAuth.Exists() { ga := globalAuth.Bool() global.GlobalAuth = &ga } // 处理 allowed_algorithms 配置 allowedAlgorithms := jsonData.Get("allowed_algorithms") if allowedAlgorithms.Exists() && len(allowedAlgorithms.Array()) > 0 { global.AllowedAlgorithms = []string{} for _, item := range allowedAlgorithms.Array() { algorithm := item.String() if !validAlgorithms[algorithm] { return errors.New("invalid allowed_algorithm: " + algorithm + ". Must be one of: hmac-sha1, hmac-sha256, hmac-sha512") } global.AllowedAlgorithms = append(global.AllowedAlgorithms, algorithm) } } else { // 如果未设置,则使用默认值 global.AllowedAlgorithms = []string{"hmac-sha1", "hmac-sha256", "hmac-sha512"} } // 处理 clock_skew 配置 clockSkew := jsonData.Get("clock_skew") if !clockSkew.Exists() { // 如果未设置,则使用默认值300 global.ClockSkew = 300 } else if clockSkew.Int() >= 1 { global.ClockSkew = int(clockSkew.Int()) } // 处理 signed_headers 配置 signedHeaders := jsonData.Get("signed_headers") if signedHeaders.Exists() { global.SignedHeaders = []string{} for _, item := range signedHeaders.Array() { global.SignedHeaders = append(global.SignedHeaders, item.String()) } } // 处理 validate_request_body 配置 validateRequestBody := jsonData.Get("validate_request_body") if validateRequestBody.Exists() { global.ValidateRequestBody = validateRequestBody.Bool() } // 处理 hide_credentials 配置 hideCredentials := jsonData.Get("hide_credentials") if hideCredentials.Exists() { global.HideCredentials = hideCredentials.Bool() } // 处理 anonymous_consumer 配置 anonymousConsumer := jsonData.Get("anonymous_consumer") if anonymousConsumer.Exists() { global.AnonymousConsumer = anonymousConsumer.String() } if globalBytes, err := json.Marshal(global); err == nil { log.Debugf("global: %s", string(globalBytes)) } return nil } func ParseOverrideRuleConfig(jsonData gjson.Result, global HmacAuthConfig, config *HmacAuthConfig) error { log.Debug("domain/route config") *config = global // 处理 allow 配置 allow := jsonData.Get("allow") if allow.Exists() { config.Allow = []string{} consumerNames := make(map[string]bool) for _, consumer := range config.Consumers { consumerNames[consumer.Name] = true } for _, item := range allow.Array() { allowedName := item.String() config.Allow = append(config.Allow, allowedName) // 检查允许的名称是否在消费者列表中 if !consumerNames[allowedName] { log.Warnf("allowed consumer name '%s' is not in the consumers list", allowedName) } } } config.RuleSet = true if configBytes, err := json.Marshal(config); err == nil { log.Debugf("config: %s", string(configBytes)) } return nil }