github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/configs/configmaps.go (about) 1 package configs 2 3 import ( 4 "strings" 5 6 "github.com/golang/glog" 7 v1 "k8s.io/api/core/v1" 8 9 "github.com/nginxinc/kubernetes-ingress/internal/configs/version1" 10 ) 11 12 // ParseConfigMap parses ConfigMap into ConfigParams. 13 func ParseConfigMap(cfgm *v1.ConfigMap, nginxPlus bool, hasAppProtect bool) *ConfigParams { 14 cfgParams := NewDefaultConfigParams() 15 16 if serverTokens, exists, err := GetMapKeyAsBool(cfgm.Data, "server-tokens", cfgm); exists { 17 if err != nil { 18 if nginxPlus { 19 cfgParams.ServerTokens = cfgm.Data["server-tokens"] 20 } else { 21 glog.Error(err) 22 } 23 } else { 24 cfgParams.ServerTokens = "off" 25 if serverTokens { 26 cfgParams.ServerTokens = "on" 27 } 28 } 29 } 30 31 if lbMethod, exists := cfgm.Data["lb-method"]; exists { 32 if nginxPlus { 33 if parsedMethod, err := ParseLBMethodForPlus(lbMethod); err != nil { 34 glog.Errorf("Configmap %s/%s: Invalid value for the lb-method key: got %q: %v", cfgm.GetNamespace(), cfgm.GetName(), lbMethod, err) 35 } else { 36 cfgParams.LBMethod = parsedMethod 37 } 38 } else { 39 if parsedMethod, err := ParseLBMethod(lbMethod); err != nil { 40 glog.Errorf("Configmap %s/%s: Invalid value for the lb-method key: got %q: %v", cfgm.GetNamespace(), cfgm.GetName(), lbMethod, err) 41 } else { 42 cfgParams.LBMethod = parsedMethod 43 } 44 } 45 } 46 47 if proxyConnectTimeout, exists := cfgm.Data["proxy-connect-timeout"]; exists { 48 cfgParams.ProxyConnectTimeout = proxyConnectTimeout 49 } 50 51 if proxyReadTimeout, exists := cfgm.Data["proxy-read-timeout"]; exists { 52 cfgParams.ProxyReadTimeout = proxyReadTimeout 53 } 54 55 if proxySendTimeout, exists := cfgm.Data["proxy-send-timeout"]; exists { 56 cfgParams.ProxySendTimeout = proxySendTimeout 57 } 58 59 if proxyHideHeaders, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "proxy-hide-headers", cfgm, ","); exists { 60 if err != nil { 61 glog.Error(err) 62 } else { 63 cfgParams.ProxyHideHeaders = proxyHideHeaders 64 } 65 } 66 67 if proxyPassHeaders, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "proxy-pass-headers", cfgm, ","); exists { 68 if err != nil { 69 glog.Error(err) 70 } else { 71 cfgParams.ProxyPassHeaders = proxyPassHeaders 72 } 73 } 74 75 if clientMaxBodySize, exists := cfgm.Data["client-max-body-size"]; exists { 76 cfgParams.ClientMaxBodySize = clientMaxBodySize 77 } 78 79 if serverNamesHashBucketSize, exists := cfgm.Data["server-names-hash-bucket-size"]; exists { 80 cfgParams.MainServerNamesHashBucketSize = serverNamesHashBucketSize 81 } 82 83 if serverNamesHashMaxSize, exists := cfgm.Data["server-names-hash-max-size"]; exists { 84 cfgParams.MainServerNamesHashMaxSize = serverNamesHashMaxSize 85 } 86 87 if HTTP2, exists, err := GetMapKeyAsBool(cfgm.Data, "http2", cfgm); exists { 88 if err != nil { 89 glog.Error(err) 90 } else { 91 cfgParams.HTTP2 = HTTP2 92 } 93 } 94 95 if redirectToHTTPS, exists, err := GetMapKeyAsBool(cfgm.Data, "redirect-to-https", cfgm); exists { 96 if err != nil { 97 glog.Error(err) 98 } else { 99 cfgParams.RedirectToHTTPS = redirectToHTTPS 100 } 101 } 102 103 if sslRedirect, exists, err := GetMapKeyAsBool(cfgm.Data, "ssl-redirect", cfgm); exists { 104 if err != nil { 105 glog.Error(err) 106 } else { 107 cfgParams.SSLRedirect = sslRedirect 108 } 109 } 110 111 if hsts, exists, err := GetMapKeyAsBool(cfgm.Data, "hsts", cfgm); exists { 112 if err != nil { 113 glog.Error(err) 114 } else { 115 parsingErrors := false 116 117 hstsMaxAge, existsMA, err := GetMapKeyAsInt64(cfgm.Data, "hsts-max-age", cfgm) 118 if existsMA && err != nil { 119 glog.Error(err) 120 parsingErrors = true 121 } 122 hstsIncludeSubdomains, existsIS, err := GetMapKeyAsBool(cfgm.Data, "hsts-include-subdomains", cfgm) 123 if existsIS && err != nil { 124 glog.Error(err) 125 parsingErrors = true 126 } 127 hstsBehindProxy, existsBP, err := GetMapKeyAsBool(cfgm.Data, "hsts-behind-proxy", cfgm) 128 if existsBP && err != nil { 129 glog.Error(err) 130 parsingErrors = true 131 } 132 133 if parsingErrors { 134 glog.Errorf("Configmap %s/%s: There are configuration issues with hsts annotations, skipping options for all hsts settings", cfgm.GetNamespace(), cfgm.GetName()) 135 } else { 136 cfgParams.HSTS = hsts 137 if existsMA { 138 cfgParams.HSTSMaxAge = hstsMaxAge 139 } 140 if existsIS { 141 cfgParams.HSTSIncludeSubdomains = hstsIncludeSubdomains 142 } 143 if existsBP { 144 cfgParams.HSTSBehindProxy = hstsBehindProxy 145 } 146 } 147 } 148 } 149 150 if proxyProtocol, exists, err := GetMapKeyAsBool(cfgm.Data, "proxy-protocol", cfgm); exists { 151 if err != nil { 152 glog.Error(err) 153 } else { 154 cfgParams.ProxyProtocol = proxyProtocol 155 } 156 } 157 158 if realIPHeader, exists := cfgm.Data["real-ip-header"]; exists { 159 cfgParams.RealIPHeader = realIPHeader 160 } 161 162 if setRealIPFrom, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "set-real-ip-from", cfgm, ","); exists { 163 if err != nil { 164 glog.Error(err) 165 } else { 166 cfgParams.SetRealIPFrom = setRealIPFrom 167 } 168 } 169 170 if realIPRecursive, exists, err := GetMapKeyAsBool(cfgm.Data, "real-ip-recursive", cfgm); exists { 171 if err != nil { 172 glog.Error(err) 173 } else { 174 cfgParams.RealIPRecursive = realIPRecursive 175 } 176 } 177 178 if sslProtocols, exists := cfgm.Data["ssl-protocols"]; exists { 179 cfgParams.MainServerSSLProtocols = sslProtocols 180 } 181 182 if sslPreferServerCiphers, exists, err := GetMapKeyAsBool(cfgm.Data, "ssl-prefer-server-ciphers", cfgm); exists { 183 if err != nil { 184 glog.Error(err) 185 } else { 186 cfgParams.MainServerSSLPreferServerCiphers = sslPreferServerCiphers 187 } 188 } 189 190 if sslCiphers, exists := cfgm.Data["ssl-ciphers"]; exists { 191 cfgParams.MainServerSSLCiphers = strings.Trim(sslCiphers, "\n") 192 } 193 194 if sslDHParamFile, exists := cfgm.Data["ssl-dhparam-file"]; exists { 195 sslDHParamFile = strings.Trim(sslDHParamFile, "\n") 196 cfgParams.MainServerSSLDHParamFileContent = &sslDHParamFile 197 } 198 199 if errorLogLevel, exists := cfgm.Data["error-log-level"]; exists { 200 cfgParams.MainErrorLogLevel = errorLogLevel 201 } 202 203 if accessLogOff, exists, err := GetMapKeyAsBool(cfgm.Data, "access-log-off", cfgm); exists { 204 if err != nil { 205 glog.Error(err) 206 } else { 207 cfgParams.MainAccessLogOff = accessLogOff 208 } 209 } 210 211 if logFormat, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "log-format", cfgm, "\n"); exists { 212 if err != nil { 213 glog.Error(err) 214 } else { 215 cfgParams.MainLogFormat = logFormat 216 } 217 } 218 219 if logFormatEscaping, exists := cfgm.Data["log-format-escaping"]; exists { 220 logFormatEscaping = strings.TrimSpace(logFormatEscaping) 221 if logFormatEscaping != "" { 222 cfgParams.MainLogFormatEscaping = logFormatEscaping 223 } 224 } 225 226 if streamLogFormat, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "stream-log-format", cfgm, "\n"); exists { 227 if err != nil { 228 glog.Error(err) 229 } else { 230 cfgParams.MainStreamLogFormat = streamLogFormat 231 } 232 } 233 234 if streamLogFormatEscaping, exists := cfgm.Data["stream-log-format-escaping"]; exists { 235 streamLogFormatEscaping = strings.TrimSpace(streamLogFormatEscaping) 236 if streamLogFormatEscaping != "" { 237 cfgParams.MainStreamLogFormatEscaping = streamLogFormatEscaping 238 } 239 } 240 241 if defaultServerAccessLogOff, exists, err := GetMapKeyAsBool(cfgm.Data, "default-server-access-log-off", cfgm); exists { 242 if err != nil { 243 glog.Error(err) 244 } else { 245 cfgParams.DefaultServerAccessLogOff = defaultServerAccessLogOff 246 } 247 } 248 249 if defaultServerReturn, exists := cfgm.Data["default-server-return"]; exists { 250 cfgParams.DefaultServerReturn = defaultServerReturn 251 } 252 253 if proxyBuffering, exists, err := GetMapKeyAsBool(cfgm.Data, "proxy-buffering", cfgm); exists { 254 if err != nil { 255 glog.Error(err) 256 } else { 257 cfgParams.ProxyBuffering = proxyBuffering 258 } 259 } 260 261 if proxyBuffers, exists := cfgm.Data["proxy-buffers"]; exists { 262 cfgParams.ProxyBuffers = proxyBuffers 263 } 264 265 if proxyBufferSize, exists := cfgm.Data["proxy-buffer-size"]; exists { 266 cfgParams.ProxyBufferSize = proxyBufferSize 267 } 268 269 if proxyMaxTempFileSize, exists := cfgm.Data["proxy-max-temp-file-size"]; exists { 270 cfgParams.ProxyMaxTempFileSize = proxyMaxTempFileSize 271 } 272 273 if mainMainSnippets, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "main-snippets", cfgm, "\n"); exists { 274 if err != nil { 275 glog.Error(err) 276 } else { 277 cfgParams.MainMainSnippets = mainMainSnippets 278 } 279 } 280 281 if mainHTTPSnippets, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "http-snippets", cfgm, "\n"); exists { 282 if err != nil { 283 glog.Error(err) 284 } else { 285 cfgParams.MainHTTPSnippets = mainHTTPSnippets 286 } 287 } 288 289 if locationSnippets, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "location-snippets", cfgm, "\n"); exists { 290 if err != nil { 291 glog.Error(err) 292 } else { 293 cfgParams.LocationSnippets = locationSnippets 294 } 295 } 296 297 if serverSnippets, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "server-snippets", cfgm, "\n"); exists { 298 if err != nil { 299 glog.Error(err) 300 } else { 301 cfgParams.ServerSnippets = serverSnippets 302 } 303 } 304 305 if _, exists, err := GetMapKeyAsInt(cfgm.Data, "worker-processes", cfgm); exists { 306 if err != nil && cfgm.Data["worker-processes"] != "auto" { 307 glog.Errorf("Configmap %s/%s: Invalid value for worker-processes key: must be an integer or the string 'auto', got %q", cfgm.GetNamespace(), cfgm.GetName(), cfgm.Data["worker-processes"]) 308 } else { 309 cfgParams.MainWorkerProcesses = cfgm.Data["worker-processes"] 310 } 311 } 312 313 if workerCPUAffinity, exists := cfgm.Data["worker-cpu-affinity"]; exists { 314 cfgParams.MainWorkerCPUAffinity = workerCPUAffinity 315 } 316 317 if workerShutdownTimeout, exists := cfgm.Data["worker-shutdown-timeout"]; exists { 318 cfgParams.MainWorkerShutdownTimeout = workerShutdownTimeout 319 } 320 321 if workerConnections, exists := cfgm.Data["worker-connections"]; exists { 322 cfgParams.MainWorkerConnections = workerConnections 323 } 324 325 if workerRlimitNofile, exists := cfgm.Data["worker-rlimit-nofile"]; exists { 326 cfgParams.MainWorkerRlimitNofile = workerRlimitNofile 327 } 328 329 if keepalive, exists, err := GetMapKeyAsInt(cfgm.Data, "keepalive", cfgm); exists { 330 if err != nil { 331 glog.Error(err) 332 } else { 333 cfgParams.Keepalive = keepalive 334 } 335 } 336 337 if maxFails, exists, err := GetMapKeyAsInt(cfgm.Data, "max-fails", cfgm); exists { 338 if err != nil { 339 glog.Error(err) 340 } else { 341 cfgParams.MaxFails = maxFails 342 } 343 } 344 345 if upstreamZoneSize, exists := cfgm.Data["upstream-zone-size"]; exists { 346 cfgParams.UpstreamZoneSize = upstreamZoneSize 347 } 348 349 if failTimeout, exists := cfgm.Data["fail-timeout"]; exists { 350 cfgParams.FailTimeout = failTimeout 351 } 352 353 if mainTemplate, exists := cfgm.Data["main-template"]; exists { 354 cfgParams.MainTemplate = &mainTemplate 355 } 356 357 if ingressTemplate, exists := cfgm.Data["ingress-template"]; exists { 358 cfgParams.IngressTemplate = &ingressTemplate 359 } 360 361 if virtualServerTemplate, exists := cfgm.Data["virtualserver-template"]; exists { 362 cfgParams.VirtualServerTemplate = &virtualServerTemplate 363 } 364 365 if mainStreamSnippets, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "stream-snippets", cfgm, "\n"); exists { 366 if err != nil { 367 glog.Error(err) 368 } else { 369 cfgParams.MainStreamSnippets = mainStreamSnippets 370 } 371 } 372 373 if resolverAddresses, exists, err := GetMapKeyAsStringSlice(cfgm.Data, "resolver-addresses", cfgm, ","); exists { 374 if err != nil { 375 glog.Error(err) 376 } else { 377 if nginxPlus { 378 cfgParams.ResolverAddresses = resolverAddresses 379 } else { 380 glog.Warning("ConfigMap key 'resolver-addresses' requires NGINX Plus") 381 } 382 } 383 } 384 385 if resolverIpv6, exists, err := GetMapKeyAsBool(cfgm.Data, "resolver-ipv6", cfgm); exists { 386 if err != nil { 387 glog.Error(err) 388 } else { 389 if nginxPlus { 390 cfgParams.ResolverIPV6 = resolverIpv6 391 } else { 392 glog.Warning("ConfigMap key 'resolver-ipv6' requires NGINX Plus") 393 } 394 } 395 } 396 397 if resolverValid, exists := cfgm.Data["resolver-valid"]; exists { 398 if nginxPlus { 399 cfgParams.ResolverValid = resolverValid 400 } else { 401 glog.Warning("ConfigMap key 'resolver-valid' requires NGINX Plus") 402 } 403 } 404 405 if resolverTimeout, exists := cfgm.Data["resolver-timeout"]; exists { 406 if nginxPlus { 407 cfgParams.ResolverTimeout = resolverTimeout 408 } else { 409 glog.Warning("ConfigMap key 'resolver-timeout' requires NGINX Plus") 410 } 411 } 412 413 if keepaliveTimeout, exists := cfgm.Data["keepalive-timeout"]; exists { 414 cfgParams.MainKeepaliveTimeout = keepaliveTimeout 415 } 416 417 if keepaliveRequests, exists, err := GetMapKeyAsInt64(cfgm.Data, "keepalive-requests", cfgm); exists { 418 if err != nil { 419 glog.Error(err) 420 } else { 421 cfgParams.MainKeepaliveRequests = keepaliveRequests 422 } 423 } 424 425 if varHashBucketSize, exists, err := GetMapKeyAsUint64(cfgm.Data, "variables-hash-bucket-size", cfgm, true); exists { 426 if err != nil { 427 glog.Error(err) 428 } else { 429 cfgParams.VariablesHashBucketSize = varHashBucketSize 430 } 431 } 432 433 if varHashMaxSize, exists, err := GetMapKeyAsUint64(cfgm.Data, "variables-hash-max-size", cfgm, false); exists { 434 if err != nil { 435 glog.Error(err) 436 } else { 437 cfgParams.VariablesHashMaxSize = varHashMaxSize 438 } 439 } 440 441 if openTracingTracer, exists := cfgm.Data["opentracing-tracer"]; exists { 442 cfgParams.MainOpenTracingTracer = openTracingTracer 443 } 444 445 if openTracingTracerConfig, exists := cfgm.Data["opentracing-tracer-config"]; exists { 446 cfgParams.MainOpenTracingTracerConfig = openTracingTracerConfig 447 } 448 449 if cfgParams.MainOpenTracingTracer != "" || cfgParams.MainOpenTracingTracerConfig != "" { 450 cfgParams.MainOpenTracingLoadModule = true 451 } 452 453 if openTracing, exists, err := GetMapKeyAsBool(cfgm.Data, "opentracing", cfgm); exists { 454 if err != nil { 455 glog.Error(err) 456 } else { 457 if cfgParams.MainOpenTracingLoadModule { 458 cfgParams.MainOpenTracingEnabled = openTracing 459 } else { 460 glog.Error("ConfigMap Key 'opentracing' requires both 'opentracing-tracer' and 'opentracing-tracer-config' Keys configured, Opentracing will be disabled") 461 } 462 } 463 } 464 465 if hasAppProtect { 466 if appProtectFailureModeAction, exists := cfgm.Data["app-protect-failure-mode-action"]; exists { 467 if appProtectFailureModeAction == "pass" || appProtectFailureModeAction == "drop" { 468 cfgParams.MainAppProtectFailureModeAction = appProtectFailureModeAction 469 } else { 470 glog.Error("ConfigMap Key 'app-protect-failure-mode-action' must have value 'pass' or 'drop'. Ignoring.") 471 } 472 } 473 474 if appProtectCookieSeed, exists := cfgm.Data["app-protect-cookie-seed"]; exists { 475 cfgParams.MainAppProtectCookieSeed = appProtectCookieSeed 476 } 477 478 if appProtectCPUThresholds, exists := cfgm.Data["app-protect-cpu-thresholds"]; exists { 479 if VerifyAppProtectThresholds(appProtectCPUThresholds) { 480 cfgParams.MainAppProtectCPUThresholds = appProtectCPUThresholds 481 } else { 482 glog.Error("ConfigMap Key 'app-protect-cpu-thresholds' must follow pattern: 'high=<0 - 100> low=<0 - 100>'. Ignoring.") 483 } 484 } 485 486 if appProtectPhysicalMemoryThresholds, exists := cfgm.Data["app-protect-physical-memory-util-thresholds"]; exists { 487 cfgParams.MainAppProtectPhysicalMemoryThresholds = appProtectPhysicalMemoryThresholds 488 if VerifyAppProtectThresholds(appProtectPhysicalMemoryThresholds) { 489 cfgParams.MainAppProtectPhysicalMemoryThresholds = appProtectPhysicalMemoryThresholds 490 } else { 491 glog.Error("ConfigMap Key 'app-protect-physical-memory-thresholds' must follow pattern: 'high=<0 - 100> low=<0 - 100>'. Ignoring.") 492 } 493 } 494 } 495 496 return cfgParams 497 } 498 499 // GenerateNginxMainConfig generates MainConfig. 500 func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *ConfigParams) *version1.MainConfig { 501 nginxCfg := &version1.MainConfig{ 502 AccessLogOff: config.MainAccessLogOff, 503 DefaultServerAccessLogOff: config.DefaultServerAccessLogOff, 504 DefaultServerReturn: config.DefaultServerReturn, 505 ErrorLogLevel: config.MainErrorLogLevel, 506 HealthStatus: staticCfgParams.HealthStatus, 507 HealthStatusURI: staticCfgParams.HealthStatusURI, 508 HTTP2: config.HTTP2, 509 HTTPSnippets: config.MainHTTPSnippets, 510 KeepaliveRequests: config.MainKeepaliveRequests, 511 KeepaliveTimeout: config.MainKeepaliveTimeout, 512 LogFormat: config.MainLogFormat, 513 LogFormatEscaping: config.MainLogFormatEscaping, 514 MainSnippets: config.MainMainSnippets, 515 NginxStatus: staticCfgParams.NginxStatus, 516 NginxStatusAllowCIDRs: staticCfgParams.NginxStatusAllowCIDRs, 517 NginxStatusPort: staticCfgParams.NginxStatusPort, 518 OpenTracingEnabled: config.MainOpenTracingEnabled, 519 OpenTracingLoadModule: config.MainOpenTracingLoadModule, 520 OpenTracingTracer: config.MainOpenTracingTracer, 521 OpenTracingTracerConfig: config.MainOpenTracingTracerConfig, 522 ProxyProtocol: config.ProxyProtocol, 523 ResolverAddresses: config.ResolverAddresses, 524 ResolverIPV6: config.ResolverIPV6, 525 ResolverTimeout: config.ResolverTimeout, 526 ResolverValid: config.ResolverValid, 527 RealIPHeader: config.RealIPHeader, 528 RealIPRecursive: config.RealIPRecursive, 529 SetRealIPFrom: config.SetRealIPFrom, 530 ServerNamesHashBucketSize: config.MainServerNamesHashBucketSize, 531 ServerNamesHashMaxSize: config.MainServerNamesHashMaxSize, 532 ServerTokens: config.ServerTokens, 533 SSLCiphers: config.MainServerSSLCiphers, 534 SSLDHParam: config.MainServerSSLDHParam, 535 SSLPreferServerCiphers: config.MainServerSSLPreferServerCiphers, 536 SSLProtocols: config.MainServerSSLProtocols, 537 SSLRejectHandshake: staticCfgParams.SSLRejectHandshake, 538 TLSPassthrough: staticCfgParams.TLSPassthrough, 539 StreamLogFormat: config.MainStreamLogFormat, 540 StreamLogFormatEscaping: config.MainStreamLogFormatEscaping, 541 StreamSnippets: config.MainStreamSnippets, 542 StubStatusOverUnixSocketForOSS: staticCfgParams.StubStatusOverUnixSocketForOSS, 543 WorkerCPUAffinity: config.MainWorkerCPUAffinity, 544 WorkerProcesses: config.MainWorkerProcesses, 545 WorkerShutdownTimeout: config.MainWorkerShutdownTimeout, 546 WorkerConnections: config.MainWorkerConnections, 547 WorkerRlimitNofile: config.MainWorkerRlimitNofile, 548 VariablesHashBucketSize: config.VariablesHashBucketSize, 549 VariablesHashMaxSize: config.VariablesHashMaxSize, 550 AppProtectLoadModule: staticCfgParams.MainAppProtectLoadModule, 551 AppProtectFailureModeAction: config.MainAppProtectFailureModeAction, 552 AppProtectCookieSeed: config.MainAppProtectCookieSeed, 553 AppProtectCPUThresholds: config.MainAppProtectCPUThresholds, 554 AppProtectPhysicalMemoryThresholds: config.MainAppProtectPhysicalMemoryThresholds, 555 InternalRouteServer: staticCfgParams.EnableInternalRoutes, 556 InternalRouteServerName: staticCfgParams.PodName, 557 LatencyMetrics: staticCfgParams.EnableLatencyMetrics, 558 PreviewPolicies: staticCfgParams.EnablePreviewPolicies, 559 } 560 return nginxCfg 561 }