github.com/dbernstein1/tyk@v2.9.0-beta9-dl-apic+incompatible/config/config.go (about) 1 package config 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "runtime" 11 "sync" 12 "sync/atomic" 13 14 "github.com/kelseyhightower/envconfig" 15 16 "github.com/TykTechnologies/tyk/apidef" 17 logger "github.com/TykTechnologies/tyk/log" 18 "github.com/TykTechnologies/tyk/regexp" 19 ) 20 21 type IPsHandleStrategy string 22 23 var ( 24 log = logger.Get() 25 global atomic.Value 26 globalMu sync.Mutex 27 28 Default = Config{ 29 ListenPort: 8080, 30 Secret: "352d20ee67be67f6340b4c0605b044b7", 31 TemplatePath: "templates", 32 MiddlewarePath: "middleware", 33 AppPath: "apps/", 34 Storage: StorageOptionsConf{ 35 Type: "redis", 36 Host: "localhost", 37 MaxIdle: 100, 38 Port: 6379, 39 }, 40 AnalyticsConfig: AnalyticsConfigConfig{ 41 IgnoredIPs: make([]string, 0), 42 }, 43 DnsCache: DnsCacheConfig{ 44 Enabled: false, 45 TTL: dnsCacheDefaultTtl, 46 CheckInterval: dnsCacheDefaultCheckInterval, 47 MultipleIPsHandleStrategy: NoCacheStrategy, 48 }, 49 } 50 ) 51 52 const ( 53 envPrefix = "TYK_GW" 54 55 dnsCacheDefaultTtl = 3600 56 dnsCacheDefaultCheckInterval = 60 57 58 PickFirstStrategy IPsHandleStrategy = "pick_first" 59 RandomStrategy IPsHandleStrategy = "random" 60 NoCacheStrategy IPsHandleStrategy = "no_cache" 61 62 DefaultDashPolicySource = "service" 63 DefaultDashPolicyRecordName = "tyk_policies" 64 ) 65 66 type PoliciesConfig struct { 67 PolicySource string `json:"policy_source"` 68 PolicyConnectionString string `json:"policy_connection_string"` 69 PolicyRecordName string `json:"policy_record_name"` 70 AllowExplicitPolicyID bool `json:"allow_explicit_policy_id"` 71 } 72 73 type DBAppConfOptionsConfig struct { 74 ConnectionString string `json:"connection_string"` 75 NodeIsSegmented bool `json:"node_is_segmented"` 76 Tags []string `json:"tags"` 77 } 78 79 type RedisDBAppConfOptionsConfig struct { 80 Host string `json:"host"` 81 Port int `json:"port"` 82 DB int `json:"db"` 83 Password string `json:"password"` 84 PoolSize int `json:"pool_size"` 85 } 86 87 type StorageOptionsConf struct { 88 Type string `json:"type"` 89 Host string `json:"host"` 90 Port int `json:"port"` 91 Hosts map[string]string `json:"hosts"` 92 Username string `json:"username"` 93 Password string `json:"password"` 94 Database int `json:"database"` 95 MaxIdle int `json:"optimisation_max_idle"` 96 MaxActive int `json:"optimisation_max_active"` 97 Timeout int `json:"timeout"` 98 EnableCluster bool `json:"enable_cluster"` 99 UseSSL bool `json:"use_ssl"` 100 SSLInsecureSkipVerify bool `json:"ssl_insecure_skip_verify"` 101 } 102 103 type NormalisedURLConfig struct { 104 Enabled bool `json:"enabled"` 105 NormaliseUUIDs bool `json:"normalise_uuids"` 106 NormaliseNumbers bool `json:"normalise_numbers"` 107 Custom []string `json:"custom_patterns"` 108 CompiledPatternSet NormaliseURLPatterns `json:"-"` // see analytics.go 109 } 110 111 type NormaliseURLPatterns struct { 112 UUIDs *regexp.Regexp 113 IDs *regexp.Regexp 114 Custom []*regexp.Regexp 115 } 116 117 type AnalyticsConfigConfig struct { 118 Type string `json:"type"` 119 IgnoredIPs []string `json:"ignored_ips"` 120 EnableDetailedRecording bool `json:"enable_detailed_recording"` 121 EnableGeoIP bool `json:"enable_geo_ip"` 122 GeoIPDBLocation string `json:"geo_ip_db_path"` 123 NormaliseUrls NormalisedURLConfig `json:"normalise_urls"` 124 PoolSize int `json:"pool_size"` 125 RecordsBufferSize uint64 `json:"records_buffer_size"` 126 StorageExpirationTime int `json:"storage_expiration_time"` 127 ignoredIPsCompiled map[string]bool 128 } 129 130 type HealthCheckConfig struct { 131 EnableHealthChecks bool `json:"enable_health_checks"` 132 HealthCheckValueTimeout int64 `json:"health_check_value_timeouts"` 133 } 134 135 type DnsCacheConfig struct { 136 Enabled bool `json:"enabled"` 137 TTL int64 `json:"ttl"` 138 CheckInterval int64 `json:"-" ignored:"true"` //controls cache cleanup interval. By convention shouldn't be exposed to config or env_variable_setup 139 MultipleIPsHandleStrategy IPsHandleStrategy `json:"multiple_ips_handle_strategy"` 140 } 141 142 type MonitorConfig struct { 143 EnableTriggerMonitors bool `json:"enable_trigger_monitors"` 144 Config WebHookHandlerConf `json:"configuration"` 145 GlobalTriggerLimit float64 `json:"global_trigger_limit"` 146 MonitorUserKeys bool `json:"monitor_user_keys"` 147 MonitorOrgKeys bool `json:"monitor_org_keys"` 148 } 149 150 type WebHookHandlerConf struct { 151 Method string `bson:"method" json:"method"` 152 TargetPath string `bson:"target_path" json:"target_path"` 153 TemplatePath string `bson:"template_path" json:"template_path"` 154 HeaderList map[string]string `bson:"header_map" json:"header_map"` 155 EventTimeout int64 `bson:"event_timeout" json:"event_timeout"` 156 } 157 158 type SlaveOptionsConfig struct { 159 UseRPC bool `json:"use_rpc"` 160 UseSSL bool `json:"use_ssl"` 161 SSLInsecureSkipVerify bool `json:"ssl_insecure_skip_verify"` 162 ConnectionString string `json:"connection_string"` 163 RPCKey string `json:"rpc_key"` 164 APIKey string `json:"api_key"` 165 EnableRPCCache bool `json:"enable_rpc_cache"` 166 BindToSlugsInsteadOfListenPaths bool `json:"bind_to_slugs"` 167 DisableKeySpaceSync bool `json:"disable_keyspace_sync"` 168 GroupID string `json:"group_id"` 169 CallTimeout int `json:"call_timeout"` 170 PingTimeout int `json:"ping_timeout"` 171 RPCPoolSize int `json:"rpc_pool_size"` 172 } 173 174 type LocalSessionCacheConf struct { 175 DisableCacheSessionState bool `json:"disable_cached_session_state"` 176 CachedSessionTimeout int `json:"cached_session_timeout"` 177 CacheSessionEviction int `json:"cached_session_eviction"` 178 } 179 180 type HttpServerOptionsConfig struct { 181 OverrideDefaults bool `json:"override_defaults"` 182 ReadTimeout int `json:"read_timeout"` 183 WriteTimeout int `json:"write_timeout"` 184 UseSSL bool `json:"use_ssl"` 185 UseLE_SSL bool `json:"use_ssl_le"` 186 EnableHttp2 bool `json:"enable_http2"` 187 SSLInsecureSkipVerify bool `json:"ssl_insecure_skip_verify"` 188 EnableWebSockets bool `json:"enable_websockets"` 189 Certificates []CertData `json:"certificates"` 190 SSLCertificates []string `json:"ssl_certificates"` 191 ServerName string `json:"server_name"` 192 MinVersion uint16 `json:"min_version"` 193 FlushInterval int `json:"flush_interval"` 194 SkipURLCleaning bool `json:"skip_url_cleaning"` 195 SkipTargetPathEscaping bool `json:"skip_target_path_escaping"` 196 Ciphers []string `json:"ssl_ciphers"` 197 } 198 199 type AuthOverrideConf struct { 200 ForceAuthProvider bool `json:"force_auth_provider"` 201 AuthProvider apidef.AuthProviderMeta `json:"auth_provider"` 202 ForceSessionProvider bool `json:"force_session_provider"` 203 SessionProvider apidef.SessionProviderMeta `json:"session_provider"` 204 } 205 206 type UptimeTestsConfigDetail struct { 207 FailureTriggerSampleSize int `json:"failure_trigger_sample_size"` 208 TimeWait int `json:"time_wait"` 209 CheckerPoolSize int `json:"checker_pool_size"` 210 EnableUptimeAnalytics bool `json:"enable_uptime_analytics"` 211 } 212 213 type UptimeTestsConfig struct { 214 Disable bool `json:"disable"` 215 Config UptimeTestsConfigDetail `json:"config"` 216 } 217 218 type ServiceDiscoveryConf struct { 219 DefaultCacheTimeout int `json:"default_cache_timeout"` 220 } 221 222 type CoProcessConfig struct { 223 EnableCoProcess bool `json:"enable_coprocess"` 224 CoProcessGRPCServer string `json:"coprocess_grpc_server"` 225 PythonPathPrefix string `json:"python_path_prefix"` 226 } 227 228 type CertificatesConfig struct { 229 API []string `json:"apis"` 230 Upstream map[string]string `json:"upstream"` 231 ControlAPI []string `json:"control_api"` 232 Dashboard []string `json:"dashboard_api"` 233 MDCB []string `json:"mdcb_api"` 234 } 235 236 type SecurityConfig struct { 237 PrivateCertificateEncodingSecret string `json:"private_certificate_encoding_secret"` 238 ControlAPIUseMutualTLS bool `json:"control_api_use_mutual_tls"` 239 PinnedPublicKeys map[string]string `json:"pinned_public_keys"` 240 Certificates CertificatesConfig `json:"certificates"` 241 } 242 243 type NewRelicConfig struct { 244 AppName string `json:"app_name"` 245 LicenseKey string `json:"license_key"` 246 } 247 248 type Tracer struct { 249 // The name of the tracer to initialize. For instance appdash, to use appdash 250 // tracer 251 Name string `json:"name"` 252 253 // If true then this tracer will be activated and all tracing data will be sent 254 // to this tracer.NoOp tracer is used otherwise which collects traces but 255 // discard them. 256 Enabled bool `json:"enabled"` 257 258 // Key value pairs used to initialize the tracer. These are tracer specific, 259 // each tracer requires different options to operate. Please see trace package 260 // for options required by supported tracer implementation. 261 Options map[string]interface{} `json:"options"` 262 } 263 264 // Config is the configuration object used by tyk to set up various parameters. 265 type Config struct { 266 // OriginalPath is the path to the config file that was read. If 267 // none was found, it's the path to the default config file that 268 // was written. 269 OriginalPath string `json:"-"` 270 271 HostName string `json:"hostname"` 272 ListenAddress string `json:"listen_address"` 273 ListenPort int `json:"listen_port"` 274 ControlAPIHostname string `json:"control_api_hostname"` 275 ControlAPIPort int `json:"control_api_port"` 276 Secret string `json:"secret"` 277 NodeSecret string `json:"node_secret"` 278 PIDFileLocation string `json:"pid_file_location"` 279 AllowInsecureConfigs bool `json:"allow_insecure_configs"` 280 PublicKeyPath string `json:"public_key_path"` 281 AllowRemoteConfig bool `bson:"allow_remote_config" json:"allow_remote_config"` 282 Security SecurityConfig `json:"security"` 283 HttpServerOptions HttpServerOptionsConfig `json:"http_server_options"` 284 ReloadWaitTime int `bson:"reload_wait_time" json:"reload_wait_time"` 285 VersionHeader string `json:"version_header"` 286 UseAsyncSessionWrite bool `json:"optimisations_use_async_session_write"` 287 SuppressRedisSignalReload bool `json:"suppress_redis_signal_reload"` 288 289 // Gateway Security Policies 290 HashKeys bool `json:"hash_keys"` 291 HashKeyFunction string `json:"hash_key_function"` 292 EnableHashedKeysListing bool `json:"enable_hashed_keys_listing"` 293 MinTokenLength int `json:"min_token_length"` 294 EnableAPISegregation bool `json:"enable_api_segregation"` 295 TemplatePath string `json:"template_path"` 296 Policies PoliciesConfig `json:"policies"` 297 298 // CE Configurations 299 AppPath string `json:"app_path"` 300 301 // Dashboard Configurations 302 UseDBAppConfigs bool `json:"use_db_app_configs"` 303 DBAppConfOptions DBAppConfOptionsConfig `json:"db_app_conf_options"` 304 Storage StorageOptionsConf `json:"storage"` 305 DisableDashboardZeroConf bool `json:"disable_dashboard_zeroconf"` 306 307 // Slave Configurations 308 SlaveOptions SlaveOptionsConfig `json:"slave_options"` 309 ManagementNode bool `json:"management_node"` 310 AuthOverride AuthOverrideConf `json:"auth_override"` 311 312 // Rate Limiting Strategy 313 EnableNonTransactionalRateLimiter bool `json:"enable_non_transactional_rate_limiter"` 314 EnableSentinelRateLimiter bool `json:"enable_sentinel_rate_limiter"` 315 EnableRedisRollingLimiter bool `json:"enable_redis_rolling_limiter"` 316 DRLNotificationFrequency int `json:"drl_notification_frequency"` 317 318 // Organization configurations 319 EnforceOrgDataAge bool `json:"enforce_org_data_age"` 320 EnforceOrgDataDetailLogging bool `json:"enforce_org_data_detail_logging"` 321 EnforceOrgQuotas bool `json:"enforce_org_quotas"` 322 ExperimentalProcessOrgOffThread bool `json:"experimental_process_org_off_thread"` 323 Monitor MonitorConfig `json:"monitor"` 324 325 // Client-Gateway Configuration 326 MaxIdleConns int `bson:"max_idle_connections" json:"max_idle_connections"` 327 MaxIdleConnsPerHost int `bson:"max_idle_connections_per_host" json:"max_idle_connections_per_host"` 328 MaxConnTime int64 `json:"max_conn_time"` 329 CloseIdleConnections bool `json:"close_idle_connections"` 330 CloseConnections bool `json:"close_connections"` 331 EnableCustomDomains bool `json:"enable_custom_domains"` 332 // If AllowMasterKeys is set to true, session objects (key definitions) that do not have explicit access rights set 333 // will be allowed by Tyk. This means that keys that are created have access to ALL APIs, which in many cases is 334 // unwanted behaviour unless you are sure about what you are doing. 335 AllowMasterKeys bool `json:"allow_master_keys"` 336 337 // Gateway-Service Configuration 338 ServiceDiscovery ServiceDiscoveryConf `json:"service_discovery"` 339 ProxySSLInsecureSkipVerify bool `json:"proxy_ssl_insecure_skip_verify"` 340 ProxyEnableHttp2 bool `json:"proxy_enable_http2"` 341 ProxySSLMinVersion uint16 `json:"proxy_ssl_min_version"` 342 ProxySSLCipherSuites []string `json:"proxy_ssl_ciphers"` 343 ProxyDefaultTimeout float64 `json:"proxy_default_timeout"` 344 ProxySSLDisableRenegotiation bool `json:"proxy_ssl_disable_renegotiation"` 345 ProxyCloseConnections bool `json:"proxy_close_connections"` 346 UptimeTests UptimeTestsConfig `json:"uptime_tests"` 347 HealthCheck HealthCheckConfig `json:"health_check"` 348 OauthRefreshExpire int64 `json:"oauth_refresh_token_expire"` 349 OauthTokenExpire int32 `json:"oauth_token_expire"` 350 OauthTokenExpiredRetainPeriod int32 `json:"oauth_token_expired_retain_period"` 351 OauthRedirectUriSeparator string `json:"oauth_redirect_uri_separator"` 352 EnableKeyLogging bool `json:"enable_key_logging"` 353 354 // Proxy analytics configuration 355 EnableAnalytics bool `json:"enable_analytics"` 356 AnalyticsConfig AnalyticsConfigConfig `json:"analytics_config"` 357 358 // Cache 359 DnsCache DnsCacheConfig `json:"dns_cache"` 360 DisableRegexpCache bool `json:"disable_regexp_cache"` 361 RegexpCacheExpire int32 `json:"regexp_cache_expire"` 362 LocalSessionCache LocalSessionCacheConf `json:"local_session_cache"` 363 EnableSeperateCacheStore bool `json:"enable_separate_cache_store"` 364 CacheStorage StorageOptionsConf `json:"cache_storage"` 365 366 // Middleware/Plugin Configuration 367 EnableBundleDownloader bool `bson:"enable_bundle_downloader" json:"enable_bundle_downloader"` 368 BundleBaseURL string `bson:"bundle_base_url" json:"bundle_base_url"` 369 EnableJSVM bool `json:"enable_jsvm"` 370 JSVMTimeout int `json:"jsvm_timeout"` 371 DisableVirtualPathBlobs bool `json:"disable_virtual_path_blobs"` 372 TykJSPath string `json:"tyk_js_path"` 373 MiddlewarePath string `json:"middleware_path"` 374 CoProcessOptions CoProcessConfig `json:"coprocess_options"` 375 376 // Monitoring, Logging & Profiling 377 LogLevel string `json:"log_level"` 378 HealthCheckEndpointName string `json:"health_check_endpoint_name"` 379 Tracer Tracer `json:"tracing"` 380 NewRelic NewRelicConfig `json:"newrelic"` 381 HTTPProfile bool `json:"enable_http_profiler"` 382 UseRedisLog bool `json:"use_redis_log"` 383 SentryCode string `json:"sentry_code"` 384 UseSentry bool `json:"use_sentry"` 385 UseSyslog bool `json:"use_syslog"` 386 UseGraylog bool `json:"use_graylog"` 387 UseLogstash bool `json:"use_logstash"` 388 GraylogNetworkAddr string `json:"graylog_network_addr"` 389 LogstashNetworkAddr string `json:"logstash_network_addr"` 390 SyslogTransport string `json:"syslog_transport"` 391 LogstashTransport string `json:"logstash_transport"` 392 SyslogNetworkAddr string `json:"syslog_network_addr"` 393 StatsdConnectionString string `json:"statsd_connection_string"` 394 StatsdPrefix string `json:"statsd_prefix"` 395 396 // Event System 397 EventHandlers apidef.EventHandlerMetaConfig `json:"event_handlers"` 398 EventTriggers map[apidef.TykEvent][]TykEventHandler `json:"event_trigers_defunct"` // Deprecated: Config.GetEventTriggers instead. 399 EventTriggersDefunct map[apidef.TykEvent][]TykEventHandler `json:"event_triggers_defunct"` // Deprecated: Config.GetEventTriggers instead. 400 401 // TODO: These config options are not documented - What do they do? 402 SessionUpdatePoolSize int `json:"session_update_pool_size"` 403 SessionUpdateBufferSize int `json:"session_update_buffer_size"` 404 SupressDefaultOrgStore bool `json:"suppress_default_org_store"` 405 LegacyEnableAllowanceCountdown bool `bson:"legacy_enable_allowance_countdown" json:"legacy_enable_allowance_countdown"` 406 GlobalSessionLifetime int64 `bson:"global_session_lifetime" json:"global_session_lifetime"` 407 ForceGlobalSessionLifetime bool `bson:"force_global_session_lifetime" json:"force_global_session_lifetime"` 408 HideGeneratorHeader bool `json:"hide_generator_header"` 409 410 // Cisco - Redis DB Api Store 411 UseRedisDBAppConfig bool `json:"use_redis_db_app_configs"` 412 RedisDBAppConfOptions RedisDBAppConfOptionsConfig `json:"redis_db_app_conf_options"` 413 414 // Cisco - Read timeout 415 DynamicAPIConnTimeout int `json:"dynamic_api_timeout_milli_sec"` 416 } 417 418 // GetEventTriggers returns event triggers. There was a typo in the json tag. 419 // To maintain backward compatibility, this solution is chosen. 420 func (c Config) GetEventTriggers() map[apidef.TykEvent][]TykEventHandler { 421 if c.EventTriggersDefunct == nil { 422 return c.EventTriggers 423 } 424 425 if c.EventTriggers != nil { 426 log.Info("Both event_trigers_defunct and event_triggers_defunct are configured in the config," + 427 " event_triggers_defunct will be used.") 428 } 429 430 return c.EventTriggersDefunct 431 } 432 433 func (c *Config) SetEventTriggers(eventTriggers map[apidef.TykEvent][]TykEventHandler) { 434 c.EventTriggersDefunct = eventTriggers 435 } 436 437 type CertData struct { 438 Name string `json:"domain_name"` 439 CertFile string `json:"cert_file"` 440 KeyFile string `json:"key_file"` 441 } 442 443 // EventMessage is a standard form to send event data to handlers 444 type EventMessage struct { 445 Type apidef.TykEvent 446 Meta interface{} 447 TimeStamp string 448 } 449 450 // TykEventHandler defines an event handler, e.g. LogMessageEventHandler will handle an event by logging it to stdout. 451 type TykEventHandler interface { 452 Init(interface{}) error 453 HandleEvent(EventMessage) 454 } 455 456 func init() { 457 SetGlobal(Config{}) 458 } 459 460 func Global() Config { 461 return global.Load().(Config) 462 } 463 464 func SetGlobal(conf Config) { 465 globalMu.Lock() 466 defer globalMu.Unlock() 467 global.Store(conf) 468 } 469 470 func WriteConf(path string, conf *Config) error { 471 bs, err := json.MarshalIndent(conf, "", " ") 472 if err != nil { 473 return err 474 } 475 return ioutil.WriteFile(path, bs, 0644) 476 } 477 478 // writeDefault will set conf to the default config and write it to disk 479 // in path, if the path is non-empty. 480 func WriteDefault(path string, conf *Config) error { 481 _, b, _, _ := runtime.Caller(0) 482 configPath := filepath.Dir(b) 483 rootPath := filepath.Dir(configPath) 484 Default.TemplatePath = filepath.Join(rootPath, "templates") 485 486 *conf = Default 487 if err := envconfig.Process(envPrefix, conf); err != nil { 488 return err 489 } 490 if path == "" { 491 return nil 492 } 493 return WriteConf(path, conf) 494 } 495 496 // Load will load a configuration file, trying each of the paths given 497 // and using the first one that is a regular file and can be opened. 498 // 499 // If none exists, a default config will be written to the first path in 500 // the list. 501 // 502 // An error will be returned only if any of the paths existed but was 503 // not a valid config file. 504 func Load(paths []string, conf *Config) error { 505 var r io.Reader 506 for _, path := range paths { 507 f, err := os.Open(path) 508 if err == nil { 509 r = f 510 conf.OriginalPath = path 511 break 512 } 513 if os.IsNotExist(err) { 514 continue 515 } 516 return err 517 } 518 if r == nil { 519 path := paths[0] 520 log.Warnf("No config file found, writing default to %s", path) 521 if err := WriteDefault(path, conf); err != nil { 522 return err 523 } 524 log.Info("Loading default configuration...") 525 return Load([]string{path}, conf) 526 } 527 if err := json.NewDecoder(r).Decode(&conf); err != nil { 528 return fmt.Errorf("couldn't unmarshal config: %v", err) 529 } 530 if err := envconfig.Process(envPrefix, conf); err != nil { 531 return fmt.Errorf("failed to process config env vars: %v", err) 532 } 533 return nil 534 } 535 536 func (c *Config) LoadIgnoredIPs() { 537 c.AnalyticsConfig.ignoredIPsCompiled = make(map[string]bool, len(c.AnalyticsConfig.IgnoredIPs)) 538 for _, ip := range c.AnalyticsConfig.IgnoredIPs { 539 c.AnalyticsConfig.ignoredIPsCompiled[ip] = true 540 } 541 } 542 543 func (c *Config) StoreAnalytics(ip string) bool { 544 if !c.EnableAnalytics { 545 return false 546 } 547 548 return !c.AnalyticsConfig.ignoredIPsCompiled[ip] 549 }