From f7780150ea938370c356f20e9e3ff8d863ac2da3 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Thu, 18 Jul 2024 19:20:52 -0300 Subject: [PATCH 01/16] Bootstrap initial crossplane work (#11653) * Bootstrap initial crossplane work * Disable some tests to speed up stuff --- .golangci.yml | 1 - go.mod | 2 + go.sum | 10 + go.work.sum | 121 +----------- images/kube-webhook-certgen/rootfs/go.mod | 6 +- images/kube-webhook-certgen/rootfs/go.sum | 12 +- .../controller/template/crossplane/config.go | 38 ++++ .../template/crossplane/crossplane.go | 70 +++++++ .../crossplane/crossplane_internal_test.go | 90 +++++++++ .../crossplane_internal_utils_test.go | 58 ++++++ .../template/crossplane/crossplane_test.go | 28 +++ .../controller/template/crossplane/events.go | 36 ++++ .../controller/template/crossplane/http.go | 187 ++++++++++++++++++ .../controller/template/crossplane/utils.go | 100 ++++++++++ magefiles/go.mod | 14 +- magefiles/go.sum | 54 ++--- 16 files changed, 650 insertions(+), 177 deletions(-) create mode 100644 internal/ingress/controller/template/crossplane/config.go create mode 100644 internal/ingress/controller/template/crossplane/crossplane.go create mode 100644 internal/ingress/controller/template/crossplane/crossplane_internal_test.go create mode 100644 internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go create mode 100644 internal/ingress/controller/template/crossplane/crossplane_test.go create mode 100644 internal/ingress/controller/template/crossplane/events.go create mode 100644 internal/ingress/controller/template/crossplane/http.go create mode 100644 internal/ingress/controller/template/crossplane/utils.go diff --git a/.golangci.yml b/.golangci.yml index 2d73e14e77..afbe3b8251 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,7 +25,6 @@ linters: - ginkgolinter - gocheckcompilerdirectives - goconst - - gocritic - gocyclo - godox - gofmt diff --git a/go.mod b/go.mod index 8826fb0d2b..70577d3b7a 100644 --- a/go.mod +++ b/go.mod @@ -48,8 +48,10 @@ require ( require ( github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/jstemmer/go-junit-report v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/moby/sys/userns v0.1.0 // indirect + github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 // indirect github.com/x448/float16 v0.8.4 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/release-utils v0.8.3 // indirect diff --git a/go.sum b/go.sum index 174d9074e8..13405bda60 100644 --- a/go.sum +++ b/go.sum @@ -107,6 +107,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v1.0.0 h1:8X1gzZpR+nVQLAht+L/foqOeX2l9DTZoaIPbEQHxsds= +github.com/jstemmer/go-junit-report v1.0.0/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -129,6 +131,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM= +github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= @@ -158,6 +162,10 @@ github.com/ncabatoff/go-seq v0.0.0-20180805175032-b08ef85ed833 h1:t4WWQ9I797y7QU github.com/ncabatoff/go-seq v0.0.0-20180805175032-b08ef85ed833/go.mod h1:0CznHmXSjMEqs5Tezj/w2emQoM41wzYM9KpDKUHPYag= github.com/ncabatoff/process-exporter v0.8.4 h1:qj0pWbP6AytVQ1fMYabRd5LnuV6NPh0O6WCfenPJT54= github.com/ncabatoff/process-exporter v0.8.4/go.mod h1:MxEOWl740VK/hlWycJkq91VrA2mI+U9Bvc1wuyAaxA4= +github.com/ncabatoff/process-exporter v0.8.3 h1:ZJpzWhRfwdBisIpr2BkitAlUR6dt45hpQn8/AYgToO8= +github.com/ncabatoff/process-exporter v0.8.3/go.mod h1:MxEOWl740VK/hlWycJkq91VrA2mI+U9Bvc1wuyAaxA4= +github.com/nginxinc/nginx-go-crossplane v0.4.63 h1:nx5e+EXzPepWVM3YsTEhcs8kp8XDTK1BCzPTTmdgK1E= +github.com/nginxinc/nginx-go-crossplane v0.4.63/go.mod h1:b7L/JSru3rvbbxVJxBgkePkNvC+LXo/IWE4iJJJvUUw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -193,6 +201,8 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= diff --git a/go.work.sum b/go.work.sum index 06d0a1ab92..655b6a542b 100644 --- a/go.work.sum +++ b/go.work.sum @@ -559,7 +559,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOC github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9 h1:7kQgkwGRoLzC9K0oyXdJo7nve/bynv/KwUsxbiTlzAM= @@ -610,11 +609,7 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= @@ -690,12 +685,7 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= @@ -742,10 +732,6 @@ github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -753,36 +739,6 @@ github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= -github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE= github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -837,9 +793,6 @@ github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85 github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncabatoff/fakescraper v0.0.0-20201102132415-4b37ba603d65 h1:Og+dVkxEQNvRGU2vUKeOwYT2UJ+pEaDMWB6tIQnIh6A= github.com/ncabatoff/fakescraper v0.0.0-20201102132415-4b37ba603d65/go.mod h1:Tx6UMSMyIsjLG/VU/F6xA1+0XI+/f9o1dGJnf1l+bPg= @@ -867,14 +820,6 @@ github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0 github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= -github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= -github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= -github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= -github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= -github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -893,7 +838,6 @@ github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ai github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -1023,15 +967,9 @@ golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGb golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= @@ -1044,11 +982,9 @@ golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCA golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1058,45 +994,20 @@ golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/I golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= -gonum.org/v1/plot v0.10.1 h1:dnifSs43YJuNMDzB7v8wV64O4ABBHReuAVAoBxqBqS4= -google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o= -google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= -google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= -google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk= -google.golang.org/api v0.162.0/go.mod h1:6SulDkfoBIg4NFmCuZ39XeeAgSHCPecfSUuDyYlAHs0= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:CCviP9RmpZ1mxVr8MUjCnSiY09IbAXZxhLE6EhHIdPU= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405/go.mod h1:3WDQMjmJk36UQhjQ89emUzb1mdaHcPeeAh4SCBKznB4= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= -google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= @@ -1171,29 +1082,5 @@ k8s.io/kms v0.31.0/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= k8s.io/kms v0.31.2/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg= -modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/libc v1.17.1 h1:Q8/Cpi36V/QBfuQaFVeisEBs3WqoGAJprZzmf7TfEYI= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/memory v1.2.1 h1:dkRh86wgmq/bJu2cAS2oqBCz/KsMZU7TUM4CibQ7eBs= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/sqlite v1.18.1 h1:ko32eKt3jf7eqIkCgPAeHMBXw3riNSLhl2f3loEF7o8= -modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= -modernc.org/tcl v1.13.1 h1:npxzTwFTZYM8ghWicVIX1cRWzj7Nd8i6AqqX2p+IYao= -modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= -modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= -rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= -rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/images/kube-webhook-certgen/rootfs/go.mod b/images/kube-webhook-certgen/rootfs/go.mod index 4efc9c6d3e..c6dfc7e8cd 100644 --- a/images/kube-webhook-certgen/rootfs/go.mod +++ b/images/kube-webhook-certgen/rootfs/go.mod @@ -17,9 +17,9 @@ require ( github.com/emicklei/go-restful/v3 v3.11.3 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/swag v0.22.9 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect diff --git a/images/kube-webhook-certgen/rootfs/go.sum b/images/kube-webhook-certgen/rootfs/go.sum index fae381cc43..04b52a1205 100644 --- a/images/kube-webhook-certgen/rootfs/go.sum +++ b/images/kube-webhook-certgen/rootfs/go.sum @@ -9,12 +9,12 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= diff --git a/internal/ingress/controller/template/crossplane/config.go b/internal/ingress/controller/template/crossplane/config.go new file mode 100644 index 0000000000..007bdf1a82 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/config.go @@ -0,0 +1,38 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" +) + +func (c *crossplaneTemplate) buildConfig() { + // Write basic directives + config := &ngx_crossplane.Config{ + Parsed: ngx_crossplane.Directives{ + buildDirective("pid", c.tplConfig.PID), + buildDirective("daemon", "off"), + buildDirective("worker_processes", c.tplConfig.Cfg.WorkerProcesses), + buildDirective("worker_rlimit_nofile", c.tplConfig.Cfg.MaxWorkerOpenFiles), + buildDirective("worker_shutdown_timeout", c.tplConfig.Cfg.WorkerShutdownTimeout), + }, + } + if c.tplConfig.Cfg.WorkerCPUAffinity != "" { + config.Parsed = append(config.Parsed, buildDirective("worker_cpu_affinity", c.tplConfig.Cfg.WorkerCPUAffinity)) + } + c.config = config +} diff --git a/internal/ingress/controller/template/crossplane/crossplane.go b/internal/ingress/controller/template/crossplane/crossplane.go new file mode 100644 index 0000000000..c674cc6fe7 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/crossplane.go @@ -0,0 +1,70 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "bytes" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + + "k8s.io/ingress-nginx/internal/ingress/controller/config" +) + +/* +Unsupported directives: +- opentelemetry +- modsecurity +- any stream directive (TCP/UDP forwarding) +- geoip2 +*/ + +// On this case we will try to use the go ngx_crossplane to write the template instead of the template renderer + +type crossplaneTemplate struct { + options *ngx_crossplane.BuildOptions + config *ngx_crossplane.Config + tplConfig *config.TemplateConfig +} + +func NewCrossplaneTemplate() *crossplaneTemplate { + lua := ngx_crossplane.Lua{} + return &crossplaneTemplate{ + options: &ngx_crossplane.BuildOptions{ + Builders: []ngx_crossplane.RegisterBuilder{ + lua.RegisterBuilder(), + }, + }, + } +} + +func (c *crossplaneTemplate) Write(conf *config.TemplateConfig) ([]byte, error) { + c.tplConfig = conf + + // build root directives + c.buildConfig() + + // build events directive + c.buildEvents() + + // build http directive + c.buildHTTP() + + var buf bytes.Buffer + + err := ngx_crossplane.Build(&buf, *c.config, &ngx_crossplane.BuildOptions{}) + return buf.Bytes(), err +} diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go new file mode 100644 index 0000000000..6479b197eb --- /dev/null +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go @@ -0,0 +1,90 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "testing" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + "github.com/stretchr/testify/require" + + "k8s.io/ingress-nginx/internal/ingress/controller/config" +) + +// THIS FILE SHOULD BE USED JUST FOR INTERNAL TESTS - Private functions + +func Test_Internal_buildEvents(t *testing.T) { + t.Run("should fill correctly events directives with defaults", func(t *testing.T) { + c := ngx_crossplane.Config{} + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } + + expectedEvents := &ngx_crossplane.Config{ + File: "", + Parsed: ngx_crossplane.Directives{ + { + Directive: "events", + Block: ngx_crossplane.Directives{ + buildDirective("worker_connections", 16384), + buildDirective("use", "epool"), + buildDirective("multi_accept", true), + }, + }, + }, + } + + cplane := NewCrossplaneTemplate() + cplane.config = &c + cplane.tplConfig = tplConfig + cplane.buildEvents() + require.Equal(t, expectedEvents, cplane.config) + }) + + t.Run("should fill correctly events directives with specific values", func(t *testing.T) { + c := ngx_crossplane.Config{} + tplConfig := &config.TemplateConfig{ + Cfg: config.Configuration{ + MaxWorkerConnections: 50, + EnableMultiAccept: false, + DebugConnections: []string{"127.0.0.1/32", "192.168.0.10"}, + }, + } + + expectedEvents := &ngx_crossplane.Config{ + File: "", + Parsed: ngx_crossplane.Directives{ + { + Directive: "events", + Block: ngx_crossplane.Directives{ + buildDirective("worker_connections", 50), + buildDirective("use", "epool"), + buildDirective("multi_accept", false), + buildDirective("debug_connection", "127.0.0.1/32"), + buildDirective("debug_connection", "192.168.0.10"), + }, + }, + }, + } + + cplane := NewCrossplaneTemplate() + cplane.config = &c + cplane.tplConfig = tplConfig + cplane.buildEvents() + require.Equal(t, expectedEvents, cplane.config) + }) +} diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go new file mode 100644 index 0000000000..e9ac966918 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go @@ -0,0 +1,58 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/ingress-nginx/internal/ingress/controller/config" +) + +// THIS FILE SHOULD BE USED JUST FOR INTERNAL TESTS - Private functions + +func Test_Internal_buildDirectives(t *testing.T) { + t.Run("should be able to run a directive with a single argument", func(t *testing.T) { + directive := buildDirective("somedirective", "bla") + require.Equal(t, directive.Directive, "somedirective", []string{"bla"}) + }) + t.Run("should be able to run a directive with multiple different arguments", func(t *testing.T) { + directive := buildDirective("somedirective", "bla", 5, true, seconds(10), []string{"xpto", "bla"}) + require.Equal(t, directive.Directive, "somedirective", []string{"bla", "5", "on", "10s", "xpto", "bla"}) + }) +} + +func Test_Internal_boolToStr(t *testing.T) { + require.Equal(t, boolToStr(true), "on") + require.Equal(t, boolToStr(false), "off") +} + +func Test_Internal_buildLuaDictionaries(t *testing.T) { + t.Skip("Maps are not sorted, need to fix this") + cfg := &config.Configuration{ + LuaSharedDicts: map[string]int{ + "somedict": 1024, + "otherdict": 1025, + }, + } + directives := buildLuaSharedDictionaries(cfg) + require.Len(t, directives, 2) + require.Equal(t, "lua_shared_dict", directives[0].Directive) + require.Equal(t, []string{"somedict", "1M"}, directives[0].Args) + require.Equal(t, "lua_shared_dict", directives[1].Directive) + require.Equal(t, []string{"otherdict", "1025K"}, directives[1].Args) +} diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go new file mode 100644 index 0000000000..bc83cc79ac --- /dev/null +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -0,0 +1,28 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane_test + +import "testing" + +// TestCrossplaneTemplate should be a roundtrip test. +// We should initialize the scenarios based on the template configuration +// Then Parse and write a crossplane configuration, and roundtrip/parse back to check +// if the directives matches +// we should ignore line numbers and comments +func TestCrossplaneTemplate(t *testing.T) { + // implement +} diff --git a/internal/ingress/controller/template/crossplane/events.go b/internal/ingress/controller/template/crossplane/events.go new file mode 100644 index 0000000000..179358a5f8 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/events.go @@ -0,0 +1,36 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" +) + +func (c *crossplaneTemplate) buildEvents() { + events := &ngx_crossplane.Directive{ + Directive: "events", + Block: ngx_crossplane.Directives{ + buildDirective("worker_connections", c.tplConfig.Cfg.MaxWorkerConnections), + buildDirective("use", "epool"), + buildDirective("multi_accept", c.tplConfig.Cfg.EnableMultiAccept), + }, + } + for k := range c.tplConfig.Cfg.DebugConnections { + events.Block = append(events.Block, buildDirective("debug_connection", c.tplConfig.Cfg.DebugConnections[k])) + } + c.config.Parsed = append(c.config.Parsed, events) +} diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go new file mode 100644 index 0000000000..a8343d9966 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/http.go @@ -0,0 +1,187 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + "strconv" + "strings" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" +) + +func (c *crossplaneTemplate) initHTTPDirectives() ngx_crossplane.Directives { + cfg := c.tplConfig.Cfg + httpBlock := ngx_crossplane.Directives{ + buildDirective("lua_package_path", "/etc/nginx/lua/?.lua;;"), + buildDirective("include", "/etc/nginx/mime.types"), + buildDirective("default_type", cfg.DefaultType), + buildDirective("real_ip_recursive", "on"), + buildDirective("aio", "threads"), + buildDirective("aio_write", cfg.EnableAioWrite), + buildDirective("server_tokens", cfg.ShowServerTokens), + buildDirective("resolver", buildResolversInternal(cfg.Resolver, cfg.DisableIpv6DNS)), + buildDirective("tcp_nopush", "on"), + buildDirective("tcp_nodelay", "on"), + buildDirective("log_subrequest", "on"), + buildDirective("reset_timedout_connection", "on"), + buildDirective("keepalive_timeout", seconds(cfg.KeepAlive)), + buildDirective("keepalive_requests", cfg.KeepAliveRequests), + buildDirective("client_body_temp_path", "/tmp/nginx/client-body"), + buildDirective("fastcgi_temp_path", "/tmp/nginx/fastcgi-temp"), + buildDirective("proxy_temp_path", "/tmp/nginx/proxy-temp"), + buildDirective("client_header_buffer_size", cfg.ClientHeaderBufferSize), + buildDirective("client_header_timeout", seconds(cfg.ClientHeaderTimeout)), + buildDirective("large_client_header_buffers", cfg.LargeClientHeaderBuffers), + buildDirective("client_body_buffer_size", cfg.ClientBodyBufferSize), + buildDirective("client_body_timeout", seconds(cfg.ClientBodyTimeout)), + buildDirective("types_hash_max_size", "2048"), + buildDirective("server_names_hash_max_size", cfg.ServerNameHashMaxSize), + buildDirective("server_names_hash_bucket_size", cfg.ServerNameHashBucketSize), + buildDirective("map_hash_bucket_size", cfg.MapHashBucketSize), + buildDirective("proxy_headers_hash_max_size", cfg.ProxyHeadersHashMaxSize), + buildDirective("proxy_headers_hash_bucket_size", cfg.ProxyHeadersHashBucketSize), + buildDirective("variables_hash_bucket_size", cfg.VariablesHashBucketSize), + buildDirective("variables_hash_max_size", cfg.VariablesHashMaxSize), + buildDirective("underscores_in_headers", cfg.EnableUnderscoresInHeaders), + buildDirective("ignore_invalid_headers", cfg.IgnoreInvalidHeaders), + buildDirective("limit_req_status", cfg.LimitReqStatusCode), + buildDirective("limit_conn_status", cfg.LimitConnStatusCode), + buildDirective("uninitialized_variable_warn", "off"), + buildDirective("server_name_in_redirect", "off"), + buildDirective("port_in_redirect", "off"), + buildDirective("ssl_protocols", strings.Split(cfg.SSLProtocols, " ")), + buildDirective("ssl_early_data", cfg.SSLEarlyData), + buildDirective("ssl_session_tickets", cfg.SSLSessionTickets), + buildDirective("ssl_buffer_size", cfg.SSLBufferSize), + buildDirective("ssl_ecdh_curve", cfg.SSLECDHCurve), + buildDirective("ssl_certificate", cfg.DefaultSSLCertificate.PemFileName), + buildDirective("ssl_certificate_key", cfg.DefaultSSLCertificate.PemFileName), + buildDirective("proxy_ssl_session_reuse", "on"), + buildDirective("proxy_cache_path", []string{ + "/tmp/nginx/nginx-cache-auth", "levels=1:2", "keys_zone=auth_cache:10m", + "max_size=128m", "inactive=30m", "use_temp_path=off", + }), + } + return httpBlock +} + +func (c *crossplaneTemplate) buildHTTP() { + cfg := c.tplConfig.Cfg + httpBlock := c.initHTTPDirectives() + httpBlock = append(httpBlock, buildLuaSharedDictionaries(&c.tplConfig.Cfg)...) + + // Real IP dealing + if (cfg.UseForwardedHeaders || cfg.UseProxyProtocol) || cfg.EnableRealIP { + if cfg.UseProxyProtocol { + httpBlock = append(httpBlock, buildDirective("real_ip_header", "proxy_protocol")) + } else { + httpBlock = append(httpBlock, buildDirective("real_ip_header", cfg.ForwardedForHeader)) + } + + for k := range cfg.ProxyRealIPCIDR { + httpBlock = append(httpBlock, buildDirective("set_real_ip_from", cfg.ProxyRealIPCIDR[k])) + } + } + + if cfg.GRPCBufferSizeKb > 0 { + httpBlock = append(httpBlock, buildDirective("grpc_buffer_size", strconv.Itoa(cfg.GRPCBufferSizeKb)+"k")) + } + + // HTTP2 Configuration + if cfg.HTTP2MaxHeaderSize != "" && cfg.HTTP2MaxFieldSize != "" { + httpBlock = append(httpBlock, buildDirective("http2_max_field_size", cfg.HTTP2MaxFieldSize)) + httpBlock = append(httpBlock, buildDirective("http2_max_header_size", cfg.HTTP2MaxHeaderSize)) + if cfg.HTTP2MaxRequests > 0 { + httpBlock = append(httpBlock, buildDirective("http2_max_requests", cfg.HTTP2MaxRequests)) + } + } + + if cfg.UseGzip { + httpBlock = append(httpBlock, buildDirective("gzip", "on")) + httpBlock = append(httpBlock, buildDirective("gzip_comp_level", cfg.GzipLevel)) + httpBlock = append(httpBlock, buildDirective("gzip_http_version", "1.1")) + httpBlock = append(httpBlock, buildDirective("gzip_min_length", cfg.GzipMinLength)) + httpBlock = append(httpBlock, buildDirective("gzip_types", cfg.GzipTypes)) + httpBlock = append(httpBlock, buildDirective("gzip_proxied", "any")) + httpBlock = append(httpBlock, buildDirective("gzip_vary", "on")) + + if cfg.GzipDisable != "" { + httpBlock = append(httpBlock, buildDirective("gzip_disable", strings.Split(cfg.GzipDisable, ""))) + } + } + + if !cfg.ShowServerTokens { + httpBlock = append(httpBlock, buildDirective("more_clear_headers", "Server")) + } + + if len(c.tplConfig.AddHeaders) > 0 { + additionalHeaders := make([]string, 0) + for headerName, headerValue := range c.tplConfig.AddHeaders { + additionalHeaders = append(additionalHeaders, fmt.Sprintf("%s: %s", headerName, headerValue)) + } + httpBlock = append(httpBlock, buildDirective("more_set_headers", additionalHeaders)) + } + + escape := "" + if cfg.LogFormatEscapeNone { + escape = "escape=none" + } else if cfg.LogFormatEscapeJSON { + escape = "escape=json" + } + + httpBlock = append(httpBlock, buildDirective("log_format", "upstreaminfo", escape, cfg.LogFormatUpstream)) + + // buildMap directive + mapLogDirective := &ngx_crossplane.Directive{ + Directive: "map", + Args: []string{"$request_uri", "$loggable"}, + Block: make(ngx_crossplane.Directives, 0), + } + for k := range cfg.SkipAccessLogURLs { + mapLogDirective.Block = append(mapLogDirective.Block, buildDirective(cfg.SkipAccessLogURLs[k], "0")) + } + mapLogDirective.Block = append(mapLogDirective.Block, buildDirective("default", "1")) + httpBlock = append(httpBlock, mapLogDirective) + // end of build mapLog + + if cfg.DisableAccessLog || cfg.DisableHTTPAccessLog { + httpBlock = append(httpBlock, buildDirective("access_log", "off")) + } else { + logDirectives := []string{"upstreaminfo", "if=$loggable"} + if cfg.EnableSyslog { + httpBlock = append(httpBlock, buildDirective("access_log", fmt.Sprintf("syslog:server%s:%d", cfg.SyslogHost, cfg.SyslogPort), logDirectives)) + } else { + accessLog := cfg.AccessLogPath + if cfg.HTTPAccessLogPath != "" { + accessLog = cfg.HTTPAccessLogPath + } + httpBlock = append(httpBlock, buildDirective("access_log", accessLog, logDirectives)) + } + } + + if cfg.EnableSyslog { + httpBlock = append(httpBlock, buildDirective("error_log", fmt.Sprintf("syslog:server%s:%d", cfg.SyslogHost, cfg.SyslogPort), cfg.ErrorLogLevel)) + } else { + httpBlock = append(httpBlock, buildDirective("error_log", cfg.ErrorLogPath, cfg.ErrorLogLevel)) + } + + c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ + Directive: "http", + Block: httpBlock, + }) +} diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go new file mode 100644 index 0000000000..8c07b61c28 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -0,0 +1,100 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + "net" + "strconv" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + + "k8s.io/ingress-nginx/internal/ingress/controller/config" + ing_net "k8s.io/ingress-nginx/internal/net" +) + +type seconds int + +func buildDirective(directive string, args ...any) *ngx_crossplane.Directive { + argsVal := make([]string, 0) + for k := range args { + switch v := args[k].(type) { + case string: + argsVal = append(argsVal, v) + case []string: + argsVal = append(argsVal, v...) + case int: + argsVal = append(argsVal, strconv.Itoa(v)) + case bool: + argsVal = append(argsVal, boolToStr(v)) + case seconds: + argsVal = append(argsVal, strconv.Itoa(int(v))+"s") + } + } + return &ngx_crossplane.Directive{ + Directive: directive, + Args: argsVal, + } +} + +func buildLuaSharedDictionaries(cfg *config.Configuration) []*ngx_crossplane.Directive { + out := make([]*ngx_crossplane.Directive, 0, len(cfg.LuaSharedDicts)) + for name, size := range cfg.LuaSharedDicts { + sizeStr := dictKbToStr(size) + out = append(out, buildDirective("lua_shared_dict", name, sizeStr)) + } + + return out +} + +// TODO: The utils below should be moved to a level where they can be consumed by any template writer + +// buildResolvers returns the resolvers reading the /etc/resolv.conf file +func buildResolversInternal(res []net.IP, disableIpv6 bool) []string { + r := make([]string, 0) + for _, ns := range res { + if ing_net.IsIPV6(ns) { + if disableIpv6 { + continue + } + r = append(r, fmt.Sprintf("[%s]", ns)) + } else { + r = append(r, ns.String()) + } + } + r = append(r, "valid=30s") + + if disableIpv6 { + r = append(r, "ipv6=off") + } + + return r +} + +func boolToStr(b bool) string { + if b { + return "on" + } + return "off" +} + +func dictKbToStr(size int) string { + if size%1024 == 0 { + return fmt.Sprintf("%dM", size/1024) + } + return fmt.Sprintf("%dK", size) +} diff --git a/magefiles/go.mod b/magefiles/go.mod index 64f18e43d2..ae3732ea7d 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -8,7 +8,7 @@ require ( github.com/helm/helm v2.17.0+incompatible github.com/magefile/mage v1.15.0 github.com/vmware-labs/yaml-jsonpath v0.3.2 - golang.org/x/oauth2 v0.18.0 + golang.org/x/oauth2 v0.22.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -24,15 +24,13 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/gomega v1.30.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/onsi/gomega v1.34.1 // indirect github.com/sergi/go-diff v1.3.1 // indirect - github.com/stretchr/testify v1.9.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/net v0.28.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.29.3 // indirect + k8s.io/apimachinery v0.31.0 // indirect k8s.io/helm v2.17.0+incompatible // indirect ) diff --git a/magefiles/go.sum b/magefiles/go.sum index 16bc8460fa..9e3b9d2783 100644 --- a/magefiles/go.sum +++ b/magefiles/go.sum @@ -8,8 +8,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 h1:aRd8M7HJVZOqn/vhOzrGcQH0lNAMkqMn+pXUYkatmcA= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -28,15 +28,12 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE= @@ -67,12 +64,10 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= @@ -84,30 +79,22 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -116,41 +103,25 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -168,7 +139,6 @@ gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= k8s.io/helm v2.17.0+incompatible h1:Bpn6o1wKLYqKM3+Osh8e+1/K2g/GsQJ4F4yNF2+deao= k8s.io/helm v2.17.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= From 0e7a583942570dee65f11431a78995d5de8c321a Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Sun, 21 Jul 2024 21:12:21 -0300 Subject: [PATCH 02/16] Add crossplane test and more directives (#11670) * Add roundtrip test * Add more directives and fix lint --- .../controller/template/crossplane/config.go | 10 +- .../template/crossplane/crossplane.go | 14 +- .../crossplane/crossplane_internal_test.go | 4 +- .../crossplane_internal_utils_test.go | 11 + .../template/crossplane/crossplane_test.go | 65 +- .../controller/template/crossplane/events.go | 2 +- .../controller/template/crossplane/http.go | 98 +- .../template/crossplane/testdata/README.md | 8 + .../template/crossplane/testdata/nginx.tmpl | 1250 +++++++++++++++++ .../controller/template/crossplane/utils.go | 9 + 10 files changed, 1445 insertions(+), 26 deletions(-) create mode 100644 internal/ingress/controller/template/crossplane/testdata/README.md create mode 100644 internal/ingress/controller/template/crossplane/testdata/nginx.tmpl diff --git a/internal/ingress/controller/template/crossplane/config.go b/internal/ingress/controller/template/crossplane/config.go index 007bdf1a82..369ce2fb3b 100644 --- a/internal/ingress/controller/template/crossplane/config.go +++ b/internal/ingress/controller/template/crossplane/config.go @@ -20,7 +20,7 @@ import ( ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" ) -func (c *crossplaneTemplate) buildConfig() { +func (c *Template) buildConfig() { // Write basic directives config := &ngx_crossplane.Config{ Parsed: ngx_crossplane.Directives{ @@ -34,5 +34,13 @@ func (c *crossplaneTemplate) buildConfig() { if c.tplConfig.Cfg.WorkerCPUAffinity != "" { config.Parsed = append(config.Parsed, buildDirective("worker_cpu_affinity", c.tplConfig.Cfg.WorkerCPUAffinity)) } + + if c.tplConfig.Cfg.EnableBrotli { + config.Parsed = append(config.Parsed, + buildDirective("load_module", "/etc/nginx/modules/ngx_http_brotli_filter_module.so"), + buildDirective("load_module", "/etc/nginx/modules/ngx_http_brotli_static_module.so"), + ) + } + c.config = config } diff --git a/internal/ingress/controller/template/crossplane/crossplane.go b/internal/ingress/controller/template/crossplane/crossplane.go index c674cc6fe7..1307de2f7a 100644 --- a/internal/ingress/controller/template/crossplane/crossplane.go +++ b/internal/ingress/controller/template/crossplane/crossplane.go @@ -34,15 +34,17 @@ Unsupported directives: // On this case we will try to use the go ngx_crossplane to write the template instead of the template renderer -type crossplaneTemplate struct { +type Template struct { options *ngx_crossplane.BuildOptions config *ngx_crossplane.Config tplConfig *config.TemplateConfig + mimeFile string } -func NewCrossplaneTemplate() *crossplaneTemplate { +func NewTemplate() *Template { lua := ngx_crossplane.Lua{} - return &crossplaneTemplate{ + return &Template{ + mimeFile: "/etc/nginx/mime.types", options: &ngx_crossplane.BuildOptions{ Builders: []ngx_crossplane.RegisterBuilder{ lua.RegisterBuilder(), @@ -51,7 +53,11 @@ func NewCrossplaneTemplate() *crossplaneTemplate { } } -func (c *crossplaneTemplate) Write(conf *config.TemplateConfig) ([]byte, error) { +func (c *Template) SetMimeFile(file string) { + c.mimeFile = file +} + +func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) { c.tplConfig = conf // build root directives diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go index 6479b197eb..b8bc3258d0 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_internal_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go @@ -48,7 +48,7 @@ func Test_Internal_buildEvents(t *testing.T) { }, } - cplane := NewCrossplaneTemplate() + cplane := NewTemplate() cplane.config = &c cplane.tplConfig = tplConfig cplane.buildEvents() @@ -81,7 +81,7 @@ func Test_Internal_buildEvents(t *testing.T) { }, } - cplane := NewCrossplaneTemplate() + cplane := NewTemplate() cplane.config = &c cplane.tplConfig = tplConfig cplane.buildEvents() diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go index e9ac966918..f31701781d 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go @@ -19,6 +19,7 @@ package crossplane import ( "testing" + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" "github.com/stretchr/testify/require" "k8s.io/ingress-nginx/internal/ingress/controller/config" ) @@ -36,6 +37,16 @@ func Test_Internal_buildDirectives(t *testing.T) { }) } +func Test_Internal_buildMapDirectives(t *testing.T) { + t.Run("should be able to run build a map directive with empty block", func(t *testing.T) { + directive := buildMapDirective("somedirective", "bla", ngx_crossplane.Directives{buildDirective("something", "otherstuff")}) + require.Equal(t, directive.Directive, "map") + require.Equal(t, directive.Args, []string{"somedirective", "bla"}) + require.Equal(t, directive.Block[0].Directive, "something") + require.Equal(t, directive.Block[0].Args, []string{"otherstuff"}) + }) +} + func Test_Internal_boolToStr(t *testing.T) { require.Equal(t, boolToStr(true), "on") require.Equal(t, boolToStr(false), "off") diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index bc83cc79ac..9b6b2fa9a5 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -16,13 +16,72 @@ limitations under the License. package crossplane_test -import "testing" +import ( + "os" + "testing" -// TestCrossplaneTemplate should be a roundtrip test. + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + "github.com/stretchr/testify/require" + + "k8s.io/ingress-nginx/internal/ingress/controller/config" + "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane" + "k8s.io/ingress-nginx/pkg/apis/ingress" +) + +const mockMimeTypes = ` +types { + text/html html htm shtml; + text/css css; + text/xml xml; +} +` + +// TestTemplate should be a roundtrip test. // We should initialize the scenarios based on the template configuration // Then Parse and write a crossplane configuration, and roundtrip/parse back to check // if the directives matches // we should ignore line numbers and comments func TestCrossplaneTemplate(t *testing.T) { - // implement + lua := ngx_crossplane.Lua{} + options := ngx_crossplane.ParseOptions{ + ErrorOnUnknownDirectives: true, + StopParsingOnError: true, + IgnoreDirectives: []string{"more_clear_headers"}, + DirectiveSources: []ngx_crossplane.MatchFunc{ngx_crossplane.DefaultDirectivesMatchFunc, ngx_crossplane.LuaDirectivesMatchFn}, + LexOptions: ngx_crossplane.LexOptions{ + Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, + }, + } + defaultCertificate := &ingress.SSLCert{ + PemFileName: "bla.crt", + PemCertKey: "bla.key", + } + + mimeFile, err := os.CreateTemp("", "") + require.NoError(t, err) + _, err = mimeFile.WriteString(mockMimeTypes) + require.NoError(t, err) + require.NoError(t, mimeFile.Close()) + + t.Run("it should be able to marshall and unmarshall the current configuration", func(t *testing.T) { + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } + tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + tplConfig.Cfg.EnableBrotli = true + + tpl := crossplane.NewTemplate() + tpl.SetMimeFile(mimeFile.Name()) + content, err := tpl.Write(tplConfig) + require.NoError(t, err) + + tmpFile, err := os.CreateTemp("", "") + require.NoError(t, err) + _, err = tmpFile.Write(content) + require.NoError(t, err) + require.NoError(t, tmpFile.Close()) + + _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) + require.NoError(t, err) + }) } diff --git a/internal/ingress/controller/template/crossplane/events.go b/internal/ingress/controller/template/crossplane/events.go index 179358a5f8..fa0c599e5e 100644 --- a/internal/ingress/controller/template/crossplane/events.go +++ b/internal/ingress/controller/template/crossplane/events.go @@ -20,7 +20,7 @@ import ( ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" ) -func (c *crossplaneTemplate) buildEvents() { +func (c *Template) buildEvents() { events := &ngx_crossplane.Directive{ Directive: "events", Block: ngx_crossplane.Directives{ diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index a8343d9966..c8b49d8345 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -24,11 +24,11 @@ import ( ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" ) -func (c *crossplaneTemplate) initHTTPDirectives() ngx_crossplane.Directives { +func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { cfg := c.tplConfig.Cfg httpBlock := ngx_crossplane.Directives{ buildDirective("lua_package_path", "/etc/nginx/lua/?.lua;;"), - buildDirective("include", "/etc/nginx/mime.types"), + buildDirective("include", c.mimeFile), buildDirective("default_type", cfg.DefaultType), buildDirective("real_ip_recursive", "on"), buildDirective("aio", "threads"), @@ -46,7 +46,7 @@ func (c *crossplaneTemplate) initHTTPDirectives() ngx_crossplane.Directives { buildDirective("proxy_temp_path", "/tmp/nginx/proxy-temp"), buildDirective("client_header_buffer_size", cfg.ClientHeaderBufferSize), buildDirective("client_header_timeout", seconds(cfg.ClientHeaderTimeout)), - buildDirective("large_client_header_buffers", cfg.LargeClientHeaderBuffers), + buildDirective("large_client_header_buffers", strings.Split(cfg.LargeClientHeaderBuffers, " ")), buildDirective("client_body_buffer_size", cfg.ClientBodyBufferSize), buildDirective("client_body_timeout", seconds(cfg.ClientBodyTimeout)), buildDirective("types_hash_max_size", "2048"), @@ -64,6 +64,7 @@ func (c *crossplaneTemplate) initHTTPDirectives() ngx_crossplane.Directives { buildDirective("uninitialized_variable_warn", "off"), buildDirective("server_name_in_redirect", "off"), buildDirective("port_in_redirect", "off"), + buildDirective("http2_max_concurrent_streams", cfg.HTTP2MaxConcurrentStreams), buildDirective("ssl_protocols", strings.Split(cfg.SSLProtocols, " ")), buildDirective("ssl_early_data", cfg.SSLEarlyData), buildDirective("ssl_session_tickets", cfg.SSLSessionTickets), @@ -80,7 +81,7 @@ func (c *crossplaneTemplate) initHTTPDirectives() ngx_crossplane.Directives { return httpBlock } -func (c *crossplaneTemplate) buildHTTP() { +func (c *Template) buildHTTP() { cfg := c.tplConfig.Cfg httpBlock := c.initHTTPDirectives() httpBlock = append(httpBlock, buildLuaSharedDictionaries(&c.tplConfig.Cfg)...) @@ -121,7 +122,7 @@ func (c *crossplaneTemplate) buildHTTP() { httpBlock = append(httpBlock, buildDirective("gzip_vary", "on")) if cfg.GzipDisable != "" { - httpBlock = append(httpBlock, buildDirective("gzip_disable", strings.Split(cfg.GzipDisable, ""))) + httpBlock = append(httpBlock, buildDirective("gzip_disable", strings.Split(cfg.GzipDisable, " "))) } } @@ -146,18 +147,12 @@ func (c *crossplaneTemplate) buildHTTP() { httpBlock = append(httpBlock, buildDirective("log_format", "upstreaminfo", escape, cfg.LogFormatUpstream)) - // buildMap directive - mapLogDirective := &ngx_crossplane.Directive{ - Directive: "map", - Args: []string{"$request_uri", "$loggable"}, - Block: make(ngx_crossplane.Directives, 0), - } + loggableMap := make(ngx_crossplane.Directives, 0) for k := range cfg.SkipAccessLogURLs { - mapLogDirective.Block = append(mapLogDirective.Block, buildDirective(cfg.SkipAccessLogURLs[k], "0")) + loggableMap = append(loggableMap, buildDirective(cfg.SkipAccessLogURLs[k], "0")) } - mapLogDirective.Block = append(mapLogDirective.Block, buildDirective("default", "1")) - httpBlock = append(httpBlock, mapLogDirective) - // end of build mapLog + loggableMap = append(loggableMap, buildDirective("default", "1")) + httpBlock = append(httpBlock, buildMapDirective("$request_uri", "$loggable", loggableMap)) if cfg.DisableAccessLog || cfg.DisableHTTPAccessLog { httpBlock = append(httpBlock, buildDirective("access_log", "off")) @@ -180,6 +175,79 @@ func (c *crossplaneTemplate) buildHTTP() { httpBlock = append(httpBlock, buildDirective("error_log", cfg.ErrorLogPath, cfg.ErrorLogLevel)) } + if cfg.SSLSessionCache { + httpBlock = append(httpBlock, + buildDirective("ssl_session_cache", fmt.Sprintf("shared:SSL:%s", cfg.SSLSessionCacheSize)), + buildDirective("ssl_session_timeout", cfg.SSLSessionTimeout), + ) + } + + if cfg.SSLSessionTicketKey != "" { + httpBlock = append(httpBlock, buildDirective("ssl_session_ticket_key", "/etc/ingress-controller/tickets.key")) + } + + if cfg.SSLCiphers != "" { + httpBlock = append(httpBlock, + buildDirective("ssl_ciphers", cfg.SSLCiphers), + buildDirective("ssl_prefer_server_ciphers", "on"), + ) + } + + if cfg.SSLDHParam != "" { + httpBlock = append(httpBlock, buildDirective("ssl_dhparam", cfg.SSLDHParam)) + } + + if len(cfg.CustomHTTPErrors) > 0 && !cfg.DisableProxyInterceptErrors { + httpBlock = append(httpBlock, buildDirective("proxy_intercept_errors", "on")) + } + + httpUpgradeMap := ngx_crossplane.Directives{buildDirective("default", "upgrade")} + if cfg.UpstreamKeepaliveConnections < 1 { + httpUpgradeMap = append(httpUpgradeMap, buildDirective("", "close")) + } + httpBlock = append(httpBlock, buildMapDirective("$http_upgrade", "$connection_upgrade", httpUpgradeMap)) + + reqIDMap := ngx_crossplane.Directives{buildDirective("default", "$http_x_request_id")} + if cfg.GenerateRequestID { + reqIDMap = append(reqIDMap, buildDirective("", "$request_id")) + } + httpBlock = append(httpBlock, buildMapDirective("$http_x_request_id", "$req_id", reqIDMap)) + + if cfg.UseForwardedHeaders && cfg.ComputeFullForwardedFor { + forwardForMap := make(ngx_crossplane.Directives, 0) + if cfg.UseProxyProtocol { + forwardForMap = append(forwardForMap, + buildDirective("default", "$http_x_forwarded_for, $proxy_protocol_addr"), + buildDirective("", "$http_x_forwarded_for, $proxy_protocol_addr"), + ) + } else { + forwardForMap = append(forwardForMap, + buildDirective("default", "$http_x_forwarded_for, $realip_remote_addr"), + buildDirective("", "$realip_remote_addr"), + ) + } + httpBlock = append(httpBlock, buildMapDirective("$http_x_forwarded_for", "$full_x_forwarded_for", forwardForMap)) + } + + if cfg.AllowBackendServerHeader { + httpBlock = append(httpBlock, buildDirective("proxy_pass_header", "Server")) + } + + if cfg.EnableBrotli { + httpBlock = append(httpBlock, + buildDirective("brotli", "on"), + buildDirective("brotli_comp_level", cfg.BrotliLevel), + buildDirective("brotli_min_length", cfg.BrotliMinLength), + buildDirective("brotli_types", cfg.BrotliTypes), + ) + } + + if len(cfg.HideHeaders) > 0 { + for k := range cfg.HideHeaders { + httpBlock = append(httpBlock, buildDirective("proxy_hide_header", cfg.HideHeaders[k])) + } + } + c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ Directive: "http", Block: httpBlock, diff --git a/internal/ingress/controller/template/crossplane/testdata/README.md b/internal/ingress/controller/template/crossplane/testdata/README.md new file mode 100644 index 0000000000..4f44e3c98e --- /dev/null +++ b/internal/ingress/controller/template/crossplane/testdata/README.md @@ -0,0 +1,8 @@ +This directory contains the following files: + +* nginx.tmpl - Should be used to track migrated directives. We will test later to see +if the ending result of it is the same as the one parsed by go-crossplane +* various nginx.conf - Will be used to see if the template parser reacts as +expected, creating files that matches and can be parsed by go-crossplane + +TODO: move files to embed.FS \ No newline at end of file diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl new file mode 100644 index 0000000000..cf9d200065 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl @@ -0,0 +1,1250 @@ +{{ $all := . }} +{{ $servers := .Servers }} +{{ $cfg := .Cfg }} +{{ $IsIPV6Enabled := .IsIPV6Enabled }} +{{ $healthzURI := .HealthzURI }} +{{ $backends := .Backends }} +{{ $proxyHeaders := .ProxySetHeaders }} +{{ $addHeaders := .AddHeaders }} + +# MIGRATED +pid {{ .PID }}; + +# MODULES ARE NOT MIGRATED YET! +{{ if $cfg.EnableBrotli }} +load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; +load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; +{{ end }} + +{{ if (shouldLoadAuthDigestModule $servers) }} +load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; +{{ end }} + +{{ if (shouldLoadOpentelemetryModule $cfg $servers) }} +load_module /etc/nginx/modules/otel_ngx_module.so; +{{ end }} + +# MIGRATED 1 +daemon off; + +worker_processes {{ $cfg.WorkerProcesses }}; +{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} +worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; +{{ end }} + +worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; + +{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} +{{/* avoid waiting too long during a reload */}} +worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; + +events { + multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; + worker_connections {{ $cfg.MaxWorkerConnections }}; + use epoll; + {{ range $index , $v := $cfg.DebugConnections }} + debug_connection {{ $v }}; + {{ end }} +} + +# END MIGRATED 1 + +http { + {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} + opentelemetry_config {{ $cfg.OpentelemetryConfig }}; + {{ end }} + + # MIGRATED + lua_package_path "/etc/nginx/lua/?.lua;;"; + + # MIGRATED + {{ buildLuaSharedDictionaries $cfg $servers }} + + # NOT MIGRATED + init_by_lua_block { + collectgarbage("collect") + + -- init modules + local ok, res + + ok, res = pcall(require, "lua_ingress") + if not ok then + error("require failed: " .. tostring(res)) + else + lua_ingress = res + lua_ingress.set_config({{ configForLua $all }}) + end + + ok, res = pcall(require, "configuration") + if not ok then + error("require failed: " .. tostring(res)) + else + configuration = res + configuration.prohibited_localhost_port = '{{ .StatusPort }}' + end + + ok, res = pcall(require, "balancer") + if not ok then + error("require failed: " .. tostring(res)) + else + balancer = res + end + + {{ if $all.EnableMetrics }} + ok, res = pcall(require, "monitor") + if not ok then + error("require failed: " .. tostring(res)) + else + monitor = res + end + {{ end }} + + ok, res = pcall(require, "certificate") + if not ok then + error("require failed: " .. tostring(res)) + else + certificate = res + certificate.is_ocsp_stapling_enabled = {{ $cfg.EnableOCSP }} + end + + ok, res = pcall(require, "plugins") + if not ok then + error("require failed: " .. tostring(res)) + else + plugins = res + end + -- load all plugins that'll be used here + plugins.init({ {{ range $idx, $plugin := $cfg.Plugins }}{{ if $idx }},{{ end }}{{ $plugin | quote }}{{ end }} }) + } + + init_worker_by_lua_block { + lua_ingress.init_worker() + balancer.init_worker() + {{ if $all.EnableMetrics }} + monitor.init_worker({{ $all.MonitorMaxBatchSize }}) + {{ end }} + + plugins.run() + } + + # MIGRATED VARIOUS 1 + {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} + {{/* we use the value of the real IP for the geo_ip module */}} + {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} + {{ if $cfg.UseProxyProtocol }} + real_ip_header proxy_protocol; + {{ else }} + real_ip_header {{ $cfg.ForwardedForHeader }}; + {{ end }} + + real_ip_recursive on; + {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} + set_real_ip_from {{ $trusted_ip }}; + {{ end }} + {{ end }} + + aio threads; + + {{ if $cfg.EnableAioWrite }} + aio_write on; + {{ end }} + + tcp_nopush on; + tcp_nodelay on; + + log_subrequest on; + + reset_timedout_connection on; + + keepalive_timeout {{ $cfg.KeepAlive }}s; + keepalive_requests {{ $cfg.KeepAliveRequests }}; + + client_body_temp_path /tmp/nginx/client-body; + fastcgi_temp_path /tmp/nginx/fastcgi-temp; + proxy_temp_path /tmp/nginx/proxy-temp; + + client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; + client_header_timeout {{ $cfg.ClientHeaderTimeout }}s; + large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; + client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; + client_body_timeout {{ $cfg.ClientBodyTimeout }}s; + + {{ if gt $cfg.GRPCBufferSizeKb 0 }} + grpc_buffer_size {{ $cfg.GRPCBufferSizeKb }}k; + {{ end }} + + {{ if and (ne $cfg.HTTP2MaxHeaderSize "") (ne $cfg.HTTP2MaxFieldSize "") }} + http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; + http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; + {{ end }} + + {{ if (gt $cfg.HTTP2MaxRequests 0) }} + http2_max_requests {{ $cfg.HTTP2MaxRequests }}; + {{ end }} + + http2_max_concurrent_streams {{ $cfg.HTTP2MaxConcurrentStreams }}; + + types_hash_max_size 2048; + server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; + server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; + map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; + + proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }}; + proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }}; + + variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; + variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; + + underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; + ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; + + limit_req_status {{ $cfg.LimitReqStatusCode }}; + limit_conn_status {{ $cfg.LimitConnStatusCode }}; + + include /etc/nginx/mime.types; + default_type {{ $cfg.DefaultType }}; + + {{ if $cfg.UseGzip }} + gzip on; + gzip_comp_level {{ $cfg.GzipLevel }}; + {{- if $cfg.GzipDisable }} + gzip_disable "{{ $cfg.GzipDisable }}"; + {{- end }} + gzip_http_version 1.1; + gzip_min_length {{ $cfg.GzipMinLength}}; + gzip_types {{ $cfg.GzipTypes }}; + gzip_proxied any; + gzip_vary on; + {{ end }} + + # Custom headers for response + {{ range $k, $v := $addHeaders }} + more_set_headers {{ printf "%s: %s" $k $v | quote }}; + {{ end }} + + server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; + {{ if not $cfg.ShowServerTokens }} + more_clear_headers Server; + {{ end }} + + # disable warnings + uninitialized_variable_warn off; + + # Additional available variables: + # $namespace + # $ingress_name + # $service_name + # $service_port + log_format upstreaminfo {{ if $cfg.LogFormatEscapeNone }}escape=none {{ else if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ $cfg.LogFormatUpstream }}'; + + {{/* map urls that should not appear in access.log */}} + {{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} + map $request_uri $loggable { + {{ range $reqUri := $cfg.SkipAccessLogURLs }} + {{ $reqUri }} 0;{{ end }} + default 1; + } + + {{ if or $cfg.DisableAccessLog $cfg.DisableHTTPAccessLog }} + access_log off; + {{ else }} + {{ if $cfg.EnableSyslog }} + access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable; + {{ else }} + access_log {{ or $cfg.HTTPAccessLogPath $cfg.AccessLogPath }} upstreaminfo {{ $cfg.AccessLogParams }} if=$loggable; + {{ end }} + {{ end }} + + {{ if $cfg.EnableSyslog }} + error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }}; + {{ else }} + error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; + {{ end }} + + {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} + + server_name_in_redirect off; + port_in_redirect off; + + ssl_protocols {{ $cfg.SSLProtocols }}; + + ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; + + # allow configuring ssl session tickets + ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; + + # slightly reduce the time-to-first-byte + ssl_buffer_size {{ $cfg.SSLBufferSize }}; + + ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; + # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} + ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; + ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; + + proxy_ssl_session_reuse on; + + # See https://www.nginx.com/blog/websocket-nginx + map $http_upgrade $connection_upgrade { + default upgrade; + {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} + # See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive + '' ''; + {{ else }} + '' close; + {{ end }} + } + + # Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server. + # If no such header is provided, it can provide a random value. + map $http_x_request_id $req_id { + default $http_x_request_id; + {{ if $cfg.GenerateRequestID }} + "" $request_id; + {{ end }} + } + + # Cache for internal auth checks + proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; + + {{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} + # We can't use $proxy_add_x_forwarded_for because the realip module + # replaces the remote_addr too soon + map $http_x_forwarded_for $full_x_forwarded_for { + {{ if $all.Cfg.UseProxyProtocol }} + default "$http_x_forwarded_for, $proxy_protocol_addr"; + '' "$proxy_protocol_addr"; + {{ else }} + default "$http_x_forwarded_for, $realip_remote_addr"; + '' "$realip_remote_addr"; + {{ end}} + } + + {{ end }} + + # turn on session caching to drastically improve performance + {{ if $cfg.SSLSessionCache }} + ssl_session_cache shared:SSL:{{ $cfg.SSLSessionCacheSize }}; + ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; + {{ end }} + + {{ if not (empty $cfg.SSLSessionTicketKey ) }} + ssl_session_ticket_key /etc/ingress-controller/tickets.key; + {{ end }} + + {{ if not (empty $cfg.SSLCiphers) }} + # allow configuring custom ssl ciphers + ssl_ciphers '{{ $cfg.SSLCiphers }}'; + ssl_prefer_server_ciphers on; + {{ end }} + + {{ if not (empty $cfg.SSLDHParam) }} + # allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam + ssl_dhparam {{ $cfg.SSLDHParam }}; + {{ end }} + + {{ if and $cfg.CustomHTTPErrors (not $cfg.DisableProxyInterceptErrors) }} + proxy_intercept_errors on; + {{ end }} + + {{ if $cfg.EnableBrotli }} + brotli on; + brotli_comp_level {{ $cfg.BrotliLevel }}; + brotli_min_length {{ $cfg.BrotliMinLength }}; + brotli_types {{ $cfg.BrotliTypes }}; + {{ end }} + + {{ if $cfg.AllowBackendServerHeader }} + proxy_pass_header Server; + {{ end }} + + {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; + {{ end }} + + # END MIGRATED VARIOUS 1 + + {{ buildOpentelemetry $cfg $servers }} + + # Create a variable that contains the literal $ character. + # This works because the geo module will not resolve variables. + geo $literal_dollar { + default "$"; + } + + {{ range $errCode := $cfg.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} + + upstream upstream_balancer { + server 0.0.0.1; # placeholder + + balancer_by_lua_block { + balancer.balance() + } + + {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} + keepalive {{ $cfg.UpstreamKeepaliveConnections }}; + keepalive_time {{ $cfg.UpstreamKeepaliveTime }}; + keepalive_timeout {{ $cfg.UpstreamKeepaliveTimeout }}s; + keepalive_requests {{ $cfg.UpstreamKeepaliveRequests }}; + {{ end }} + } + + {{ range $rl := (filterRateLimits $servers ) }} + # Ratelimit {{ $rl.Name }} + geo $remote_addr $allowlist_{{ $rl.ID }} { + default 0; + {{ range $ip := $rl.Allowlist }} + {{ $ip }} 1;{{ end }} + } + + # Ratelimit {{ $rl.Name }} + map $allowlist_{{ $rl.ID }} $limit_{{ $rl.ID }} { + 0 {{ $cfg.LimitConnZoneVariable }}; + 1 ""; + } + {{ end }} + + {{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} + {{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} + {{ range $zone := (buildRateLimitZones $servers) }} + {{ $zone }} + {{ end }} + + # Global filters + {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; + {{ end }} + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + map $http_user_agent $block_ua { + default 0; + + {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; + {{ end }} + } + {{ end }} + + {{ if gt (len $cfg.BlockReferers) 0 }} + map $http_referer $block_ref { + default 0; + + {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; + {{ end }} + } + {{ end }} + + {{/* Build server redirects (from/to www) */}} + {{ range $redirect := .RedirectServers }} + ## start server {{ $redirect.From }} + server { + server_name {{ $redirect.From }}; + + {{ buildHTTPListener $all $redirect.From }} + {{ buildHTTPSListener $all $redirect.From }} + + ssl_certificate_by_lua_block { + certificate.call() + } + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + if ($block_ua) { + return 403; + } + {{ end }} + {{ if gt (len $cfg.BlockReferers) 0 }} + if ($block_ref) { + return 403; + } + {{ end }} + + set_by_lua_block $redirect_to { + local request_uri = ngx.var.request_uri + if string.sub(request_uri, -1) == "/" then + request_uri = string.sub(request_uri, 1, -2) + end + + {{ if $cfg.UseForwardedHeaders }} + local redirectScheme + if not ngx.var.http_x_forwarded_proto then + redirectScheme = ngx.var.scheme + else + redirectScheme = ngx.var.http_x_forwarded_proto + end + {{ else }} + local redirectScheme = ngx.var.scheme + {{ end }} + + {{ if ne $all.ListenPorts.HTTPS 443 }} + {{ $redirect_port := (printf ":%v" $all.ListenPorts.HTTPS) }} + return string.format("%s://%s%s%s", redirectScheme, "{{ $redirect.To }}", "{{ $redirect_port }}", request_uri) + {{ else }} + return string.format("%s://%s%s", redirectScheme, "{{ $redirect.To }}", request_uri) + {{ end }} + } + + return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; + } + ## end server {{ $redirect.From }} + {{ end }} + + {{ range $server := $servers }} + {{ range $location := $server.Locations }} + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} + upstream {{ buildAuthUpstreamName $location $server.Hostname }} { + {{- $externalAuth := $location.ExternalAuth }} + server {{ extractHostPort $externalAuth.URL }}; + + keepalive {{ $externalAuth.KeepaliveConnections }}; + keepalive_requests {{ $externalAuth.KeepaliveRequests }}; + keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; + } + ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} + {{ end }} + {{ end }} + {{ end }} + + {{ range $server := $servers }} + ## start server {{ $server.Hostname }} + server { + server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; + + {{ if $cfg.UseHTTP2 }} + http2 on; + {{ end }} + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + if ($block_ua) { + return 403; + } + {{ end }} + {{ if gt (len $cfg.BlockReferers) 0 }} + if ($block_ref) { + return 403; + } + {{ end }} + + {{ template "SERVER" serverConfig $all $server }} + + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics) }} + } + ## end server {{ $server.Hostname }} + + {{ end }} + + # backend for when default-backend-service is not configured or it does not have endpoints + server { + listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; + {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} + set $proxy_upstream_name "internal"; + + access_log off; + + location / { + return 404; + } + } + + # default server, used for NGINX healthcheck and access to nginx stats + server { + listen 127.0.0.1:{{ .StatusPort }}; + set $proxy_upstream_name "internal"; + + keepalive_timeout 0; + gzip off; + + access_log off; + + {{ if $cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + location {{ $healthzURI }} { + return 200; + } + + location /is-dynamic-lb-initialized { + content_by_lua_block { + local configuration = require("configuration") + local backend_data = configuration.get_backends_data() + if not backend_data then + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) + return + end + + ngx.say("OK") + ngx.exit(ngx.HTTP_OK) + } + } + + location {{ .StatusPath }} { + stub_status on; + } + + location /configuration { + client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; + client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; + proxy_buffering off; + + content_by_lua_block { + configuration.call() + } + } + + location / { + content_by_lua_block { + ngx.exit(ngx.HTTP_NOT_FOUND) + } + } + } +} + +{{/* definition of templates to avoid repetitions */}} +{{ define "CUSTOM_ERRORS" }} + {{ $enableMetrics := .EnableMetrics }} + {{ $upstreamName := .UpstreamName }} + {{ range $errCode := .ErrorCodes }} + location @custom_{{ $upstreamName }}_{{ $errCode }} { + internal; + + proxy_intercept_errors off; + + proxy_set_header X-Code {{ $errCode }}; + proxy_set_header X-Format $http_accept; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Namespace $namespace; + proxy_set_header X-Ingress-Name $ingress_name; + proxy_set_header X-Service-Name $service_name; + proxy_set_header X-Service-Port $service_port; + proxy_set_header X-Request-ID $req_id; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $best_http_host; + + set $proxy_upstream_name {{ $upstreamName | quote }}; + + rewrite (.*) / break; + + proxy_pass http://upstream_balancer; + log_by_lua_block { + {{ if $enableMetrics }} + monitor.call() + {{ end }} + } + } + {{ end }} +{{ end }} + +{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} +{{ define "CORS" }} + {{ $cors := .CorsConfig }} + # Cors Preflight methods needs additional options and different Return Code + {{ if $cors.CorsAllowOrigin }} + {{ buildCorsOriginRegex $cors.CorsAllowOrigin }} + {{ end }} + if ($request_method = 'OPTIONS') { + set $cors ${cors}options; + } + + if ($cors = "true") { + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; + } + + if ($cors = "trueoptions") { + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; + more_set_headers 'Content-Type: text/plain charset=UTF-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } +{{ end }} + +{{/* definition of server-template to avoid repetitions with server-alias */}} +{{ define "SERVER" }} + {{ $all := .First }} + {{ $server := .Second }} + + {{ buildHTTPListener $all $server.Hostname }} + {{ buildHTTPSListener $all $server.Hostname }} + + set $proxy_upstream_name "-"; + + {{ if not ( empty $server.CertificateAuth.MatchCN ) }} + {{ if gt (len $server.CertificateAuth.MatchCN) 0 }} + if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { + return 403 "client certificate unauthorized"; + } + {{ end }} + {{ end }} + + {{ if eq $server.Hostname "_" }} + ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; + {{ end }} + + ssl_certificate_by_lua_block { + certificate.call() + } + + {{ if not (empty $server.AuthTLSError) }} + # {{ $server.AuthTLSError }} + return 403; + {{ else }} + + {{ if not (empty $server.CertificateAuth.CAFileName) }} + # PEM sha: {{ $server.CertificateAuth.CASHA }} + ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; + ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; + ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; + + {{ if not (empty $server.CertificateAuth.CRLFileName) }} + # PEM sha: {{ $server.CertificateAuth.CRLSHA }} + ssl_crl {{ $server.CertificateAuth.CRLFileName }}; + {{ end }} + + {{ if not (empty $server.CertificateAuth.ErrorPage)}} + error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; + {{ end }} + {{ end }} + + {{ if not (empty $server.ProxySSL.CAFileName) }} + # PEM sha: {{ $server.ProxySSL.CASHA }} + proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; + proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; + proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; + proxy_ssl_verify {{ $server.ProxySSL.Verify }}; + proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; + {{ if not (empty $server.ProxySSL.ProxySSLName) }} + proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; + proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; + {{ end }} + {{ end }} + + {{ if not (empty $server.ProxySSL.PemFileName) }} + proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; + proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; + {{ end }} + + {{ if not (empty $server.SSLCiphers) }} + ssl_ciphers {{ $server.SSLCiphers }}; + {{ end }} + + {{ if not (empty $server.SSLPreferServerCiphers) }} + ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; + {{ end }} + + {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics) }} + {{ end }} + + {{ buildMirrorLocations $server.Locations }} + + {{ $enforceRegex := enforceRegexModifier $server.Locations }} + {{ range $location := $server.Locations }} + {{ $path := buildLocation $location $enforceRegex }} + {{ $proxySetHeader := proxySetHeader $location }} + {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + + {{ $externalAuth := $location.ExternalAuth }} + {{ if eq $applyGlobalAuth true }} + {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} + {{ end }} + + {{ if not (empty $location.Rewrite.AppRoot) }} + if ($uri = /) { + return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; + } + {{ end }} + + {{ if $authPath }} + location = {{ $authPath }} { + internal; + + {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} + opentelemetry on; + opentelemetry_propagate; + {{ end }} + + {{ if not $all.Cfg.EnableAuthAccessLog }} + access_log off; + {{ end }} + + {{ if $externalAuth.AuthCacheKey }} + set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; + set $cache_key ''; + + rewrite_by_lua_block { + ngx.var.cache_key = ngx.encode_base64(ngx.sha1_bin(ngx.var.tmp_cache_key)) + } + + proxy_cache auth_cache; + + {{- range $dur := $externalAuth.AuthCacheDuration }} + proxy_cache_valid {{ $dur }}; + {{- end }} + + proxy_cache_key "$cache_key"; + {{ end }} + + # ngx_auth_request module overrides variables in the parent request, + # therefore we have to explicitly set this variable again so that when the parent request + # resumes it has the correct value set for this variable so that Lua can pick backend correctly + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; + + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Forwarded-Proto ""; + proxy_set_header X-Request-ID $req_id; + + {{ if $externalAuth.Method }} + proxy_method {{ $externalAuth.Method }}; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Scheme $pass_access_scheme; + {{ end }} + + proxy_set_header Host {{ $externalAuth.Host }}; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Original-Method $request_method; + proxy_set_header X-Sent-From "nginx-ingress-controller"; + proxy_set_header X-Real-IP $remote_addr; + {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} + proxy_set_header X-Forwarded-For $full_x_forwarded_for; + {{ else }} + proxy_set_header X-Forwarded-For $remote_addr; + {{ end }} + + {{ if $externalAuth.RequestRedirect }} + proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; + {{ else }} + proxy_set_header X-Auth-Request-Redirect $request_uri; + {{ end }} + + {{ if $externalAuth.AuthCacheKey }} + proxy_buffering "on"; + {{ else }} + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; + {{ end }} + proxy_buffer_size {{ $location.Proxy.BufferSize }}; + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + + proxy_ssl_server_name on; + proxy_pass_request_headers on; + {{ if isValidByteSize $location.Proxy.BodySize true }} + client_max_body_size {{ $location.Proxy.BodySize }}; + {{ end }} + {{ if isValidByteSize $location.ClientBodyBufferSize false }} + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; + {{ end }} + + # Pass the extracted client certificate to the auth provider + {{ if not (empty $server.CertificateAuth.CAFileName) }} + {{ if $server.CertificateAuth.PassCertToUpstream }} + proxy_set_header ssl-client-cert $ssl_client_escaped_cert; + {{ end }} + proxy_set_header ssl-client-verify $ssl_client_verify; + proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; + proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; + {{ end }} + + {{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} + {{ $line }} + {{- end }} + + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} + # The target is an upstream with HTTP keepalive, that is why the + # Connection header is cleared and the HTTP version is set to 1.1 as + # the Nginx documentation suggests: + # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive + proxy_http_version 1.1; + proxy_set_header Connection ""; + set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; + {{ else }} + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; + set $target {{ $externalAuth.URL }}; + {{ end }} + proxy_pass $target; + } + {{ end }} + + {{ if isLocationAllowed $location }} + {{ if $externalAuth.SigninURL }} + location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { + internal; + + add_header Set-Cookie $auth_cookie; + + {{ if $location.CorsConfig.CorsEnabled }} + {{ template "CORS" $location }} + {{ end }} + + return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; + } + {{ end }} + {{ end }} + + location {{ $path }} { + {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} + set $namespace {{ $ing.Namespace | quote}}; + set $ingress_name {{ $ing.Rule | quote }}; + set $service_name {{ $ing.Service | quote }}; + set $service_port {{ $ing.ServicePort | quote }}; + set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; + set $global_rate_limit_exceeding n; + + {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} + + {{ if $location.Mirror.Source }} + mirror {{ $location.Mirror.Source }}; + mirror_request_body {{ $location.Mirror.RequestBody }}; + {{ end }} + + rewrite_by_lua_block { + lua_ingress.rewrite({{ locationConfigForLua $location $all }}) + balancer.rewrite() + plugins.run() + } + + # be careful with `access_by_lua_block` and `satisfy any` directives as satisfy any + # will always succeed when there's `access_by_lua_block` that does not have any lua code doing `ngx.exit(ngx.DECLINED)` + # other authentication method such as basic auth or external auth useless - all requests will be allowed. + #access_by_lua_block { + #} + + header_filter_by_lua_block { + lua_ingress.header() + plugins.run() + } + + body_filter_by_lua_block { + plugins.run() + } + + log_by_lua_block { + balancer.log() + {{ if $all.EnableMetrics }} + monitor.call() + {{ end }} + + plugins.run() + } + + {{ if not $location.Logs.Access }} + access_log off; + {{ end }} + + {{ if $location.Logs.Rewrite }} + rewrite_log on; + {{ end }} + + {{ if $location.HTTP2PushPreload }} + http2_push_preload on; + {{ end }} + + port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; + + set $balancer_ewma_score -1; + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; + set $proxy_host $proxy_upstream_name; + set $pass_access_scheme $scheme; + + {{ if $all.Cfg.UseProxyProtocol }} + set $pass_server_port $proxy_protocol_server_port; + {{ else }} + set $pass_server_port $server_port; + {{ end }} + + set $best_http_host $http_host; + set $pass_port $pass_server_port; + + set $proxy_alternative_upstream_name ""; + + {{ if isLocationAllowed $location }} + {{ if gt (len $location.Denylist.CIDR) 0 }} + {{ range $ip := $location.Denylist.CIDR }} + deny {{ $ip }};{{ end }} + {{ end }} + {{ if gt (len $location.Allowlist.CIDR) 0 }} + {{ range $ip := $location.Allowlist.CIDR }} + allow {{ $ip }};{{ end }} + deny all; + {{ end }} + + {{ if $location.CorsConfig.CorsEnabled }} + {{ template "CORS" $location }} + {{ end }} + + {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} + {{ if $authPath }} + # this location requires authentication + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + set $auth_cookie ''; + add_header Set-Cookie $auth_cookie; + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} + {{ $line }} + {{- end }} + # `auth_request` module does not support HTTP keepalives in upstream block: + # https://trac.nginx.org/nginx/ticket/1579 + access_by_lua_block { + local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) + if res.status == ngx.HTTP_OK then + ngx.var.auth_cookie = res.header['Set-Cookie'] + {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} + {{ $line }} + {{- end }} + return + end + if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then + ngx.exit(res.status) + end + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) + } + {{ else }} + auth_request {{ $authPath }}; + auth_request_set $auth_cookie $upstream_http_set_cookie; + {{ if $externalAuth.AlwaysSetCookie }} + add_header Set-Cookie $auth_cookie always; + {{ else }} + add_header Set-Cookie $auth_cookie; + {{ end }} + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} + {{ $line }} + {{- end }} + {{ end }} + {{ end }} + + {{ if $externalAuth.SigninURL }} + set_escape_uri $escaped_request_uri $request_uri; + error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; + {{ end }} + + {{ if $location.BasicDigestAuth.Secured }} + {{ if eq $location.BasicDigestAuth.Type "basic" }} + auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; + auth_basic_user_file {{ $location.BasicDigestAuth.File }}; + {{ else }} + auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; + auth_digest_user_file {{ $location.BasicDigestAuth.File }}; + {{ end }} + {{ $proxySetHeader }} Authorization ""; + {{ end }} + {{ end }} + + {{/* if the location contains a rate limit annotation, create one */}} + {{ $limits := buildRateLimit $location }} + {{ range $limit := $limits }} + {{ $limit }}{{ end }} + + {{ if isValidByteSize $location.Proxy.BodySize true }} + client_max_body_size {{ $location.Proxy.BodySize }}; + {{ end }} + {{ if isValidByteSize $location.ClientBodyBufferSize false }} + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; + {{ end }} + + {{/* By default use vhost as Host to upstream, but allow overrides */}} + {{ if not (empty $location.UpstreamVhost) }} + {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; + {{ else }} + {{ $proxySetHeader }} Host $best_http_host; + {{ end }} + + # Pass the extracted client certificate to the backend + {{ if not (empty $server.CertificateAuth.CAFileName) }} + {{ if $server.CertificateAuth.PassCertToUpstream }} + {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; + {{ end }} + {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; + {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; + {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; + {{ end }} + + # Allow websocket connections + {{ $proxySetHeader }} Upgrade $http_upgrade; + {{ if $location.Connection.Enabled}} + {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; + {{ else }} + {{ $proxySetHeader }} Connection $connection_upgrade; + {{ end }} + + {{ $proxySetHeader }} X-Request-ID $req_id; + {{ $proxySetHeader }} X-Real-IP $remote_addr; + {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} + {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; + {{ else }} + {{ $proxySetHeader }} X-Forwarded-For $remote_addr; + {{ end }} + {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; + {{ $proxySetHeader }} X-Forwarded-Port $pass_port; + {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; + {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; + {{ if $all.Cfg.ProxyAddOriginalURIHeader }} + {{ $proxySetHeader }} X-Original-URI $request_uri; + {{ end }} + {{ $proxySetHeader }} X-Scheme $pass_access_scheme; + + # Pass the original X-Forwarded-For + {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; + + # mitigate HTTPoxy Vulnerability + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ + {{ $proxySetHeader }} Proxy ""; + + # Custom headers to proxied server + {{ range $k, $v := $all.ProxySetHeaders }} + {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; + {{ end }} + + proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; + proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; + proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; + + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; + proxy_buffer_size {{ $location.Proxy.BufferSize }}; + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; + {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} + proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; + {{ end }} + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; + + proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; + proxy_cookie_path {{ $location.Proxy.CookiePath }}; + + # In case of errors try the next upstream server before returning an error + proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; + proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; + + {{ if or (eq $location.BackendProtocol "GRPC") (eq $location.BackendProtocol "GRPCS") }} + # Grpc settings + grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; + grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; + grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; + {{ end }} + + {{ if $location.CustomHeaders }} + # Custom Response Headers + {{ range $k, $v := $location.CustomHeaders.Headers }} + more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; + {{ end }} + {{ end }} + + {{/* if we are sending the request to a custom default backend, we add the required headers */}} + {{ if (hasPrefix $location.Backend "custom-default-backend-") }} + proxy_set_header X-Code 503; + proxy_set_header X-Format $http_accept; + proxy_set_header X-Namespace $namespace; + proxy_set_header X-Ingress-Name $ingress_name; + proxy_set_header X-Service-Name $service_name; + proxy_set_header X-Service-Port $service_port; + proxy_set_header X-Request-ID $req_id; + {{ end }} + + {{ if $location.Satisfy }} + satisfy {{ $location.Satisfy }}; + {{ end }} + + {{/* if a location-specific error override is set, add the proxy_intercept here */}} + {{ if and $location.CustomHTTPErrors (not $location.DisableProxyInterceptErrors) }} + # Custom error pages per ingress + proxy_intercept_errors on; + {{ end }} + + {{ range $errCode := $location.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} + + {{ if (eq $location.BackendProtocol "FCGI") }} + include /etc/nginx/fastcgi_params; + {{ end }} + {{- if $location.FastCGI.Index -}} + fastcgi_index {{ $location.FastCGI.Index | quote }}; + {{- end -}} + {{ range $k, $v := $location.FastCGI.Params }} + fastcgi_param {{ $k }} {{ $v | quote }}; + {{ end }} + + {{ if not (empty $location.Redirect.URL) }} + return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; + {{ end }} + + {{ buildProxyPass $server.Hostname $all.Backends $location }} + {{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; + {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; + {{ end }} + {{ else }} + # Location denied. Reason: {{ $location.Denied | quote }} + return 503; + {{ end }} + {{ if not (empty $location.ProxySSL.CAFileName) }} + # PEM sha: {{ $location.ProxySSL.CASHA }} + proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; + proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; + proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; + proxy_ssl_verify {{ $location.ProxySSL.Verify }}; + proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; + {{ end }} + + {{ if not (empty $location.ProxySSL.ProxySSLName) }} + proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; + {{ end }} + {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} + proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; + {{ end }} + + {{ if not (empty $location.ProxySSL.PemFileName) }} + proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; + proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; + {{ end }} + } + {{ end }} + {{ end }} + + {{ if eq $server.Hostname "_" }} + # health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} + location {{ $all.HealthzURI }} { + + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + + access_log off; + return 200; + } + + # this is required to avoid error if nginx is being monitored + # with an external software (like sysdig) + location /nginx_status { + + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + + {{ range $v := $all.NginxStatusIpv4Whitelist }} + allow {{ $v }}; + {{ end }} + {{ if $all.IsIPV6Enabled -}} + {{ range $v := $all.NginxStatusIpv6Whitelist }} + allow {{ $v }}; + {{ end }} + {{ end -}} + deny all; + + access_log off; + stub_status on; + } + + {{ end }} + +{{ end }} diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index 8c07b61c28..437a59ef5c 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -85,6 +85,15 @@ func buildResolversInternal(res []net.IP, disableIpv6 bool) []string { return r } +// buildMapDirective is used to build a map directive +func buildMapDirective(name, variable string, block ngx_crossplane.Directives) *ngx_crossplane.Directive { + return &ngx_crossplane.Directive{ + Directive: "map", + Args: []string{name, variable}, + Block: block, + } +} + func boolToStr(b bool) string { if b { return "on" From bf7815823d0e74ebdb19404a3978e9a12d7c3e96 Mon Sep 17 00:00:00 2001 From: Erlison Santos <98214640+MrErlison@users.noreply.github.com> Date: Fri, 26 Jul 2024 20:02:57 -0300 Subject: [PATCH 03/16] Fix move nested if statement (#11688) --- internal/ingress/controller/template/crossplane/http.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index c8b49d8345..f5f39e1d51 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -107,9 +107,10 @@ func (c *Template) buildHTTP() { if cfg.HTTP2MaxHeaderSize != "" && cfg.HTTP2MaxFieldSize != "" { httpBlock = append(httpBlock, buildDirective("http2_max_field_size", cfg.HTTP2MaxFieldSize)) httpBlock = append(httpBlock, buildDirective("http2_max_header_size", cfg.HTTP2MaxHeaderSize)) - if cfg.HTTP2MaxRequests > 0 { - httpBlock = append(httpBlock, buildDirective("http2_max_requests", cfg.HTTP2MaxRequests)) - } + } + + if cfg.HTTP2MaxRequests > 0 { + httpBlock = append(httpBlock, buildDirective("http2_max_requests", cfg.HTTP2MaxRequests)) } if cfg.UseGzip { From 8f1c772081ed3187c4516961d11bb134cf30a95d Mon Sep 17 00:00:00 2001 From: Erlison Santos <98214640+MrErlison@users.noreply.github.com> Date: Fri, 26 Jul 2024 20:08:22 -0300 Subject: [PATCH 04/16] Add tests for tags with custom values (#11686) * Add tests for tags with custom values * Fix typo in comments --- .../template/crossplane/crossplane_test.go | 57 +++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 9b6b2fa9a5..71765d677f 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -63,14 +63,61 @@ func TestCrossplaneTemplate(t *testing.T) { require.NoError(t, err) require.NoError(t, mimeFile.Close()) - t.Run("it should be able to marshall and unmarshall the current configuration", func(t *testing.T) { - tplConfig := &config.TemplateConfig{ - Cfg: config.NewDefault(), - } + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } + tpl := crossplane.NewTemplate() + + t.Run("it should be able to marshall and unmarshall the default configuration", func(t *testing.T) { tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate tplConfig.Cfg.EnableBrotli = true + tplConfig.Cfg.HideHeaders = []string{"x-fake-header", "x-another-fake-header"} + + tpl.SetMimeFile(mimeFile.Name()) + content, err := tpl.Write(tplConfig) + require.NoError(t, err) + + tmpFile, err := os.CreateTemp("", "") + require.NoError(t, err) + _, err = tmpFile.Write(content) + require.NoError(t, err) + require.NoError(t, tmpFile.Close()) + + _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) + require.NoError(t, err) + }) + + t.Run("it should be able to marshall and unmarshall the specified configuration", func(t *testing.T) { + tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + + tplConfig.Cfg.UseProxyProtocol = true + + tplConfig.Cfg.GRPCBufferSizeKb = 10 // default 0 + + tplConfig.Cfg.HTTP2MaxHeaderSize = "10" // default "" + tplConfig.Cfg.HTTP2MaxFieldSize = "10" // default "" + tplConfig.Cfg.HTTP2MaxRequests = 1 // default 0 + + tplConfig.Cfg.UseGzip = true // default false + tplConfig.Cfg.GzipDisable = "enable" + + tplConfig.Cfg.ShowServerTokens = true // default false + + tplConfig.Cfg.DisableAccessLog = false // TODO: test true + tplConfig.Cfg.DisableHTTPAccessLog = false + tplConfig.Cfg.EnableSyslog = true + tplConfig.Cfg.SyslogHost = "localhost" + + // Example: openssl rand 80 | openssl enc -A -base64 + tplConfig.Cfg.SSLSessionTicketKey = "lOj3+7Xe21K9GapKqqPIw/gCQm5S4C2lK8pVne6drEik0QqOQHAw1AaPSMdbAvXx2zZKKPCEG98+g3hzftmrfnePSIvokIIE+hHto3Kj1HQ=" + + tplConfig.Cfg.CustomHTTPErrors = []int{1024, 2048} + + tplConfig.Cfg.AllowBackendServerHeader = true // default false + tplConfig.Cfg.BlockCIDRs = []string{"192.168.0.0/24", " 200.200.0.0/16 "} // default 0 + tplConfig.Cfg.BlockUserAgents = []string{"someuseragent", " another/user-agent "} // default 0 - tpl := crossplane.NewTemplate() + tpl = crossplane.NewTemplate() tpl.SetMimeFile(mimeFile.Name()) content, err := tpl.Write(tplConfig) require.NoError(t, err) From 9f8a44629e53244f5330305e32ffe704affcfac1 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Sun, 28 Jul 2024 19:19:35 -0300 Subject: [PATCH 05/16] Add brotli module parser (#11690) --- .../controller/template/crossplane/config.go | 4 +- .../template/crossplane/crossplane_test.go | 66 ++++++++++++++-- .../crossplane/extramodules/README.md | 10 +++ .../crossplane/extramodules/analyze.go | 78 +++++++++++++++++++ .../crossplane/extramodules/brotli.go | 55 +++++++++++++ 5 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 internal/ingress/controller/template/crossplane/extramodules/README.md create mode 100644 internal/ingress/controller/template/crossplane/extramodules/analyze.go create mode 100644 internal/ingress/controller/template/crossplane/extramodules/brotli.go diff --git a/internal/ingress/controller/template/crossplane/config.go b/internal/ingress/controller/template/crossplane/config.go index 369ce2fb3b..b754f55dc7 100644 --- a/internal/ingress/controller/template/crossplane/config.go +++ b/internal/ingress/controller/template/crossplane/config.go @@ -17,6 +17,8 @@ limitations under the License. package crossplane import ( + "strings" + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" ) @@ -32,7 +34,7 @@ func (c *Template) buildConfig() { }, } if c.tplConfig.Cfg.WorkerCPUAffinity != "" { - config.Parsed = append(config.Parsed, buildDirective("worker_cpu_affinity", c.tplConfig.Cfg.WorkerCPUAffinity)) + config.Parsed = append(config.Parsed, buildDirective("worker_cpu_affinity", strings.Split(c.tplConfig.Cfg.WorkerCPUAffinity, " "))) } if c.tplConfig.Cfg.EnableBrotli { diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 71765d677f..24b98f1328 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -17,6 +17,7 @@ limitations under the License. package crossplane_test import ( + "net" "os" "testing" @@ -25,6 +26,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/controller/config" "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane" + "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane/extramodules" "k8s.io/ingress-nginx/pkg/apis/ingress" ) @@ -36,6 +38,8 @@ types { } ` +var resolvers = []net.IP{net.ParseIP("::1"), net.ParseIP("192.168.20.10")} + // TestTemplate should be a roundtrip test. // We should initialize the scenarios based on the template configuration // Then Parse and write a crossplane configuration, and roundtrip/parse back to check @@ -46,8 +50,12 @@ func TestCrossplaneTemplate(t *testing.T) { options := ngx_crossplane.ParseOptions{ ErrorOnUnknownDirectives: true, StopParsingOnError: true, - IgnoreDirectives: []string{"more_clear_headers"}, - DirectiveSources: []ngx_crossplane.MatchFunc{ngx_crossplane.DefaultDirectivesMatchFunc, ngx_crossplane.LuaDirectivesMatchFn}, + IgnoreDirectives: []string{"more_clear_headers", "more_set_headers"}, // TODO: Add more_set_headers + DirectiveSources: []ngx_crossplane.MatchFunc{ + ngx_crossplane.DefaultDirectivesMatchFunc, + ngx_crossplane.LuaDirectivesMatchFn, + extramodules.BrotliMatchFn, + }, LexOptions: ngx_crossplane.LexOptions{ Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, }, @@ -63,15 +71,43 @@ func TestCrossplaneTemplate(t *testing.T) { require.NoError(t, err) require.NoError(t, mimeFile.Close()) - tplConfig := &config.TemplateConfig{ - Cfg: config.NewDefault(), - } tpl := crossplane.NewTemplate() t.Run("it should be able to marshall and unmarshall the default configuration", func(t *testing.T) { + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate tplConfig.Cfg.EnableBrotli = true tplConfig.Cfg.HideHeaders = []string{"x-fake-header", "x-another-fake-header"} + tplConfig.Cfg.Resolver = resolvers + tplConfig.Cfg.DisableIpv6DNS = true + tplConfig.Cfg.UseForwardedHeaders = true + tplConfig.Cfg.LogFormatEscapeNone = true + tplConfig.Cfg.DisableAccessLog = true + tplConfig.Cfg.UpstreamKeepaliveConnections = 0 + + tpl.SetMimeFile(mimeFile.Name()) + content, err := tpl.Write(tplConfig) + require.NoError(t, err) + + tmpFile, err := os.CreateTemp("", "") + require.NoError(t, err) + _, err = tmpFile.Write(content) + require.NoError(t, err) + require.NoError(t, tmpFile.Close()) + + _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) + require.NoError(t, err) + }) + + t.Run("it should set the right logging configs", func(t *testing.T) { + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } + tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + tplConfig.Cfg.DisableAccessLog = false + tplConfig.Cfg.HTTPAccessLogPath = "/lalala.log" tpl.SetMimeFile(mimeFile.Name()) content, err := tpl.Write(tplConfig) @@ -88,9 +124,21 @@ func TestCrossplaneTemplate(t *testing.T) { }) t.Run("it should be able to marshall and unmarshall the specified configuration", func(t *testing.T) { + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + tplConfig.Cfg.WorkerCPUAffinity = "0001 0010 0100 1000" + tplConfig.Cfg.LuaSharedDicts = map[string]int{ + "configuration_data": 10240, + "certificate_data": 50, + } + tplConfig.Cfg.Resolver = resolvers + tplConfig.Cfg.DisableIpv6DNS = false tplConfig.Cfg.UseProxyProtocol = true + tplConfig.Cfg.ProxyRealIPCIDR = []string{"192.168.0.20", "200.200.200.200"} + tplConfig.Cfg.LogFormatEscapeJSON = true tplConfig.Cfg.GRPCBufferSizeKb = 10 // default 0 @@ -107,6 +155,8 @@ func TestCrossplaneTemplate(t *testing.T) { tplConfig.Cfg.DisableHTTPAccessLog = false tplConfig.Cfg.EnableSyslog = true tplConfig.Cfg.SyslogHost = "localhost" + tplConfig.Cfg.SkipAccessLogURLs = []string{"aaa.a", "bbb.b"} + tplConfig.Cfg.SSLDHParam = "/some/dh.pem" // Example: openssl rand 80 | openssl enc -A -base64 tplConfig.Cfg.SSLSessionTicketKey = "lOj3+7Xe21K9GapKqqPIw/gCQm5S4C2lK8pVne6drEik0QqOQHAw1AaPSMdbAvXx2zZKKPCEG98+g3hzftmrfnePSIvokIIE+hHto3Kj1HQ=" @@ -117,6 +167,11 @@ func TestCrossplaneTemplate(t *testing.T) { tplConfig.Cfg.BlockCIDRs = []string{"192.168.0.0/24", " 200.200.0.0/16 "} // default 0 tplConfig.Cfg.BlockUserAgents = []string{"someuseragent", " another/user-agent "} // default 0 + tplConfig.AddHeaders = map[string]string{ + "someheader": "xpto", + "anotherheader": "blabla", + } + tpl = crossplane.NewTemplate() tpl.SetMimeFile(mimeFile.Name()) content, err := tpl.Write(tplConfig) @@ -130,5 +185,6 @@ func TestCrossplaneTemplate(t *testing.T) { _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) require.NoError(t, err) + // require.Equal(t, " ", string(content)) }) } diff --git a/internal/ingress/controller/template/crossplane/extramodules/README.md b/internal/ingress/controller/template/crossplane/extramodules/README.md new file mode 100644 index 0000000000..6bd8a4e6ba --- /dev/null +++ b/internal/ingress/controller/template/crossplane/extramodules/README.md @@ -0,0 +1,10 @@ +# Extra modules +This folder contains the extra modules used by ingress-nginx and not yet +supported by nginx-go-crossplane + +The generation of the files is done using go-crossplane generator + +## Brotli +``` +go run ./cmd/generate/ -src-path=ngx_brotli/ -directive-map-name=brotliDirectives -match-func-name=BrotliMatchFn > ../ingress-crossplane/internal/ingress/controller/template/crossplane/extramodules/brotli.go +``` \ No newline at end of file diff --git a/internal/ingress/controller/template/crossplane/extramodules/analyze.go b/internal/ingress/controller/template/crossplane/extramodules/analyze.go new file mode 100644 index 0000000000..72efe24749 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/extramodules/analyze.go @@ -0,0 +1,78 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * Copyright (c) F5, Inc. + * + * This source code is licensed under the Apache License, Version 2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +// This file is an extraction from https://github.com/nginxinc/nginx-go-crossplane/blob/main/analyze.go +// +//nolint:unused +package extramodules + +// bit masks for different directive argument styles. +const ( + ngxConfNoArgs = 0x00000001 // 0 args + ngxConfTake1 = 0x00000002 // 1 args + ngxConfTake2 = 0x00000004 // 2 args + ngxConfTake3 = 0x00000008 // 3 args + ngxConfTake4 = 0x00000010 // 4 args + ngxConfTake5 = 0x00000020 // 5 args + ngxConfTake6 = 0x00000040 // 6 args + // ngxConfTake7 = 0x00000080 // 7 args (currently unused). + ngxConfBlock = 0x00000100 // followed by block + ngxConfExpr = 0x00000200 // directive followed by expression in parentheses `()` + ngxConfFlag = 0x00000400 // 'on' or 'off' + ngxConfAny = 0x00000800 // >=0 args + ngxConf1More = 0x00001000 // >=1 args + ngxConf2More = 0x00002000 // >=2 args + + // some helpful argument style aliases. + ngxConfTake12 = ngxConfTake1 | ngxConfTake2 + ngxConfTake13 = ngxConfTake1 | ngxConfTake3 + ngxConfTake23 = ngxConfTake2 | ngxConfTake3 + ngxConfTake34 = ngxConfTake3 | ngxConfTake4 + ngxConfTake123 = ngxConfTake12 | ngxConfTake3 + ngxConfTake1234 = ngxConfTake123 | ngxConfTake4 + + // bit masks for different directive locations. + ngxDirectConf = 0x00010000 // main file (not used) + ngxMgmtMainConf = 0x00020000 // mgmt // unique bitmask that may not match NGINX source + ngxMainConf = 0x00040000 // main context + ngxEventConf = 0x00080000 // events + ngxMailMainConf = 0x00100000 // mail + ngxMailSrvConf = 0x00200000 // mail > server + ngxStreamMainConf = 0x00400000 // stream + ngxStreamSrvConf = 0x00800000 // stream > server + ngxStreamUpsConf = 0x01000000 // stream > upstream + ngxHTTPMainConf = 0x02000000 // http + ngxHTTPSrvConf = 0x04000000 // http > server + ngxHTTPLocConf = 0x08000000 // http > location + ngxHTTPUpsConf = 0x10000000 // http > upstream + ngxHTTPSifConf = 0x20000000 // http > server > if + ngxHTTPLifConf = 0x40000000 // http > location > if + ngxHTTPLmtConf = 0x80000000 // http > location > limit_except +) + +// helpful directive location alias describing "any" context +// doesn't include ngxHTTPSifConf, ngxHTTPLifConf, ngxHTTPLmtConf, or ngxMgmtMainConf. +const ngxAnyConf = ngxMainConf | ngxEventConf | ngxMailMainConf | ngxMailSrvConf | + ngxStreamMainConf | ngxStreamSrvConf | ngxStreamUpsConf | + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPUpsConf | + ngxHTTPSifConf | ngxHTTPLifConf | ngxHTTPLmtConf diff --git a/internal/ingress/controller/template/crossplane/extramodules/brotli.go b/internal/ingress/controller/template/crossplane/extramodules/brotli.go new file mode 100644 index 0000000000..0e2762f985 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/extramodules/brotli.go @@ -0,0 +1,55 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by generator; DO NOT EDIT. +// All the definitions are extracted from the source code +// Each bit mask describes these behaviors: +// - how many arguments the directive can take +// - whether or not it is a block directive +// - whether this is a flag (takes one argument that's either "on" or "off") +// - which contexts it's allowed to be in + +package extramodules + +var brotliDirectives = map[string][]uint{ + "brotli": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag, + }, + "brotli_buffers": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, + }, + "brotli_comp_level": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "brotli_min_length": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "brotli_static": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "brotli_types": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConf1More, + }, + "brotli_window": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, +} + + +func BrotliMatchFn(directive string) ([]uint, bool) { + m, ok := brotliDirectives[directive] + return m, ok +} \ No newline at end of file From 1d17c840e33d23bb7c9ecdd66c25f60c3cc0ccd6 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Sun, 28 Jul 2024 20:56:57 -0300 Subject: [PATCH 06/16] Add upstream directives and some others (#11681) --- .../template/crossplane/crossplane_test.go | 14 +++++ .../controller/template/crossplane/http.go | 37 +++++++++++- .../template/crossplane/testdata/nginx.tmpl | 59 ++++++++++--------- .../controller/template/crossplane/utils.go | 13 ++-- 4 files changed, 89 insertions(+), 34 deletions(-) diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 24b98f1328..20be1af059 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -166,12 +166,26 @@ func TestCrossplaneTemplate(t *testing.T) { tplConfig.Cfg.AllowBackendServerHeader = true // default false tplConfig.Cfg.BlockCIDRs = []string{"192.168.0.0/24", " 200.200.0.0/16 "} // default 0 tplConfig.Cfg.BlockUserAgents = []string{"someuseragent", " another/user-agent "} // default 0 + tplConfig.Cfg.BlockReferers = []string{"someref", " anotherref", "escape\nref"} tplConfig.AddHeaders = map[string]string{ "someheader": "xpto", "anotherheader": "blabla", } + tplConfig.Cfg.EnableBrotli = true + tplConfig.Cfg.BrotliLevel = 7 + tplConfig.Cfg.BrotliMinLength = 2 + tplConfig.Cfg.BrotliTypes = "application/xml+rss application/atom+xml" + + tplConfig.Cfg.HideHeaders = []string{"x-fake-header", "x-another-fake-header"} + tplConfig.Cfg.UpstreamKeepaliveConnections = 15 + + tplConfig.Cfg.UpstreamKeepaliveConnections = 200 + tplConfig.Cfg.UpstreamKeepaliveTime = "60s" + tplConfig.Cfg.UpstreamKeepaliveTimeout = 200 + tplConfig.Cfg.UpstreamKeepaliveRequests = 15 + tpl = crossplane.NewTemplate() tpl.SetMimeFile(mimeFile.Name()) content, err := tpl.Write(tplConfig) diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index f5f39e1d51..d6dd81c133 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -81,6 +81,7 @@ func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { return httpBlock } +//nolint:gocyclo func (c *Template) buildHTTP() { cfg := c.tplConfig.Cfg httpBlock := c.initHTTPDirectives() @@ -239,7 +240,7 @@ func (c *Template) buildHTTP() { buildDirective("brotli", "on"), buildDirective("brotli_comp_level", cfg.BrotliLevel), buildDirective("brotli_min_length", cfg.BrotliMinLength), - buildDirective("brotli_types", cfg.BrotliTypes), + buildDirective("brotli_types", strings.Split(cfg.BrotliTypes, " ")), ) } @@ -249,6 +250,40 @@ func (c *Template) buildHTTP() { } } + blockUpstreamDirectives := ngx_crossplane.Directives{ + buildDirective("server", "0.0.0.1"), + buildBlockDirective("balancer_by_lua_block", nil, ngx_crossplane.Directives{buildDirective("balancer.balance()")}), + } + if c.tplConfig.Cfg.UpstreamKeepaliveConnections > 0 { + blockUpstreamDirectives = append(blockUpstreamDirectives, + buildDirective("keepalive", c.tplConfig.Cfg.UpstreamKeepaliveConnections), + buildDirective("keepalive_time", c.tplConfig.Cfg.UpstreamKeepaliveTime), + buildDirective("keepalive_timeout", seconds(c.tplConfig.Cfg.UpstreamKeepaliveTimeout)), + buildDirective("keepalive_requests", c.tplConfig.Cfg.UpstreamKeepaliveRequests), + ) + } + httpBlock = append(httpBlock, buildBlockDirective("upstream", []string{"upstream_balancer"}, blockUpstreamDirectives)) + + for i := range cfg.BlockCIDRs { + httpBlock = append(httpBlock, buildDirective("deny", strings.TrimSpace(cfg.BlockCIDRs[i]))) + } + + if len(cfg.BlockUserAgents) > 0 { + uaDirectives := ngx_crossplane.Directives{buildDirective("default", 0)} + for i := range cfg.BlockUserAgents { + uaDirectives = append(uaDirectives, buildDirective(strings.TrimSpace(cfg.BlockUserAgents[i]), 1)) + } + httpBlock = append(httpBlock, buildMapDirective("$http_user_agent", "$block_ua", uaDirectives)) + } + + if len(cfg.BlockReferers) > 0 { + refDirectives := ngx_crossplane.Directives{buildDirective("default", 0)} + for i := range cfg.BlockReferers { + refDirectives = append(refDirectives, buildDirective(strings.TrimSpace(cfg.BlockReferers[i]), 1)) + } + httpBlock = append(httpBlock, buildMapDirective("$http_referer", "$block_ref", refDirectives)) + } + c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ Directive: "http", Block: httpBlock, diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl index cf9d200065..c65a400c45 100644 --- a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl +++ b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl @@ -360,18 +360,27 @@ http { {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; {{ end }} - # END MIGRATED VARIOUS 1 + # Global filters + {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; + {{ end }} - {{ buildOpentelemetry $cfg $servers }} + {{ if gt (len $cfg.BlockUserAgents) 0 }} + map $http_user_agent $block_ua { + default 0; - # Create a variable that contains the literal $ character. - # This works because the geo module will not resolve variables. - geo $literal_dollar { - default "$"; + {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; + {{ end }} } + {{ end }} - {{ range $errCode := $cfg.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} + {{ if gt (len $cfg.BlockReferers) 0 }} + map $http_referer $block_ref { + default 0; + + {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; + {{ end }} + } + {{ end }} upstream upstream_balancer { server 0.0.0.1; # placeholder @@ -388,6 +397,19 @@ http { {{ end }} } + # END MIGRATED VARIOUS 1 + + {{ buildOpentelemetry $cfg $servers }} + + # Create a variable that contains the literal $ character. + # This works because the geo module will not resolve variables. + geo $literal_dollar { + default "$"; + } + + {{ range $errCode := $cfg.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} + {{ range $rl := (filterRateLimits $servers ) }} # Ratelimit {{ $rl.Name }} geo $remote_addr $allowlist_{{ $rl.ID }} { @@ -409,27 +431,6 @@ http { {{ $zone }} {{ end }} - # Global filters - {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - map $http_user_agent $block_ua { - default 0; - - {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; - {{ end }} - } - {{ end }} - - {{ if gt (len $cfg.BlockReferers) 0 }} - map $http_referer $block_ref { - default 0; - - {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; - {{ end }} - } - {{ end }} {{/* Build server redirects (from/to www) */}} {{ range $redirect := .RedirectServers }} diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index 437a59ef5c..b10363a6fa 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -85,15 +85,20 @@ func buildResolversInternal(res []net.IP, disableIpv6 bool) []string { return r } -// buildMapDirective is used to build a map directive -func buildMapDirective(name, variable string, block ngx_crossplane.Directives) *ngx_crossplane.Directive { +// buildBlockDirective is used to build a block directive +func buildBlockDirective(blockName string, args []string, block ngx_crossplane.Directives) *ngx_crossplane.Directive { return &ngx_crossplane.Directive{ - Directive: "map", - Args: []string{name, variable}, + Directive: blockName, + Args: args, Block: block, } } +// buildMapDirective is used to build a map directive +func buildMapDirective(name, variable string, block ngx_crossplane.Directives) *ngx_crossplane.Directive { + return buildBlockDirective("map", []string{name, variable}, block) +} + func boolToStr(b bool) string { if b { return "on" From 565f4576d7a30e3f880f947ff3c9820935c23abd Mon Sep 17 00:00:00 2001 From: Erlison Santos <98214640+MrErlison@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:57:00 -0300 Subject: [PATCH 07/16] Add CustomHTTPErrors directive (#11699) * Add CustomHTTPErrors directive * Fix: Add missing '=' in error_page directive --- internal/ingress/controller/template/crossplane/http.go | 5 +++++ .../controller/template/crossplane/testdata/nginx.tmpl | 1 + 2 files changed, 6 insertions(+) diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index d6dd81c133..09d6814116 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -284,6 +284,11 @@ func (c *Template) buildHTTP() { httpBlock = append(httpBlock, buildMapDirective("$http_referer", "$block_ref", refDirectives)) } + for _, v := range cfg.CustomHTTPErrors { + httpBlock = append(httpBlock, buildDirective("error_page", v, "=", + fmt.Sprintf("@custom_upstream-default-backend_%d", v))) + } + c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ Directive: "http", Block: httpBlock, diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl index c65a400c45..ff68b1d9ae 100644 --- a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl +++ b/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl @@ -407,6 +407,7 @@ http { default "$"; } + # MIGRATED {{ range $errCode := $cfg.CustomHTTPErrors }} error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} From 1b91978647010b5a46f66db0c0b74b7f9283cc2e Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 10 Sep 2024 20:20:56 -0300 Subject: [PATCH 08/16] Continue go crossplane (#11964) --- go.mod | 3 +- go.sum | 10 +- go.work.sum | 1085 ------------- images/kube-webhook-certgen/rootfs/go.mod | 6 +- images/kube-webhook-certgen/rootfs/go.sum | 9 +- .../controller/template/crossplane/config.go | 14 + .../template/crossplane/crossplane_test.go | 2 +- .../controller/template/crossplane/http.go | 38 +- .../{nginx.tmpl => nginx-new-orig.tmpl} | 674 +++++--- .../crossplane/testdata/nginx-new.tmpl | 1419 +++++++++++++++++ .../controller/template/crossplane/utils.go | 29 + magefiles/go.mod | 15 +- magefiles/go.sum | 21 +- 13 files changed, 1957 insertions(+), 1368 deletions(-) rename internal/ingress/controller/template/crossplane/testdata/{nginx.tmpl => nginx-new-orig.tmpl} (73%) create mode 100644 internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl diff --git a/go.mod b/go.mod index 70577d3b7a..b6a7c274d8 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/moul/pb v0.0.0-20220425114252-bca18df4138c github.com/ncabatoff/process-exporter v0.8.4 + github.com/nginxinc/nginx-go-crossplane v0.4.66 github.com/onsi/ginkgo/v2 v2.21.0 github.com/opencontainers/runc v1.2.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 @@ -50,8 +51,8 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/jstemmer/go-junit-report v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect + github.com/maxbrunsfeld/counterfeiter/v6 v6.10.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect - github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 // indirect github.com/x448/float16 v0.8.4 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/release-utils v0.8.3 // indirect diff --git a/go.sum b/go.sum index 13405bda60..29e03b0209 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM= -github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= +github.com/maxbrunsfeld/counterfeiter/v6 v6.10.0 h1:9WsegDYiSKtZXru+NcOB4z7iqb00n4atjmQlyy5TRXI= +github.com/maxbrunsfeld/counterfeiter/v6 v6.10.0/go.mod h1:TeVdzh+5QB5IpWDJAU/uviXA6kOg9yXzLrrjeLKJXqY= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= @@ -162,10 +162,8 @@ github.com/ncabatoff/go-seq v0.0.0-20180805175032-b08ef85ed833 h1:t4WWQ9I797y7QU github.com/ncabatoff/go-seq v0.0.0-20180805175032-b08ef85ed833/go.mod h1:0CznHmXSjMEqs5Tezj/w2emQoM41wzYM9KpDKUHPYag= github.com/ncabatoff/process-exporter v0.8.4 h1:qj0pWbP6AytVQ1fMYabRd5LnuV6NPh0O6WCfenPJT54= github.com/ncabatoff/process-exporter v0.8.4/go.mod h1:MxEOWl740VK/hlWycJkq91VrA2mI+U9Bvc1wuyAaxA4= -github.com/ncabatoff/process-exporter v0.8.3 h1:ZJpzWhRfwdBisIpr2BkitAlUR6dt45hpQn8/AYgToO8= -github.com/ncabatoff/process-exporter v0.8.3/go.mod h1:MxEOWl740VK/hlWycJkq91VrA2mI+U9Bvc1wuyAaxA4= -github.com/nginxinc/nginx-go-crossplane v0.4.63 h1:nx5e+EXzPepWVM3YsTEhcs8kp8XDTK1BCzPTTmdgK1E= -github.com/nginxinc/nginx-go-crossplane v0.4.63/go.mod h1:b7L/JSru3rvbbxVJxBgkePkNvC+LXo/IWE4iJJJvUUw= +github.com/nginxinc/nginx-go-crossplane v0.4.66 h1:BS6ZyRTWP+ZSFZ7j0VxBdpUyuS8QRMSdU/y+EsCPY9w= +github.com/nginxinc/nginx-go-crossplane v0.4.66/go.mod h1:LgUBS07yefkK+cEjw2seernNp5Q86GG8IuNHLj1RQOo= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/go.work.sum b/go.work.sum index 655b6a542b..d1535915af 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,1086 +1 @@ -cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= -cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= -cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= -cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= -cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= -cloud.google.com/go/accessapproval v1.6.0 h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0= -cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= -cloud.google.com/go/accessapproval v1.7.4/go.mod h1:/aTEh45LzplQgFYdQdwPMR9YdX0UlhBmvB84uAmQKUc= -cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0= -cloud.google.com/go/accesscontextmanager v1.7.0 h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA= -cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= -cloud.google.com/go/accesscontextmanager v1.8.4/go.mod h1:ParU+WbMpD34s5JFEnGAnPBYAgUHozaTmDJU7aCU9+M= -cloud.google.com/go/accesscontextmanager v1.8.5/go.mod h1:TInEhcZ7V9jptGNqN3EzZ5XMhT6ijWxTGjzyETwmL0Q= -cloud.google.com/go/aiplatform v1.37.0 h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg= -cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= -cloud.google.com/go/aiplatform v1.50.0/go.mod h1:IRc2b8XAMTa9ZmfJV1BCCQbieWWvDnP1A8znyz5N7y4= -cloud.google.com/go/aiplatform v1.52.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv65IHILGA//VEU= -cloud.google.com/go/aiplatform v1.58.0/go.mod h1:pwZMGvqe0JRkI1GWSZCtnAfrR4K1bv65IHILGA//VEU= -cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM= -cloud.google.com/go/analytics v0.19.0 h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM= -cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/analytics v0.21.3/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/analytics v0.21.6/go.mod h1:eiROFQKosh4hMaNhF85Oc9WO97Cpa7RggD40e/RBy8w= -cloud.google.com/go/analytics v0.22.0/go.mod h1:eiROFQKosh4hMaNhF85Oc9WO97Cpa7RggD40e/RBy8w= -cloud.google.com/go/analytics v0.23.0/go.mod h1:YPd7Bvik3WS95KBok2gPXDqQPHy08TsCQG6CdUCb+u0= -cloud.google.com/go/apigateway v1.5.0 h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg= -cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= -cloud.google.com/go/apigateway v1.6.4/go.mod h1:0EpJlVGH5HwAN4VF4Iec8TAzGN1aQgbxAWGJsnPCGGY= -cloud.google.com/go/apigateway v1.6.5/go.mod h1:6wCwvYRckRQogyDDltpANi3zsCDl6kWi0b4Je+w2UiI= -cloud.google.com/go/apigeeconnect v1.5.0 h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA= -cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= -cloud.google.com/go/apigeeconnect v1.6.4/go.mod h1:CapQCWZ8TCjnU0d7PobxhpOdVz/OVJ2Hr/Zcuu1xFx0= -cloud.google.com/go/apigeeconnect v1.6.5/go.mod h1:MEKm3AiT7s11PqTfKE3KZluZA9O91FNysvd3E6SJ6Ow= -cloud.google.com/go/apigeeregistry v0.6.0 h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc= -cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= -cloud.google.com/go/apigeeregistry v0.8.2/go.mod h1:h4v11TDGdeXJDJvImtgK2AFVvMIgGWjSb0HRnBSjcX8= -cloud.google.com/go/apigeeregistry v0.8.3/go.mod h1:aInOWnqF4yMQx8kTjDqHNXjZGh/mxeNlAf52YqtASUs= -cloud.google.com/go/apikeys v0.6.0 h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ= -cloud.google.com/go/appengine v1.7.1 h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs= -cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= -cloud.google.com/go/appengine v1.8.4/go.mod h1:TZ24v+wXBujtkK77CXCpjZbnuTvsFNT41MUaZ28D6vg= -cloud.google.com/go/appengine v1.8.5/go.mod h1:uHBgNoGLTS5di7BvU25NFDuKa82v0qQLjyMJLuPQrVo= -cloud.google.com/go/area120 v0.7.1 h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag= -cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= -cloud.google.com/go/area120 v0.8.4/go.mod h1:jfawXjxf29wyBXr48+W+GyX/f8fflxp642D/bb9v68M= -cloud.google.com/go/area120 v0.8.5/go.mod h1:BcoFCbDLZjsfe4EkCnEq1LKvHSK0Ew/zk5UFu6GMyA0= -cloud.google.com/go/artifactregistry v1.13.0 h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8= -cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= -cloud.google.com/go/artifactregistry v1.14.6/go.mod h1:np9LSFotNWHcjnOgh8UVK0RFPCTUGbO0ve3384xyHfE= -cloud.google.com/go/artifactregistry v1.14.7/go.mod h1:0AUKhzWQzfmeTvT4SjfI4zjot72EMfrkvL9g9aRjnnM= -cloud.google.com/go/asset v1.13.0 h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk= -cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= -cloud.google.com/go/asset v1.15.3/go.mod h1:yYLfUD4wL4X589A9tYrv4rFrba0QlDeag0CMcM5ggXU= -cloud.google.com/go/asset v1.17.0/go.mod h1:yYLfUD4wL4X589A9tYrv4rFrba0QlDeag0CMcM5ggXU= -cloud.google.com/go/asset v1.17.2/go.mod h1:SVbzde67ehddSoKf5uebOD1sYw8Ab/jD/9EIeWg99q4= -cloud.google.com/go/assuredworkloads v1.10.0 h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag= -cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/assuredworkloads v1.11.4/go.mod h1:4pwwGNwy1RP0m+y12ef3Q/8PaiWrIDQ6nD2E8kvWI9U= -cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= -cloud.google.com/go/automl v1.12.0 h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw= -cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= -cloud.google.com/go/automl v1.13.4/go.mod h1:ULqwX/OLZ4hBVfKQaMtxMSTlPx0GqGbWN8uA/1EqCP8= -cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y= -cloud.google.com/go/baremetalsolution v0.5.0 h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s= -cloud.google.com/go/baremetalsolution v1.2.0/go.mod h1:68wi9AwPYkEWIUT4SvSGS9UJwKzNpshjHsH4lzk8iOw= -cloud.google.com/go/baremetalsolution v1.2.3/go.mod h1:/UAQ5xG3faDdy180rCUv47e0jvpp3BFxT+Cl0PFjw5g= -cloud.google.com/go/baremetalsolution v1.2.4/go.mod h1:BHCmxgpevw9IEryE99HbYEfxXkAEA3hkMJbYYsHtIuY= -cloud.google.com/go/batch v0.7.0 h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs= -cloud.google.com/go/batch v1.4.1/go.mod h1:KdBmDD61K0ovcxoRHGrN6GmOBWeAOyCgKD0Mugx4Fkk= -cloud.google.com/go/batch v1.6.3/go.mod h1:J64gD4vsNSA2O5TtDB5AAux3nJ9iV8U3ilg3JDBYejU= -cloud.google.com/go/batch v1.7.0/go.mod h1:J64gD4vsNSA2O5TtDB5AAux3nJ9iV8U3ilg3JDBYejU= -cloud.google.com/go/batch v1.8.0/go.mod h1:k8V7f6VE2Suc0zUM4WtoibNrA6D3dqBpB+++e3vSGYc= -cloud.google.com/go/beyondcorp v0.5.0 h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc= -cloud.google.com/go/beyondcorp v0.6.1/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/beyondcorp v1.0.3/go.mod h1:HcBvnEd7eYr+HGDd5ZbuVmBYX019C6CEXBonXbCVwJo= -cloud.google.com/go/beyondcorp v1.0.4/go.mod h1:Gx8/Rk2MxrvWfn4WIhHIG1NV7IBfg14pTKv1+EArVcc= -cloud.google.com/go/bigquery v1.50.0 h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ= -cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= -cloud.google.com/go/bigquery v1.55.0/go.mod h1:9Y5I3PN9kQWuid6183JFhOGOW3GcirA5LpsKCUn+2ec= -cloud.google.com/go/bigquery v1.57.1/go.mod h1:iYzC0tGVWt1jqSzBHqCr3lrRn0u13E8e+AqowBsDgug= -cloud.google.com/go/bigquery v1.58.0/go.mod h1:0eh4mWNY0KrBTjUzLjoYImapGORq9gEPT7MWjCy9lik= -cloud.google.com/go/bigquery v1.59.1/go.mod h1:VP1UJYgevyTwsV7desjzNzDND5p6hZB+Z8gZJN1GQUc= -cloud.google.com/go/billing v1.13.0 h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM= -cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= -cloud.google.com/go/billing v1.17.0/go.mod h1:Z9+vZXEq+HwH7bhJkyI4OQcR6TSbeMrjlpEjO2vzY64= -cloud.google.com/go/billing v1.17.4/go.mod h1:5DOYQStCxquGprqfuid/7haD7th74kyMBHkjO/OvDtk= -cloud.google.com/go/billing v1.18.0/go.mod h1:5DOYQStCxquGprqfuid/7haD7th74kyMBHkjO/OvDtk= -cloud.google.com/go/billing v1.18.2/go.mod h1:PPIwVsOOQ7xzbADCwNe8nvK776QpfrOAUkvKjCUcpSE= -cloud.google.com/go/binaryauthorization v1.5.0 h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs= -cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= -cloud.google.com/go/binaryauthorization v1.7.0/go.mod h1:Zn+S6QqTMn6odcMU1zDZCJxPjU2tZPV1oDl45lWY154= -cloud.google.com/go/binaryauthorization v1.7.3/go.mod h1:VQ/nUGRKhrStlGr+8GMS8f6/vznYLkdK5vaKfdCIpvU= -cloud.google.com/go/binaryauthorization v1.8.0/go.mod h1:VQ/nUGRKhrStlGr+8GMS8f6/vznYLkdK5vaKfdCIpvU= -cloud.google.com/go/binaryauthorization v1.8.1/go.mod h1:1HVRyBerREA/nhI7yLang4Zn7vfNVA3okoAR9qYQJAQ= -cloud.google.com/go/certificatemanager v1.6.0 h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc= -cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= -cloud.google.com/go/certificatemanager v1.7.4/go.mod h1:FHAylPe/6IIKuaRmHbjbdLhGhVQ+CWHSD5Jq0k4+cCE= -cloud.google.com/go/certificatemanager v1.7.5/go.mod h1:uX+v7kWqy0Y3NG/ZhNvffh0kuqkKZIXdvlZRO7z0VtM= -cloud.google.com/go/channel v1.12.0 h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw= -cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= -cloud.google.com/go/channel v1.17.0/go.mod h1:RpbhJsGi/lXWAUM1eF4IbQGbsfVlg2o8Iiy2/YLfVT0= -cloud.google.com/go/channel v1.17.3/go.mod h1:QcEBuZLGGrUMm7kNj9IbU1ZfmJq2apotsV83hbxX7eE= -cloud.google.com/go/channel v1.17.4/go.mod h1:QcEBuZLGGrUMm7kNj9IbU1ZfmJq2apotsV83hbxX7eE= -cloud.google.com/go/channel v1.17.5/go.mod h1:FlpaOSINDAXgEext0KMaBq/vwpLMkkPAw9b2mApQeHc= -cloud.google.com/go/cloudbuild v1.9.0 h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko= -cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/cloudbuild v1.14.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/cloudbuild v1.14.3/go.mod h1:eIXYWmRt3UtggLnFGx4JvXcMj4kShhVzGndL1LwleEM= -cloud.google.com/go/cloudbuild v1.15.0/go.mod h1:eIXYWmRt3UtggLnFGx4JvXcMj4kShhVzGndL1LwleEM= -cloud.google.com/go/cloudbuild v1.15.1/go.mod h1:gIofXZSu+XD2Uy+qkOrGKEx45zd7s28u/k8f99qKals= -cloud.google.com/go/clouddms v1.5.0 h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA= -cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= -cloud.google.com/go/clouddms v1.7.0/go.mod h1:MW1dC6SOtI/tPNCciTsXtsGNEM0i0OccykPvv3hiYeM= -cloud.google.com/go/clouddms v1.7.3/go.mod h1:fkN2HQQNUYInAU3NQ3vRLkV2iWs8lIdmBKOx4nrL6Hc= -cloud.google.com/go/clouddms v1.7.4/go.mod h1:RdrVqoFG9RWI5AvZ81SxJ/xvxPdtcRhFotwdE79DieY= -cloud.google.com/go/cloudtasks v1.10.0 h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU= -cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/cloudtasks v1.12.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/cloudtasks v1.12.4/go.mod h1:BEPu0Gtt2dU6FxZHNqqNdGqIG86qyWKBPGnsb7udGY0= -cloud.google.com/go/cloudtasks v1.12.6/go.mod h1:b7c7fe4+TJsFZfDyzO51F7cjq7HLUlRi/KZQLQjDsaY= -cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= -cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= -cloud.google.com/go/contactcenterinsights v1.6.0 h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk= -cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/contactcenterinsights v1.10.0/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/contactcenterinsights v1.11.3/go.mod h1:HHX5wrz5LHVAwfI2smIotQG9x8Qd6gYilaHcLLLmNis= -cloud.google.com/go/contactcenterinsights v1.12.1/go.mod h1:HHX5wrz5LHVAwfI2smIotQG9x8Qd6gYilaHcLLLmNis= -cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= -cloud.google.com/go/container v1.15.0 h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c= -cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= -cloud.google.com/go/container v1.26.0/go.mod h1:YJCmRet6+6jnYYRS000T6k0D0xUXQgBSaJ7VwI8FBj4= -cloud.google.com/go/container v1.27.1/go.mod h1:b1A1gJeTBXVLQ6GGw9/9M4FG94BEGsqJ5+t4d/3N7O4= -cloud.google.com/go/container v1.29.0/go.mod h1:b1A1gJeTBXVLQ6GGw9/9M4FG94BEGsqJ5+t4d/3N7O4= -cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA= -cloud.google.com/go/containeranalysis v0.9.0 h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U= -cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= -cloud.google.com/go/containeranalysis v0.11.0/go.mod h1:4n2e99ZwpGxpNcz+YsFT1dfOHPQFGcAC8FN2M2/ne/U= -cloud.google.com/go/containeranalysis v0.11.3/go.mod h1:kMeST7yWFQMGjiG9K7Eov+fPNQcGhb8mXj/UcTiWw9U= -cloud.google.com/go/containeranalysis v0.11.4/go.mod h1:cVZT7rXYBS9NG1rhQbWL9pWbXCKHWJPYraE8/FTSYPE= -cloud.google.com/go/datacatalog v1.13.0 h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw= -cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= -cloud.google.com/go/datacatalog v1.17.1/go.mod h1:nCSYFHgtxh2MiEktWIz71s/X+7ds/UT9kp0PC7waCzE= -cloud.google.com/go/datacatalog v1.18.3/go.mod h1:5FR6ZIF8RZrtml0VUao22FxhdjkoG+a0866rEnObryM= -cloud.google.com/go/datacatalog v1.19.2/go.mod h1:2YbODwmhpLM4lOFe3PuEhHK9EyTzQJ5AXgIy7EDKTEE= -cloud.google.com/go/datacatalog v1.19.3/go.mod h1:ra8V3UAsciBpJKQ+z9Whkxzxv7jmQg1hfODr3N3YPJ4= -cloud.google.com/go/dataflow v0.8.0 h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg= -cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= -cloud.google.com/go/dataflow v0.9.4/go.mod h1:4G8vAkHYCSzU8b/kmsoR2lWyHJD85oMJPHMtan40K8w= -cloud.google.com/go/dataflow v0.9.5/go.mod h1:udl6oi8pfUHnL0z6UN9Lf9chGqzDMVqcYTcZ1aPnCZQ= -cloud.google.com/go/dataform v0.7.0 h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48= -cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= -cloud.google.com/go/dataform v0.9.1/go.mod h1:pWTg+zGQ7i16pyn0bS1ruqIE91SdL2FDMvEYu/8oQxs= -cloud.google.com/go/dataform v0.9.2/go.mod h1:S8cQUwPNWXo7m/g3DhWHsLBoufRNn9EgFrMgne2j7cI= -cloud.google.com/go/datafusion v1.6.0 h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk= -cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= -cloud.google.com/go/datafusion v1.7.4/go.mod h1:BBs78WTOLYkT4GVZIXQCZT3GFpkpDN4aBY4NDX/jVlM= -cloud.google.com/go/datafusion v1.7.5/go.mod h1:bYH53Oa5UiqahfbNK9YuYKteeD4RbQSNMx7JF7peGHc= -cloud.google.com/go/datalabeling v0.7.0 h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk= -cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= -cloud.google.com/go/datalabeling v0.8.4/go.mod h1:Z1z3E6LHtffBGrNUkKwbwbDxTiXEApLzIgmymj8A3S8= -cloud.google.com/go/datalabeling v0.8.5/go.mod h1:IABB2lxQnkdUbMnQaOl2prCOfms20mcPxDBm36lps+s= -cloud.google.com/go/dataplex v1.6.0 h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM= -cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataplex v1.9.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataplex v1.11.1/go.mod h1:mHJYQQ2VEJHsyoC0OdNyy988DvEbPhqFs5OOLffLX0c= -cloud.google.com/go/dataplex v1.14.0/go.mod h1:mHJYQQ2VEJHsyoC0OdNyy988DvEbPhqFs5OOLffLX0c= -cloud.google.com/go/dataplex v1.14.2/go.mod h1:0oGOSFlEKef1cQeAHXy4GZPB/Ife0fz/PxBf+ZymA2U= -cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU= -cloud.google.com/go/dataproc/v2 v2.2.0/go.mod h1:lZR7AQtwZPvmINx5J87DSOOpTfof9LVZju6/Qo4lmcY= -cloud.google.com/go/dataproc/v2 v2.2.3/go.mod h1:G5R6GBc9r36SXv/RtZIVfB8SipI+xVn0bX5SxUzVYbY= -cloud.google.com/go/dataproc/v2 v2.3.0/go.mod h1:G5R6GBc9r36SXv/RtZIVfB8SipI+xVn0bX5SxUzVYbY= -cloud.google.com/go/dataproc/v2 v2.4.0/go.mod h1:3B1Ht2aRB8VZIteGxQS/iNSJGzt9+CA0WGnDVMEm7Z4= -cloud.google.com/go/dataqna v0.7.0 h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ= -cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= -cloud.google.com/go/dataqna v0.8.4/go.mod h1:mySRKjKg5Lz784P6sCov3p1QD+RZQONRMRjzGNcFd0c= -cloud.google.com/go/dataqna v0.8.5/go.mod h1:vgihg1mz6n7pb5q2YJF7KlXve6tCglInd6XO0JGOlWM= -cloud.google.com/go/datastore v1.11.0 h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774= -cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= -cloud.google.com/go/datastore v1.14.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= -cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= -cloud.google.com/go/datastream v1.7.0 h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0= -cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/datastream v1.10.0/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/datastream v1.10.3/go.mod h1:YR0USzgjhqA/Id0Ycu1VvZe8hEWwrkjuXrGbzeDOSEA= -cloud.google.com/go/datastream v1.10.4/go.mod h1:7kRxPdxZxhPg3MFeCSulmAJnil8NJGGvSNdn4p1sRZo= -cloud.google.com/go/deploy v1.8.0 h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk= -cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/deploy v1.13.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/deploy v1.14.2/go.mod h1:e5XOUI5D+YGldyLNZ21wbp9S8otJbBE4i88PtO9x/2g= -cloud.google.com/go/deploy v1.17.0/go.mod h1:XBr42U5jIr64t92gcpOXxNrqL2PStQCXHuKK5GRUuYo= -cloud.google.com/go/deploy v1.17.1/go.mod h1:SXQyfsXrk0fBmgBHRzBjQbZhMfKZ3hMQBw5ym7MN/50= -cloud.google.com/go/dialogflow v1.32.0 h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ= -cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= -cloud.google.com/go/dialogflow v1.43.0/go.mod h1:pDUJdi4elL0MFmt1REMvFkdsUTYSHq+rTCS8wg0S3+M= -cloud.google.com/go/dialogflow v1.44.3/go.mod h1:mHly4vU7cPXVweuB5R0zsYKPMzy240aQdAu06SqBbAQ= -cloud.google.com/go/dialogflow v1.48.1/go.mod h1:C1sjs2/g9cEwjCltkKeYp3FFpz8BOzNondEaAlCpt+A= -cloud.google.com/go/dialogflow v1.49.0/go.mod h1:dhVrXKETtdPlpPhE7+2/k4Z8FRNUp6kMV3EW3oz/fe0= -cloud.google.com/go/dlp v1.9.0 h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A= -cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= -cloud.google.com/go/dlp v1.11.1/go.mod h1:/PA2EnioBeXTL/0hInwgj0rfsQb3lpE3R8XUJxqUNKI= -cloud.google.com/go/dlp v1.11.2/go.mod h1:9Czi+8Y/FegpWzgSfkRlyz+jwW6Te9Rv26P3UfU/h/w= -cloud.google.com/go/documentai v1.18.0 h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI= -cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= -cloud.google.com/go/documentai v1.22.1/go.mod h1:LKs22aDHbJv7ufXuPypzRO7rG3ALLJxzdCXDPutw4Qc= -cloud.google.com/go/documentai v1.23.5/go.mod h1:ghzBsyVTiVdkfKaUCum/9bGBEyBjDO4GfooEcYKhN+g= -cloud.google.com/go/documentai v1.23.7/go.mod h1:ghzBsyVTiVdkfKaUCum/9bGBEyBjDO4GfooEcYKhN+g= -cloud.google.com/go/documentai v1.25.0/go.mod h1:ftLnzw5VcXkLItp6pw1mFic91tMRyfv6hHEY5br4KzY= -cloud.google.com/go/domains v0.8.0 h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ= -cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= -cloud.google.com/go/domains v0.9.4/go.mod h1:27jmJGShuXYdUNjyDG0SodTfT5RwLi7xmH334Gvi3fY= -cloud.google.com/go/domains v0.9.5/go.mod h1:dBzlxgepazdFhvG7u23XMhmMKBjrkoUNaw0A8AQB55Y= -cloud.google.com/go/edgecontainer v1.0.0 h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c= -cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= -cloud.google.com/go/edgecontainer v1.1.4/go.mod h1:AvFdVuZuVGdgaE5YvlL1faAoa1ndRR/5XhXZvPBHbsE= -cloud.google.com/go/edgecontainer v1.1.5/go.mod h1:rgcjrba3DEDEQAidT4yuzaKWTbkTI5zAMu3yy6ZWS0M= -cloud.google.com/go/errorreporting v0.3.0 h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0= -cloud.google.com/go/essentialcontacts v1.5.0 h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM= -cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= -cloud.google.com/go/essentialcontacts v1.6.5/go.mod h1:jjYbPzw0x+yglXC890l6ECJWdYeZ5dlYACTFL0U/VuM= -cloud.google.com/go/essentialcontacts v1.6.6/go.mod h1:XbqHJGaiH0v2UvtuucfOzFXN+rpL/aU5BCZLn4DYl1Q= -cloud.google.com/go/eventarc v1.11.0 h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU= -cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/eventarc v1.13.0/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/eventarc v1.13.3/go.mod h1:RWH10IAZIRcj1s/vClXkBgMHwh59ts7hSWcqD3kaclg= -cloud.google.com/go/eventarc v1.13.4/go.mod h1:zV5sFVoAa9orc/52Q+OuYUG9xL2IIZTbbuTHC6JSY8s= -cloud.google.com/go/filestore v1.6.0 h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw= -cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= -cloud.google.com/go/filestore v1.7.4/go.mod h1:S5JCxIbFjeBhWMTfIYH2Jx24J6BqjwpkkPl+nBA5DlI= -cloud.google.com/go/filestore v1.8.0/go.mod h1:S5JCxIbFjeBhWMTfIYH2Jx24J6BqjwpkkPl+nBA5DlI= -cloud.google.com/go/filestore v1.8.1/go.mod h1:MbN9KcaM47DRTIuLfQhJEsjaocVebNtNQhSLhKCF5GM= -cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= -cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= -cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= -cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ= -cloud.google.com/go/functions v1.13.0 h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg= -cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= -cloud.google.com/go/functions v1.15.4/go.mod h1:CAsTc3VlRMVvx+XqXxKqVevguqJpnVip4DdonFsX28I= -cloud.google.com/go/functions v1.16.0/go.mod h1:nbNpfAG7SG7Duw/o1iZ6ohvL7mc6MapWQVpqtM29n8k= -cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc= -cloud.google.com/go/gkebackup v0.4.0 h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA= -cloud.google.com/go/gkebackup v1.3.1/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= -cloud.google.com/go/gkebackup v1.3.4/go.mod h1:gLVlbM8h/nHIs09ns1qx3q3eaXcGSELgNu1DWXYz1HI= -cloud.google.com/go/gkebackup v1.3.5/go.mod h1:KJ77KkNN7Wm1LdMopOelV6OodM01pMuK2/5Zt1t4Tvc= -cloud.google.com/go/gkeconnect v0.7.0 h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q= -cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= -cloud.google.com/go/gkeconnect v0.8.4/go.mod h1:84hZz4UMlDCKl8ifVW8layK4WHlMAFeq8vbzjU0yJkw= -cloud.google.com/go/gkeconnect v0.8.5/go.mod h1:LC/rS7+CuJ5fgIbXv8tCD/mdfnlAadTaUufgOkmijuk= -cloud.google.com/go/gkehub v0.12.0 h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs= -cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= -cloud.google.com/go/gkehub v0.14.4/go.mod h1:Xispfu2MqnnFt8rV/2/3o73SK1snL8s9dYJ9G2oQMfc= -cloud.google.com/go/gkehub v0.14.5/go.mod h1:6bzqxM+a+vEH/h8W8ec4OJl4r36laxTs3A/fMNHJ0wA= -cloud.google.com/go/gkemulticloud v0.5.0 h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk= -cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/gkemulticloud v1.0.0/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/gkemulticloud v1.0.3/go.mod h1:7NpJBN94U6DY1xHIbsDqB2+TFZUfjLUKLjUX8NGLor0= -cloud.google.com/go/gkemulticloud v1.1.0/go.mod h1:7NpJBN94U6DY1xHIbsDqB2+TFZUfjLUKLjUX8NGLor0= -cloud.google.com/go/gkemulticloud v1.1.1/go.mod h1:C+a4vcHlWeEIf45IB5FFR5XGjTeYhF83+AYIpTy4i2Q= -cloud.google.com/go/grafeas v0.2.0 h1:CYjC+xzdPvbV65gi6Dr4YowKcmLo045pm18L0DhdELM= -cloud.google.com/go/gsuiteaddons v1.5.0 h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA= -cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= -cloud.google.com/go/gsuiteaddons v1.6.4/go.mod h1:rxtstw7Fx22uLOXBpsvb9DUbC+fiXs7rF4U29KHM/pE= -cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= -cloud.google.com/go/iap v1.7.1 h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU= -cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= -cloud.google.com/go/iap v1.9.0/go.mod h1:01OFxd1R+NFrg78S+hoPV5PxEzv22HXaNqUUlmNHFuY= -cloud.google.com/go/iap v1.9.3/go.mod h1:DTdutSZBqkkOm2HEOTBzhZxh2mwwxshfD/h3yofAiCw= -cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w= -cloud.google.com/go/ids v1.3.0 h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0= -cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= -cloud.google.com/go/ids v1.4.4/go.mod h1:z+WUc2eEl6S/1aZWzwtVNWoSZslgzPxAboS0lZX0HjI= -cloud.google.com/go/ids v1.4.5/go.mod h1:p0ZnyzjMWxww6d2DvMGnFwCsSxDJM666Iir1bK1UuBo= -cloud.google.com/go/iot v1.6.0 h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM= -cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= -cloud.google.com/go/iot v1.7.4/go.mod h1:3TWqDVvsddYBG++nHSZmluoCAVGr1hAcabbWZNKEZLk= -cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0YsSsqs= -cloud.google.com/go/kms v1.10.1 h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g= -cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -cloud.google.com/go/kms v1.15.2/go.mod h1:3hopT4+7ooWRCjc2DxgnpESFxhIraaI2IpAVUEhbT/w= -cloud.google.com/go/kms v1.15.5/go.mod h1:cU2H5jnp6G2TDpUGZyqTCoy1n16fbubHZjmVXSMtwDI= -cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= -cloud.google.com/go/language v1.9.0 h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM= -cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= -cloud.google.com/go/language v1.11.0/go.mod h1:uDx+pFDdAKTY8ehpWbiXyQdz8tDSYLJbQcXsCkjYyvQ= -cloud.google.com/go/language v1.12.2/go.mod h1:9idWapzr/JKXBBQ4lWqVX/hcadxB194ry20m/bTrhWc= -cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8= -cloud.google.com/go/lifesciences v0.8.0 h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI= -cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= -cloud.google.com/go/lifesciences v0.9.4/go.mod h1:bhm64duKhMi7s9jR9WYJYvjAFJwRqNj+Nia7hF0Z7JA= -cloud.google.com/go/lifesciences v0.9.5/go.mod h1:OdBm0n7C0Osh5yZB7j9BXyrMnTRGBJIZonUMxo5CzPw= -cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= -cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= -cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= -cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/longrunning v0.5.2/go.mod h1:nqo6DQbNV2pXhGDbDMoN2bWz68MjZUzqv2YttZiveCs= -cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= -cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= -cloud.google.com/go/managedidentities v1.5.0 h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg= -cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= -cloud.google.com/go/managedidentities v1.6.4/go.mod h1:WgyaECfHmF00t/1Uk8Oun3CQ2PGUtjc3e9Alh79wyiM= -cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI= -cloud.google.com/go/maps v0.7.0 h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo= -cloud.google.com/go/maps v1.4.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/maps v1.6.1/go.mod h1:4+buOHhYXFBp58Zj/K+Lc1rCmJssxxF4pJ5CJnhdz18= -cloud.google.com/go/maps v1.6.3/go.mod h1:VGAn809ADswi1ASofL5lveOHPnE6Rk/SFTTBx1yuOLw= -cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI= -cloud.google.com/go/mediatranslation v0.7.0 h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU= -cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= -cloud.google.com/go/mediatranslation v0.8.4/go.mod h1:9WstgtNVAdN53m6TQa5GjIjLqKQPXe74hwSCxUP6nj4= -cloud.google.com/go/mediatranslation v0.8.5/go.mod h1:y7kTHYIPCIfgyLbKncgqouXJtLsU+26hZhHEEy80fSs= -cloud.google.com/go/memcache v1.9.0 h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg= -cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= -cloud.google.com/go/memcache v1.10.4/go.mod h1:v/d8PuC8d1gD6Yn5+I3INzLR01IDn0N4Ym56RgikSI0= -cloud.google.com/go/memcache v1.10.5/go.mod h1:/FcblbNd0FdMsx4natdj+2GWzTq+cjZvMa1I+9QsuMA= -cloud.google.com/go/metastore v1.10.0 h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo= -cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/metastore v1.12.0/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/metastore v1.13.3/go.mod h1:K+wdjXdtkdk7AQg4+sXS8bRrQa9gcOr+foOMF2tqINE= -cloud.google.com/go/metastore v1.13.4/go.mod h1:FMv9bvPInEfX9Ac1cVcRXp8EBBQnBcqH6gz3KvJ9BAE= -cloud.google.com/go/monitoring v1.13.0 h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM= -cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= -cloud.google.com/go/monitoring v1.16.0/go.mod h1:Ptp15HgAyM1fNICAojDMoNc/wUmn67mLHQfyqbw+poY= -cloud.google.com/go/monitoring v1.16.3/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw= -cloud.google.com/go/monitoring v1.17.0/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw= -cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg= -cloud.google.com/go/networkconnectivity v1.11.0 h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8= -cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= -cloud.google.com/go/networkconnectivity v1.13.0/go.mod h1:SAnGPes88pl7QRLUen2HmcBSE9AowVAcdug8c0RSBFk= -cloud.google.com/go/networkconnectivity v1.14.3/go.mod h1:4aoeFdrJpYEXNvrnfyD5kIzs8YtHg945Og4koAjHQek= -cloud.google.com/go/networkconnectivity v1.14.4/go.mod h1:PU12q++/IMnDJAB+3r+tJtuCXCfwfN+C6Niyj6ji1Po= -cloud.google.com/go/networkmanagement v1.6.0 h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM= -cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= -cloud.google.com/go/networkmanagement v1.9.0/go.mod h1:UTUaEU9YwbCAhhz3jEOHr+2/K/MrBk2XxOLS89LQzFw= -cloud.google.com/go/networkmanagement v1.9.3/go.mod h1:y7WMO1bRLaP5h3Obm4tey+NquUvB93Co1oh4wpL+XcU= -cloud.google.com/go/networkmanagement v1.9.4/go.mod h1:daWJAl0KTFytFL7ar33I6R/oNBH8eEOX/rBNHrC/8TA= -cloud.google.com/go/networksecurity v0.8.0 h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo= -cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= -cloud.google.com/go/networksecurity v0.9.4/go.mod h1:E9CeMZ2zDsNBkr8axKSYm8XyTqNhiCHf1JO/Vb8mD1w= -cloud.google.com/go/networksecurity v0.9.5/go.mod h1:KNkjH/RsylSGyyZ8wXpue8xpCEK+bTtvof8SBfIhMG8= -cloud.google.com/go/notebooks v1.8.0 h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M= -cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= -cloud.google.com/go/notebooks v1.10.0/go.mod h1:SOPYMZnttHxqot0SGSFSkRrwE29eqnKPBJFqgWmiK2k= -cloud.google.com/go/notebooks v1.11.2/go.mod h1:z0tlHI/lREXC8BS2mIsUeR3agM1AkgLiS+Isov3SS70= -cloud.google.com/go/notebooks v1.11.3/go.mod h1:0wQyI2dQC3AZyQqWnRsp+yA+kY4gC7ZIVP4Qg3AQcgo= -cloud.google.com/go/optimization v1.3.1 h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248= -cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= -cloud.google.com/go/optimization v1.5.0/go.mod h1:evo1OvTxeBRBu6ydPlrIRizKY/LJKo/drDMMRKqGEUU= -cloud.google.com/go/optimization v1.6.2/go.mod h1:mWNZ7B9/EyMCcwNl1frUGEuY6CPijSkz88Fz2vwKPOY= -cloud.google.com/go/optimization v1.6.3/go.mod h1:8ve3svp3W6NFcAEFr4SfJxrldzhUl4VMUJmhrqVKtYA= -cloud.google.com/go/orchestration v1.6.0 h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8= -cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= -cloud.google.com/go/orchestration v1.8.4/go.mod h1:d0lywZSVYtIoSZXb0iFjv9SaL13PGyVOKDxqGxEf/qI= -cloud.google.com/go/orchestration v1.8.5/go.mod h1:C1J7HesE96Ba8/hZ71ISTV2UAat0bwN+pi85ky38Yq8= -cloud.google.com/go/orgpolicy v1.10.0 h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4= -cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= -cloud.google.com/go/orgpolicy v1.11.4/go.mod h1:0+aNV/nrfoTQ4Mytv+Aw+stBDBjNf4d8fYRA9herfJI= -cloud.google.com/go/orgpolicy v1.12.0/go.mod h1:0+aNV/nrfoTQ4Mytv+Aw+stBDBjNf4d8fYRA9herfJI= -cloud.google.com/go/orgpolicy v1.12.1/go.mod h1:aibX78RDl5pcK3jA8ysDQCFkVxLj3aOQqrbBaUL2V5I= -cloud.google.com/go/osconfig v1.11.0 h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ= -cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= -cloud.google.com/go/osconfig v1.12.4/go.mod h1:B1qEwJ/jzqSRslvdOCI8Kdnp0gSng0xW4LOnIebQomA= -cloud.google.com/go/osconfig v1.12.5/go.mod h1:D9QFdxzfjgw3h/+ZaAb5NypM8bhOMqBzgmbhzWViiW8= -cloud.google.com/go/oslogin v1.9.0 h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw= -cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= -cloud.google.com/go/oslogin v1.12.2/go.mod h1:CQ3V8Jvw4Qo4WRhNPF0o+HAM4DiLuE27Ul9CX9g2QdY= -cloud.google.com/go/oslogin v1.13.0/go.mod h1:xPJqLwpTZ90LSE5IL1/svko+6c5avZLluiyylMb/sRA= -cloud.google.com/go/oslogin v1.13.1/go.mod h1:vS8Sr/jR7QvPWpCjNqy6LYZr5Zs1e8ZGW/KPn9gmhws= -cloud.google.com/go/phishingprotection v0.7.0 h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA= -cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= -cloud.google.com/go/phishingprotection v0.8.4/go.mod h1:6b3kNPAc2AQ6jZfFHioZKg9MQNybDg4ixFd4RPZZ2nE= -cloud.google.com/go/phishingprotection v0.8.5/go.mod h1:g1smd68F7mF1hgQPuYn3z8HDbNre8L6Z0b7XMYFmX7I= -cloud.google.com/go/policytroubleshooter v1.6.0 h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y= -cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= -cloud.google.com/go/policytroubleshooter v1.9.0/go.mod h1:+E2Lga7TycpeSTj2FsH4oXxTnrbHJGRlKhVZBLGgU64= -cloud.google.com/go/policytroubleshooter v1.10.2/go.mod h1:m4uF3f6LseVEnMV6nknlN2vYGRb+75ylQwJdnOXfnv0= -cloud.google.com/go/policytroubleshooter v1.10.3/go.mod h1:+ZqG3agHT7WPb4EBIRqUv4OyIwRTZvsVDHZ8GlZaoxk= -cloud.google.com/go/privatecatalog v0.8.0 h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc= -cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= -cloud.google.com/go/privatecatalog v0.9.4/go.mod h1:SOjm93f+5hp/U3PqMZAHTtBtluqLygrDrVO8X8tYtG0= -cloud.google.com/go/privatecatalog v0.9.5/go.mod h1:fVWeBOVe7uj2n3kWRGlUQqR/pOd450J9yZoOECcQqJk= -cloud.google.com/go/pubsub v1.30.0 h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s= -cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsub v1.34.0/go.mod h1:alj4l4rBg+N3YTFDDC+/YyFTs6JAjam2QfYsddcAW4c= -cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= -cloud.google.com/go/pubsublite v1.7.0 h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao= -cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= -cloud.google.com/go/recaptchaenterprise v1.3.1 h1:u6EznTGzIdsyOsvm+Xkw0aSuKFXQlyjGE9a4exk6iNQ= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0 h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= -cloud.google.com/go/recaptchaenterprise/v2 v2.8.3/go.mod h1:Dak54rw6lC2gBY8FBznpOCAR58wKf+R+ZSJRoeJok4w= -cloud.google.com/go/recaptchaenterprise/v2 v2.9.0/go.mod h1:Dak54rw6lC2gBY8FBznpOCAR58wKf+R+ZSJRoeJok4w= -cloud.google.com/go/recaptchaenterprise/v2 v2.9.2/go.mod h1:trwwGkfhCmp05Ll5MSJPXY7yvnO0p4v3orGANAFHAuU= -cloud.google.com/go/recommendationengine v0.7.0 h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k= -cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= -cloud.google.com/go/recommendationengine v0.8.4/go.mod h1:GEteCf1PATl5v5ZsQ60sTClUE0phbWmo3rQ1Js8louU= -cloud.google.com/go/recommendationengine v0.8.5/go.mod h1:A38rIXHGFvoPvmy6pZLozr0g59NRNREz4cx7F58HAsQ= -cloud.google.com/go/recommender v1.9.0 h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A= -cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= -cloud.google.com/go/recommender v1.11.0/go.mod h1:kPiRQhPyTJ9kyXPCG6u/dlPLbYfFlkwHNRwdzPVAoII= -cloud.google.com/go/recommender v1.11.3/go.mod h1:+FJosKKJSId1MBFeJ/TTyoGQZiEelQQIZMKYYD8ruK4= -cloud.google.com/go/recommender v1.12.0/go.mod h1:+FJosKKJSId1MBFeJ/TTyoGQZiEelQQIZMKYYD8ruK4= -cloud.google.com/go/recommender v1.12.1/go.mod h1:gf95SInWNND5aPas3yjwl0I572dtudMhMIG4ni8nr+0= -cloud.google.com/go/redis v1.11.0 h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8= -cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= -cloud.google.com/go/redis v1.14.1/go.mod h1:MbmBxN8bEnQI4doZPC1BzADU4HGocHBk2de3SbgOkqs= -cloud.google.com/go/redis v1.14.2/go.mod h1:g0Lu7RRRz46ENdFKQ2EcQZBAJ2PtJHJLuiiRuEXwyQw= -cloud.google.com/go/resourcemanager v1.7.0 h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs= -cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= -cloud.google.com/go/resourcemanager v1.9.4/go.mod h1:N1dhP9RFvo3lUfwtfLWVxfUWq8+KUQ+XLlHLH3BoFJ0= -cloud.google.com/go/resourcemanager v1.9.5/go.mod h1:hep6KjelHA+ToEjOfO3garMKi/CLYwTqeAw7YiEI9x8= -cloud.google.com/go/resourcesettings v1.5.0 h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI= -cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= -cloud.google.com/go/resourcesettings v1.6.4/go.mod h1:pYTTkWdv2lmQcjsthbZLNBP4QW140cs7wqA3DuqErVI= -cloud.google.com/go/resourcesettings v1.6.5/go.mod h1:WBOIWZraXZOGAgoR4ukNj0o0HiSMO62H9RpFi9WjP9I= -cloud.google.com/go/retail v1.12.0 h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys= -cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= -cloud.google.com/go/retail v1.14.4/go.mod h1:l/N7cMtY78yRnJqp5JW8emy7MB1nz8E4t2yfOmklYfg= -cloud.google.com/go/retail v1.16.0/go.mod h1:LW7tllVveZo4ReWt68VnldZFWJRzsh9np+01J9dYWzE= -cloud.google.com/go/run v0.9.0 h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw= -cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= -cloud.google.com/go/run v1.3.3/go.mod h1:WSM5pGyJ7cfYyYbONVQBN4buz42zFqwG67Q3ch07iK4= -cloud.google.com/go/run v1.3.4/go.mod h1:FGieuZvQ3tj1e9GnzXqrMABSuir38AJg5xhiYq+SF3o= -cloud.google.com/go/scheduler v1.9.0 h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0= -cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= -cloud.google.com/go/scheduler v1.10.4/go.mod h1:MTuXcrJC9tqOHhixdbHDFSIuh7xZF2IysiINDuiq6NI= -cloud.google.com/go/scheduler v1.10.5/go.mod h1:MTuXcrJC9tqOHhixdbHDFSIuh7xZF2IysiINDuiq6NI= -cloud.google.com/go/scheduler v1.10.6/go.mod h1:pe2pNCtJ+R01E06XCDOJs1XvAMbv28ZsQEbqknxGOuE= -cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60= -cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= -cloud.google.com/go/secretmanager v1.11.4/go.mod h1:wreJlbS9Zdq21lMzWmJ0XhWW2ZxgPeahsqeV/vZoJ3w= -cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0RdrMeZIASKc+S7VqH4= -cloud.google.com/go/security v1.13.0 h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/security v1.15.4/go.mod h1:oN7C2uIZKhxCLiAAijKUCuHLZbIt/ghYEo8MqwD/Ty4= -cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc= -cloud.google.com/go/securitycenter v1.19.0 h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14= -cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= -cloud.google.com/go/securitycenter v1.24.2/go.mod h1:l1XejOngggzqwr4Fa2Cn+iWZGf+aBLTXtB/vXjy5vXM= -cloud.google.com/go/securitycenter v1.24.3/go.mod h1:l1XejOngggzqwr4Fa2Cn+iWZGf+aBLTXtB/vXjy5vXM= -cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU= -cloud.google.com/go/servicecontrol v1.11.1 h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE= -cloud.google.com/go/servicedirectory v1.9.0 h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU= -cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicedirectory v1.11.0/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicedirectory v1.11.3/go.mod h1:LV+cHkomRLr67YoQy3Xq2tUXBGOs5z5bPofdq7qtiAw= -cloud.google.com/go/servicedirectory v1.11.4/go.mod h1:Bz2T9t+/Ehg6x+Y7Ycq5xiShYLD96NfEsWNHyitj1qM= -cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY= -cloud.google.com/go/serviceusage v1.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4= -cloud.google.com/go/shell v1.6.0 h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU= -cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= -cloud.google.com/go/shell v1.7.4/go.mod h1:yLeXB8eKLxw0dpEmXQ/FjriYrBijNsONpwnWsdPqlKM= -cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE= -cloud.google.com/go/spanner v1.45.0 h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4= -cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= -cloud.google.com/go/spanner v1.49.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= -cloud.google.com/go/spanner v1.51.0/go.mod h1:c5KNo5LQ1X5tJwma9rSQZsXNBDNvj4/n8BVc3LNahq0= -cloud.google.com/go/spanner v1.55.0/go.mod h1:HXEznMUVhC+PC+HDyo9YFG2Ajj5BQDkcbqB9Z2Ffxi0= -cloud.google.com/go/spanner v1.56.0/go.mod h1:DndqtUKQAt3VLuV2Le+9Y3WTnq5cNKrnLb/Piqcj+h0= -cloud.google.com/go/spanner v1.57.0/go.mod h1:aXQ5QDdhPRIqVhYmnkAdwPYvj/DRN0FguclhEWw+jOo= -cloud.google.com/go/speech v1.15.0 h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw= -cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/speech v1.19.0/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/speech v1.20.1/go.mod h1:wwolycgONvfz2EDU8rKuHRW3+wc9ILPsAWoikBEWavY= -cloud.google.com/go/speech v1.21.0/go.mod h1:wwolycgONvfz2EDU8rKuHRW3+wc9ILPsAWoikBEWavY= -cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA= -cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= -cloud.google.com/go/storagetransfer v1.8.0 h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o= -cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= -cloud.google.com/go/storagetransfer v1.10.3/go.mod h1:Up8LY2p6X68SZ+WToswpQbQHnJpOty/ACcMafuey8gc= -cloud.google.com/go/storagetransfer v1.10.4/go.mod h1:vef30rZKu5HSEf/x1tK3WfWrL0XVoUQN/EPDRGPzjZs= -cloud.google.com/go/talent v1.5.0 h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM= -cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= -cloud.google.com/go/talent v1.6.5/go.mod h1:Mf5cma696HmE+P2BWJ/ZwYqeJXEeU0UqjHFXVLadEDI= -cloud.google.com/go/talent v1.6.6/go.mod h1:y/WQDKrhVz12WagoarpAIyKKMeKGKHWPoReZ0g8tseQ= -cloud.google.com/go/texttospeech v1.6.0 h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc= -cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= -cloud.google.com/go/texttospeech v1.7.4/go.mod h1:vgv0002WvR4liGuSd5BJbWy4nDn5Ozco0uJymY5+U74= -cloud.google.com/go/texttospeech v1.7.5/go.mod h1:tzpCuNWPwrNJnEa4Pu5taALuZL4QRRLcb+K9pbhXT6M= -cloud.google.com/go/tpu v1.5.0 h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A= -cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= -cloud.google.com/go/tpu v1.6.4/go.mod h1:NAm9q3Rq2wIlGnOhpYICNI7+bpBebMJbh0yyp3aNw1Y= -cloud.google.com/go/tpu v1.6.5/go.mod h1:P9DFOEBIBhuEcZhXi+wPoVy/cji+0ICFi4TtTkMHSSs= -cloud.google.com/go/trace v1.9.0 h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no= -cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= -cloud.google.com/go/trace v1.10.4/go.mod h1:Nso99EDIK8Mj5/zmB+iGr9dosS/bzWCJ8wGmE6TXNWY= -cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= -cloud.google.com/go/translate v1.7.0 h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA= -cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/translate v1.9.0/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/translate v1.9.3/go.mod h1:Kbq9RggWsbqZ9W5YpM94Q1Xv4dshw/gr/SHfsl5yCZ0= -cloud.google.com/go/translate v1.10.0/go.mod h1:Kbq9RggWsbqZ9W5YpM94Q1Xv4dshw/gr/SHfsl5yCZ0= -cloud.google.com/go/translate v1.10.1/go.mod h1:adGZcQNom/3ogU65N9UXHOnnSvjPwA/jKQUMnsYXOyk= -cloud.google.com/go/video v1.15.0 h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM= -cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= -cloud.google.com/go/video v1.20.0/go.mod h1:U3G3FTnsvAGqglq9LxgqzOiBc/Nt8zis8S+850N2DUM= -cloud.google.com/go/video v1.20.3/go.mod h1:TnH/mNZKVHeNtpamsSPygSR0iHtvrR/cW1/GDjN5+GU= -cloud.google.com/go/video v1.20.4/go.mod h1:LyUVjyW+Bwj7dh3UJnUGZfyqjEto9DnrvTe1f/+QrW0= -cloud.google.com/go/videointelligence v1.10.0 h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8= -cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= -cloud.google.com/go/videointelligence v1.11.4/go.mod h1:kPBMAYsTPFiQxMLmmjpcZUMklJp3nC9+ipJJtprccD8= -cloud.google.com/go/videointelligence v1.11.5/go.mod h1:/PkeQjpRponmOerPeJxNPuxvi12HlW7Em0lJO14FC3I= -cloud.google.com/go/vision v1.2.0 h1:/CsSTkbmO9HC8iQpxbK8ATms3OQaX3YQUeTMGCxlaK4= -cloud.google.com/go/vision/v2 v2.7.0 h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg= -cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= -cloud.google.com/go/vision/v2 v2.7.5/go.mod h1:GcviprJLFfK9OLf0z8Gm6lQb6ZFUulvpZws+mm6yPLM= -cloud.google.com/go/vision/v2 v2.8.0/go.mod h1:ocqDiA2j97pvgogdyhoxiQp2ZkDCyr0HWpicywGGRhU= -cloud.google.com/go/vmmigration v1.6.0 h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k= -cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= -cloud.google.com/go/vmmigration v1.7.4/go.mod h1:yBXCmiLaB99hEl/G9ZooNx2GyzgsjKnw5fWcINRgD70= -cloud.google.com/go/vmmigration v1.7.5/go.mod h1:pkvO6huVnVWzkFioxSghZxIGcsstDvYiVCxQ9ZH3eYI= -cloud.google.com/go/vmwareengine v0.3.0 h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM= -cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vmwareengine v1.0.0/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vmwareengine v1.0.3/go.mod h1:QSpdZ1stlbfKtyt6Iu19M6XRxjmXO+vb5a/R6Fvy2y4= -cloud.google.com/go/vmwareengine v1.1.1/go.mod h1:nMpdsIVkUrSaX8UvmnBhzVzG7PPvNYc5BszcvIVudYs= -cloud.google.com/go/vpcaccess v1.6.0 h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4= -cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= -cloud.google.com/go/vpcaccess v1.7.4/go.mod h1:lA0KTvhtEOb/VOdnH/gwPuOzGgM+CWsmGu6bb4IoMKk= -cloud.google.com/go/vpcaccess v1.7.5/go.mod h1:slc5ZRvvjP78c2dnL7m4l4R9GwL3wDLcpIWz6P/ziig= -cloud.google.com/go/webrisk v1.8.0 h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0= -cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= -cloud.google.com/go/webrisk v1.9.4/go.mod h1:w7m4Ib4C+OseSr2GL66m0zMBywdrVNTDKsdEsfMl7X0= -cloud.google.com/go/webrisk v1.9.5/go.mod h1:aako0Fzep1Q714cPEM5E+mtYX8/jsfegAuS8aivxy3U= -cloud.google.com/go/websecurityscanner v1.5.0 h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk= -cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= -cloud.google.com/go/websecurityscanner v1.6.4/go.mod h1:mUiyMQ+dGpPPRkHgknIZeCzSHJ45+fY4F52nZFDHm2o= -cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ= -cloud.google.com/go/workflows v1.10.0 h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI= -cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= -cloud.google.com/go/workflows v1.12.0/go.mod h1:PYhSk2b6DhZ508tj8HXKaBh+OFe+xdl0dHF/tJdzPQM= -cloud.google.com/go/workflows v1.12.3/go.mod h1:fmOUeeqEwPzIU81foMjTRQIdwQHADi/vEr1cx9R1m5g= -cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= -gioui.org v0.0.0-20210308172011-57750fc8a0a6 h1:K72hopUosKG3ntOPNG4OzzbuhxGuVf06fa2la1/H/Ho= -git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9 h1:7kQgkwGRoLzC9K0oyXdJo7nve/bynv/KwUsxbiTlzAM= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19 h1:iXUgAaqDcIUGbRoy2TdeofRG/j1zpGRSEmNK05T+bi8= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= -github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= -github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/apache/arrow/go/v10 v10.0.1 h1:n9dERvixoC/1JjDmBcs9FPaEryoANa2sCgVFo6ez9cI= -github.com/apache/arrow/go/v11 v11.0.0 h1:hqauxvFQxww+0mEU/2XHG6LT7eZternCZq+A5Yly2uM= -github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= -github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= -github.com/chromedp/chromedp v0.9.2 h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw= -github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= -github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= -github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= -github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= -github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= -github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= -github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= -github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240621013728-1eb8caab5155/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= -github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= -github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/getsentry/sentry-go v0.21.0 h1:c9l5F1nPF30JIppulk4veau90PK6Smu3abgVtVQWon4= -github.com/getsentry/sentry-go v0.21.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ= -github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk= -github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM= -github.com/go-fonts/stix v0.1.0 h1:UlZlgrvvmT/58o573ot7NFw0vZasZ5I6bcIft/oMdgg= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.5/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-openapi/swag v0.22.6/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= -github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= -github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= -github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= -github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= -github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= -github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= -github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= -github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lyft/protoc-gen-star v0.6.1 h1:erE0rdztuaDq3bpGifD95wfoPrSZc95nGA6tbiNYh6M= -github.com/lyft/protoc-gen-star/v2 v2.0.1 h1:keaAo8hRuAT0O3DfJ/wM3rufbAjGeJ1lAtWZHDjKGB0= -github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= -github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= -github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncabatoff/fakescraper v0.0.0-20201102132415-4b37ba603d65 h1:Og+dVkxEQNvRGU2vUKeOwYT2UJ+pEaDMWB6tIQnIh6A= -github.com/ncabatoff/fakescraper v0.0.0-20201102132415-4b37ba603d65/go.mod h1:Tx6UMSMyIsjLG/VU/F6xA1+0XI+/f9o1dGJnf1l+bPg= -github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/onsi/ginkgo/v2 v/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= -github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/phpdave11/gofpdf v1.4.2 h1:KPKiIbfwbvC/wOncwhrpRdXVj2CZTCFlw4wnoyjtHfQ= -github.com/phpdave11/gofpdi v1.0.13 h1:o61duiW8M9sMlkVXWlvP92sZJtGKENvW3VExs6dZukQ= -github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245 h1:K1Xf3bKttbF+koVGaX5xngRIZ5bVjbmPnaxE/dR08uY= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:RpforrEYXWkmGwJHIGnLZ3tTWStkjVVstwzNGqxX2Ds= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= -github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= -github.com/uwu-tools/magex v0.10.0/go.mod h1:TrSEhrL1xHfJVy6n05AUwFdcQndgwrbgL5ybPNKWmVY= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc= -github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= -github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.10 h1:szRajuUUbLyppkhs9K6BRtjY37l66XQQmw7oZRANE4k= -go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= -go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= -go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.10 h1:kfYIdQftBnbAq8pUWFXfpuuxFSKzlmM5cSn76JByiT0= -go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= -go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.10 h1:MrmRktzv/XF8CvtQt+P6wLUlURaNpSDJHFZhe//2QE4= -go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= -go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= -go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= -go.etcd.io/etcd/client/v3 v3.5.10 h1:W9TXNZ+oB3MCd/8UjxHTWK5J9Nquw9fQBLJd5ne5/Ao= -go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= -go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= -go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.etcd.io/etcd/pkg/v3 v3.5.10 h1:WPR8K0e9kWl1gAhB5A7gEa5ZBTNkT9NdNWrR8Qpo1CM= -go.etcd.io/etcd/pkg/v3 v3.5.10/go.mod h1:TKTuCKKcF1zxmfKWDkfz5qqYaE3JncKKZPFf8c1nFUs= -go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= -go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= -go.etcd.io/etcd/raft/v3 v3.5.10 h1:cgNAYe7xrsrn/5kXMSaH8kM/Ky8mAdMqGOxyYwpP0LA= -go.etcd.io/etcd/raft/v3 v3.5.10/go.mod h1:odD6kr8XQXTy9oQnyMPBOr0TVe+gT0neQhElQ6jbGRc= -go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= -go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= -go.etcd.io/etcd/server/v3 v3.5.10 h1:4NOGyOwD5sUZ22PiWYKmfxqoeh72z6EhYjNosKGLmZg= -go.etcd.io/etcd/server/v3 v3.5.10/go.mod h1:gBplPHfs6YI0L+RpGkTQO7buDbHv5HJGG/Bst0/zIPo= -go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= -go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 h1:ZOLJc06r4CB42laIXg/7udr0pbZyuAihN10A/XuiQRY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/dl v0.0.0-20190829154251-82a15e2f2ead h1:jeP6FgaSLNTMP+Yri3qjlACywQLye+huGLmNGhBzm6k= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= -golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2 h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= -google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/api v0.0.0-20231211222908-989df2bf70f3/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= -google.golang.org/genproto/googleapis/api v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:PVreiBMirk8ypES6aw9d4p6iiBNSIfZEBqr3UGoAi2E= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc h1:g3hIDl0jRNd9PPTs2uBzYuaD5mQuwOkZY0vSc0LR32o= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231030173426-d783a09b4405/go.mod h1:GRUCuLdzVqZte8+Dl/D4N25yLzcGqqWaYkeVOwulFqw= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231212172506-995d672761c0/go.mod h1:guYXGPwC6jwxgWKW5Y405fKWOFNwlvUlUnzyp9i0uqo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= -gopkg.in/evanphx/json-patch.v5 v5.6.0 h1:BMT6KIwBD9CaU91PJCZIe46bDmBWa9ynTQgJIOpfQBk= -gopkg.in/evanphx/json-patch.v5 v5.6.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpihg29RtuIyfvk= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kms v0.29.3/go.mod h1:TBGbJKpRUMk59neTMDMddjIDL+D4HuFUbpuiuzmOPg0= -k8s.io/kms v0.30.0 h1:ZlnD/ei5lpvUlPw6eLfVvH7d8i9qZ6HwUQgydNVks8g= -k8s.io/kms v0.30.0/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4= -k8s.io/kms v0.30.1/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4= -k8s.io/kms v0.31.0 h1:KchILPfB1ZE+ka7223mpU5zeFNkmb45jl7RHnlImUaI= -k8s.io/kms v0.31.0/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/kms v0.31.2/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/images/kube-webhook-certgen/rootfs/go.mod b/images/kube-webhook-certgen/rootfs/go.mod index c6dfc7e8cd..2d6541291e 100644 --- a/images/kube-webhook-certgen/rootfs/go.mod +++ b/images/kube-webhook-certgen/rootfs/go.mod @@ -14,7 +14,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.3 // indirect + github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -40,7 +40,7 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect golang.org/x/text v0.19.0 // indirect @@ -51,7 +51,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/images/kube-webhook-certgen/rootfs/go.sum b/images/kube-webhook-certgen/rootfs/go.sum index 04b52a1205..0a1c8284c4 100644 --- a/images/kube-webhook-certgen/rootfs/go.sum +++ b/images/kube-webhook-certgen/rootfs/go.sum @@ -3,8 +3,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.3 h1:yagOQz/38xJmcNeZJtrUcKjkHRltIaIFXKWeG1SkWGE= -github.com/emicklei/go-restful/v3 v3.11.3/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= @@ -102,8 +101,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -156,8 +154,7 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-aggregator v0.31.2 h1:Uw1zUP2D/4wiSjKWVVzSOcCGLuW/+IdRwjjC0FJooYU= k8s.io/kube-aggregator v0.31.2/go.mod h1:41/VIXH+/Qcg9ERNAY6bRF/WQR6xL1wFgYagdHac1X4= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/internal/ingress/controller/template/crossplane/config.go b/internal/ingress/controller/template/crossplane/config.go index b754f55dc7..5ad5467652 100644 --- a/internal/ingress/controller/template/crossplane/config.go +++ b/internal/ingress/controller/template/crossplane/config.go @@ -44,5 +44,19 @@ func (c *Template) buildConfig() { ) } + if shouldLoadAuthDigestModule(c.tplConfig.Servers) { + config.Parsed = append(config.Parsed, buildDirective("load_module", "/etc/nginx/modules/ngx_http_auth_digest_module.so")) + } + + if c.tplConfig.Cfg.EnableOpentelemetry || shouldLoadOpentelemetryModule(c.tplConfig.Servers) { + config.Parsed = append(config.Parsed, buildDirective("load_module", "/etc/nginx/modules/otel_ngx_module.so")) + } + + if c.tplConfig.Cfg.UseGeoIP2 { + config.Parsed = append(config.Parsed, + buildDirective("load_module", "/etc/nginx/modules/ngx_http_geoip2_module.so"), + ) + } + c.config = config } diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 20be1af059..08ea94276d 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -53,7 +53,7 @@ func TestCrossplaneTemplate(t *testing.T) { IgnoreDirectives: []string{"more_clear_headers", "more_set_headers"}, // TODO: Add more_set_headers DirectiveSources: []ngx_crossplane.MatchFunc{ ngx_crossplane.DefaultDirectivesMatchFunc, - ngx_crossplane.LuaDirectivesMatchFn, + ngx_crossplane.MatchLuaLatest, extramodules.BrotliMatchFn, }, LexOptions: ngx_crossplane.LexOptions{ diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index 09d6814116..dc3e43dcee 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -28,9 +28,11 @@ func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { cfg := c.tplConfig.Cfg httpBlock := ngx_crossplane.Directives{ buildDirective("lua_package_path", "/etc/nginx/lua/?.lua;;"), + buildDirective("lua_shared_dict", "luaconfig", "5m"), + buildDirective("init_by_lua_file", "/etc/nginx/lua/ngx_conf_init.lua"), + buildDirective("init_worker_by_lua_file", "/etc/nginx/lua/ngx_conf_init_worker.lua"), buildDirective("include", c.mimeFile), buildDirective("default_type", cfg.DefaultType), - buildDirective("real_ip_recursive", "on"), buildDirective("aio", "threads"), buildDirective("aio_write", cfg.EnableAioWrite), buildDirective("server_tokens", cfg.ShowServerTokens), @@ -85,8 +87,11 @@ func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { func (c *Template) buildHTTP() { cfg := c.tplConfig.Cfg httpBlock := c.initHTTPDirectives() - httpBlock = append(httpBlock, buildLuaSharedDictionaries(&c.tplConfig.Cfg)...) + httpBlock = append(httpBlock, buildLuaSharedDictionaries(&cfg)...) + if c.tplConfig.Cfg.EnableOpentelemetry || shouldLoadOpentelemetryModule(c.tplConfig.Servers) { + httpBlock = append(httpBlock, buildDirective("opentelemetry_config", cfg.OpentelemetryConfig)) + } // Real IP dealing if (cfg.UseForwardedHeaders || cfg.UseProxyProtocol) || cfg.EnableRealIP { if cfg.UseProxyProtocol { @@ -94,7 +99,7 @@ func (c *Template) buildHTTP() { } else { httpBlock = append(httpBlock, buildDirective("real_ip_header", cfg.ForwardedForHeader)) } - + httpBlock = append(httpBlock, buildDirective("real_ip_recursive", "on")) for k := range cfg.ProxyRealIPCIDR { httpBlock = append(httpBlock, buildDirective("set_real_ip_from", cfg.ProxyRealIPCIDR[k])) } @@ -128,10 +133,25 @@ func (c *Template) buildHTTP() { } } + if cfg.EnableBrotli { + httpBlock = append(httpBlock, buildDirective("brotli", "on")) + httpBlock = append(httpBlock, buildDirective("brotli_comp_level", cfg.BrotliLevel)) + httpBlock = append(httpBlock, buildDirective("brotli_min_length", cfg.BrotliMinLength)) + httpBlock = append(httpBlock, buildDirective("brotli_types", cfg.BrotliTypes)) + } + if !cfg.ShowServerTokens { httpBlock = append(httpBlock, buildDirective("more_clear_headers", "Server")) } + httpBlock = append(httpBlock, buildBlockDirective( + "geo", + []string{"$literal_dollar"}, + ngx_crossplane.Directives{ + buildDirective("default", "$"), + }, + )) + if len(c.tplConfig.AddHeaders) > 0 { additionalHeaders := make([]string, 0) for headerName, headerValue := range c.tplConfig.AddHeaders { @@ -206,6 +226,8 @@ func (c *Template) buildHTTP() { httpUpgradeMap := ngx_crossplane.Directives{buildDirective("default", "upgrade")} if cfg.UpstreamKeepaliveConnections < 1 { httpUpgradeMap = append(httpUpgradeMap, buildDirective("", "close")) + } else { + httpUpgradeMap = append(httpUpgradeMap, buildDirective("", "")) } httpBlock = append(httpBlock, buildMapDirective("$http_upgrade", "$connection_upgrade", httpUpgradeMap)) @@ -220,7 +242,7 @@ func (c *Template) buildHTTP() { if cfg.UseProxyProtocol { forwardForMap = append(forwardForMap, buildDirective("default", "$http_x_forwarded_for, $proxy_protocol_addr"), - buildDirective("", "$http_x_forwarded_for, $proxy_protocol_addr"), + buildDirective("", "$proxy_protocol_addr"), ) } else { forwardForMap = append(forwardForMap, @@ -244,15 +266,13 @@ func (c *Template) buildHTTP() { ) } - if len(cfg.HideHeaders) > 0 { - for k := range cfg.HideHeaders { - httpBlock = append(httpBlock, buildDirective("proxy_hide_header", cfg.HideHeaders[k])) - } + for k := range cfg.HideHeaders { + httpBlock = append(httpBlock, buildDirective("proxy_hide_header", cfg.HideHeaders[k])) } blockUpstreamDirectives := ngx_crossplane.Directives{ buildDirective("server", "0.0.0.1"), - buildBlockDirective("balancer_by_lua_block", nil, ngx_crossplane.Directives{buildDirective("balancer.balance()")}), + buildDirective("balancer_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_balancer.lua"), } if c.tplConfig.Cfg.UpstreamKeepaliveConnections > 0 { blockUpstreamDirectives = append(blockUpstreamDirectives, diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl similarity index 73% rename from internal/ingress/controller/template/crossplane/testdata/nginx.tmpl rename to internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl index ff68b1d9ae..b7fa803829 100644 --- a/internal/ingress/controller/template/crossplane/testdata/nginx.tmpl +++ b/internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl @@ -7,11 +7,16 @@ {{ $proxyHeaders := .ProxySetHeaders }} {{ $addHeaders := .AddHeaders }} -# MIGRATED -pid {{ .PID }}; +# Configuration checksum: {{ $all.Cfg.Checksum }} -# MODULES ARE NOT MIGRATED YET! -{{ if $cfg.EnableBrotli }} +# setup custom paths that do not require root access +pid {{ .PID }}; # OK + +{{ if $cfg.UseGeoIP2 }} #OK +load_module /etc/nginx/modules/ngx_http_geoip2_module.so; +{{ end }} + +{{ if $cfg.EnableBrotli }} #OK load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; {{ end }} @@ -20,114 +25,56 @@ load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; {{ end }} +{{ if (shouldLoadModSecurityModule $cfg $servers) }} +load_module /etc/nginx/modules/ngx_http_modsecurity_module.so; +{{ end }} + {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} load_module /etc/nginx/modules/otel_ngx_module.so; {{ end }} -# MIGRATED 1 -daemon off; +daemon off; # OK -worker_processes {{ $cfg.WorkerProcesses }}; -{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} +worker_processes {{ $cfg.WorkerProcesses }}; # OK +{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} # OK worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; {{ end }} -worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; +worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; # OK {{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} {{/* avoid waiting too long during a reload */}} -worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; +worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; # OK + +# REMOVED +# {{ if not (empty $cfg.MainSnippet) }} +# {{ $cfg.MainSnippet }} +# {{ end }} events { - multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; - worker_connections {{ $cfg.MaxWorkerConnections }}; - use epoll; - {{ range $index , $v := $cfg.DebugConnections }} - debug_connection {{ $v }}; + multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; # OK + worker_connections {{ $cfg.MaxWorkerConnections }}; # OK + use epoll; # OK + {{ range $index , $v := $cfg.DebugConnections }} # OK + debug_connection {{ $v }}; # OK {{ end }} } -# END MIGRATED 1 - http { {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} opentelemetry_config {{ $cfg.OpentelemetryConfig }}; {{ end }} - # MIGRATED - lua_package_path "/etc/nginx/lua/?.lua;;"; - - # MIGRATED - {{ buildLuaSharedDictionaries $cfg $servers }} - - # NOT MIGRATED - init_by_lua_block { - collectgarbage("collect") - - -- init modules - local ok, res - - ok, res = pcall(require, "lua_ingress") - if not ok then - error("require failed: " .. tostring(res)) - else - lua_ingress = res - lua_ingress.set_config({{ configForLua $all }}) - end - - ok, res = pcall(require, "configuration") - if not ok then - error("require failed: " .. tostring(res)) - else - configuration = res - configuration.prohibited_localhost_port = '{{ .StatusPort }}' - end - - ok, res = pcall(require, "balancer") - if not ok then - error("require failed: " .. tostring(res)) - else - balancer = res - end - - {{ if $all.EnableMetrics }} - ok, res = pcall(require, "monitor") - if not ok then - error("require failed: " .. tostring(res)) - else - monitor = res - end - {{ end }} + lua_package_path "/etc/nginx/lua/?.lua;;"; # OK - ok, res = pcall(require, "certificate") - if not ok then - error("require failed: " .. tostring(res)) - else - certificate = res - certificate.is_ocsp_stapling_enabled = {{ $cfg.EnableOCSP }} - end - - ok, res = pcall(require, "plugins") - if not ok then - error("require failed: " .. tostring(res)) - else - plugins = res - end - -- load all plugins that'll be used here - plugins.init({ {{ range $idx, $plugin := $cfg.Plugins }}{{ if $idx }},{{ end }}{{ $plugin | quote }}{{ end }} }) - } + {{ buildLuaSharedDictionaries $cfg $servers }} # OK - init_worker_by_lua_block { - lua_ingress.init_worker() - balancer.init_worker() - {{ if $all.EnableMetrics }} - monitor.init_worker({{ $all.MonitorMaxBatchSize }}) - {{ end }} + lua_shared_dict luaconfig 5m; # OK - plugins.run() - } + init_by_lua_file /etc/nginx/lua/ngx_conf_init.lua; # OK + + init_worker_by_lua_file /etc/nginx/lua/ngx_conf_init_worker.lua; # OK - # MIGRATED VARIOUS 1 {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} {{/* we use the value of the real IP for the geo_ip module */}} {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} @@ -143,6 +90,162 @@ http { {{ end }} {{ end }} + {{ if $all.Cfg.EnableModsecurity }} + modsecurity on; + + {{ if (not (empty $all.Cfg.ModsecuritySnippet)) }} + modsecurity_rules ' + {{ $all.Cfg.ModsecuritySnippet }} + '; + {{ else }} + modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf; + {{ end }} + + {{ if $all.Cfg.EnableOWASPCoreRules }} + modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf; + {{ end }} + + {{ end }} + + {{ if $cfg.UseGeoIP2 }} + # https://github.com/leev/ngx_http_geoip2_module#example-usage + + {{ range $index, $file := $all.MaxmindEditionFiles }} + {{ if eq $file "GeoLite2-Country.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_country_code source=$remote_addr country iso_code; + $geoip2_country_name source=$remote_addr country names en; + $geoip2_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_continent_code source=$remote_addr continent code; + $geoip2_continent_name source=$remote_addr continent names en; + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + } + {{ end }} + + {{ if eq $file "GeoIP2-Country.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_country_code source=$remote_addr country iso_code; + $geoip2_country_name source=$remote_addr country names en; + $geoip2_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_continent_code source=$remote_addr continent code; + $geoip2_continent_name source=$remote_addr continent names en; + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + } + {{ end }} + + {{ if eq $file "GeoLite2-City.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_city_country_code source=$remote_addr country iso_code; + $geoip2_city_country_name source=$remote_addr country names en; + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_city source=$remote_addr city names en; + $geoip2_city_geoname_id source=$remote_addr city geoname_id; + $geoip2_postal_code source=$remote_addr postal code; + $geoip2_dma_code source=$remote_addr location metro_code; + $geoip2_latitude source=$remote_addr location latitude; + $geoip2_longitude source=$remote_addr location longitude; + $geoip2_time_zone source=$remote_addr location time_zone; + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; + $geoip2_region_name source=$remote_addr subdivisions 0 names en; + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; + $geoip2_city_continent_code source=$remote_addr continent code; + $geoip2_city_continent_name source=$remote_addr continent names en; + } + {{ end }} + + {{ if eq $file "GeoIP2-City.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_city_country_code source=$remote_addr country iso_code; + $geoip2_city_country_name source=$remote_addr country names en; + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_city source=$remote_addr city names en; + $geoip2_city_geoname_id source=$remote_addr city geoname_id; + $geoip2_postal_code source=$remote_addr postal code; + $geoip2_dma_code source=$remote_addr location metro_code; + $geoip2_latitude source=$remote_addr location latitude; + $geoip2_longitude source=$remote_addr location longitude; + $geoip2_time_zone source=$remote_addr location time_zone; + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; + $geoip2_region_name source=$remote_addr subdivisions 0 names en; + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; + $geoip2_city_continent_code source=$remote_addr continent code; + $geoip2_city_continent_name source=$remote_addr continent names en; + } + {{ end }} + + {{ if eq $file "GeoLite2-ASN.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_asn source=$remote_addr autonomous_system_number; + $geoip2_org source=$remote_addr autonomous_system_organization; + } + {{ end }} + + {{ if eq $file "GeoIP2-ASN.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_asn source=$remote_addr autonomous_system_number; + $geoip2_org source=$remote_addr autonomous_system_organization; + } + {{ end }} + + {{ if eq $file "GeoIP2-ISP.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_isp source=$remote_addr isp; + $geoip2_isp_org source=$remote_addr organization; + $geoip2_asn source=$remote_addr default=0 autonomous_system_number; + } + {{ end }} + + {{ if eq $file "GeoIP2-Connection-Type.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Connection-Type.mmdb { + $geoip2_connection_type connection_type; + } + {{ end }} + + {{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_is_anon source=$remote_addr is_anonymous; + $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; + $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; + $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; + $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; + $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; + } + {{ end }} + + {{ end }} + + {{ end }} + aio threads; {{ if $cfg.EnableAioWrite }} @@ -201,9 +304,18 @@ http { limit_req_status {{ $cfg.LimitReqStatusCode }}; limit_conn_status {{ $cfg.LimitConnStatusCode }}; + {{ buildOpentelemetry $cfg $servers }} + include /etc/nginx/mime.types; default_type {{ $cfg.DefaultType }}; + {{ if $cfg.EnableBrotli }} + brotli on; + brotli_comp_level {{ $cfg.BrotliLevel }}; + brotli_min_length {{ $cfg.BrotliMinLength }}; + brotli_types {{ $cfg.BrotliTypes }}; + {{ end }} + {{ if $cfg.UseGzip }} gzip on; gzip_comp_level {{ $cfg.GzipLevel }}; @@ -263,26 +375,6 @@ http { {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} - server_name_in_redirect off; - port_in_redirect off; - - ssl_protocols {{ $cfg.SSLProtocols }}; - - ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; - - # allow configuring ssl session tickets - ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; - - # slightly reduce the time-to-first-byte - ssl_buffer_size {{ $cfg.SSLBufferSize }}; - - ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; - # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} - ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; - ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; - - proxy_ssl_session_reuse on; - # See https://www.nginx.com/blog/websocket-nginx map $http_upgrade $connection_upgrade { default upgrade; @@ -303,9 +395,6 @@ http { {{ end }} } - # Cache for internal auth checks - proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; - {{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} # We can't use $proxy_add_x_forwarded_for because the realip module # replaces the remote_addr too soon @@ -321,16 +410,35 @@ http { {{ end }} - # turn on session caching to drastically improve performance + # Create a variable that contains the literal $ character. + # This works because the geo module will not resolve variables. + geo $literal_dollar { + default "$"; + } + + server_name_in_redirect off; + port_in_redirect off; + + ssl_protocols {{ $cfg.SSLProtocols }}; + + ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; + + # turn on session caching to drastically improve performance {{ if $cfg.SSLSessionCache }} ssl_session_cache shared:SSL:{{ $cfg.SSLSessionCacheSize }}; ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; {{ end }} + # allow configuring ssl session tickets + ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; + {{ if not (empty $cfg.SSLSessionTicketKey ) }} ssl_session_ticket_key /etc/ingress-controller/tickets.key; {{ end }} + # slightly reduce the time-to-first-byte + ssl_buffer_size {{ $cfg.SSLBufferSize }}; + {{ if not (empty $cfg.SSLCiphers) }} # allow configuring custom ssl ciphers ssl_ciphers '{{ $cfg.SSLCiphers }}'; @@ -342,16 +450,20 @@ http { ssl_dhparam {{ $cfg.SSLDHParam }}; {{ end }} + ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; + + # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} + ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; + ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; + {{ if and $cfg.CustomHTTPErrors (not $cfg.DisableProxyInterceptErrors) }} proxy_intercept_errors on; {{ end }} - {{ if $cfg.EnableBrotli }} - brotli on; - brotli_comp_level {{ $cfg.BrotliLevel }}; - brotli_min_length {{ $cfg.BrotliMinLength }}; - brotli_types {{ $cfg.BrotliTypes }}; - {{ end }} + {{ range $errCode := $cfg.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} + + proxy_ssl_session_reuse on; {{ if $cfg.AllowBackendServerHeader }} proxy_pass_header Server; @@ -360,34 +472,26 @@ http { {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; {{ end }} - # Global filters - {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - map $http_user_agent $block_ua { - default 0; - - {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; - {{ end }} - } - {{ end }} - - {{ if gt (len $cfg.BlockReferers) 0 }} - map $http_referer $block_ref { - default 0; - - {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; - {{ end }} - } + {{ if not (empty $cfg.HTTPSnippet) }} + # Custom code snippet configured in the configuration configmap + {{ $cfg.HTTPSnippet }} {{ end }} upstream upstream_balancer { + ### Attention!!! + # + # We no longer create "upstream" section for every backend. + # Backends are handled dynamically using Lua. If you would like to debug + # and see what backends ingress-nginx has in its memory you can + # install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin. + # Once you have the plugin you can use "kubectl ingress-nginx backends" command to + # inspect current backends. + # + ### + server 0.0.0.1; # placeholder - balancer_by_lua_block { - balancer.balance() - } + balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer.lua; {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} keepalive {{ $cfg.UpstreamKeepaliveConnections }}; @@ -397,20 +501,6 @@ http { {{ end }} } - # END MIGRATED VARIOUS 1 - - {{ buildOpentelemetry $cfg $servers }} - - # Create a variable that contains the literal $ character. - # This works because the geo module will not resolve variables. - geo $literal_dollar { - default "$"; - } - - # MIGRATED - {{ range $errCode := $cfg.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} - {{ range $rl := (filterRateLimits $servers ) }} # Ratelimit {{ $rl.Name }} geo $remote_addr $allowlist_{{ $rl.ID }} { @@ -432,6 +522,30 @@ http { {{ $zone }} {{ end }} + # Cache for internal auth checks + proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; + + # Global filters + {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; + {{ end }} + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + map $http_user_agent $block_ua { + default 0; + + {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; + {{ end }} + } + {{ end }} + + {{ if gt (len $cfg.BlockReferers) 0 }} + map $http_referer $block_ref { + default 0; + + {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; + {{ end }} + } + {{ end }} {{/* Build server redirects (from/to www) */}} {{ range $redirect := .RedirectServers }} @@ -442,9 +556,7 @@ http { {{ buildHTTPListener $all $redirect.From }} {{ buildHTTPSListener $all $redirect.From }} - ssl_certificate_by_lua_block { - certificate.call() - } + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; {{ if gt (len $cfg.BlockUserAgents) 0 }} if ($block_ua) { @@ -457,30 +569,7 @@ http { } {{ end }} - set_by_lua_block $redirect_to { - local request_uri = ngx.var.request_uri - if string.sub(request_uri, -1) == "/" then - request_uri = string.sub(request_uri, 1, -2) - end - - {{ if $cfg.UseForwardedHeaders }} - local redirectScheme - if not ngx.var.http_x_forwarded_proto then - redirectScheme = ngx.var.scheme - else - redirectScheme = ngx.var.http_x_forwarded_proto - end - {{ else }} - local redirectScheme = ngx.var.scheme - {{ end }} - - {{ if ne $all.ListenPorts.HTTPS 443 }} - {{ $redirect_port := (printf ":%v" $all.ListenPorts.HTTPS) }} - return string.format("%s://%s%s%s", redirectScheme, "{{ $redirect.To }}", "{{ $redirect_port }}", request_uri) - {{ else }} - return string.format("%s://%s%s", redirectScheme, "{{ $redirect.To }}", request_uri) - {{ end }} - } + set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; } @@ -528,7 +617,12 @@ http { {{ template "SERVER" serverConfig $all $server }} - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics) }} + {{ if not (empty $cfg.ServerSnippet) }} + # Custom code snippet configured in the configuration configmap + {{ $cfg.ServerSnippet }} + {{ end }} + + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics $cfg.EnableModsecurity) }} } ## end server {{ $server.Hostname }} @@ -549,6 +643,11 @@ http { # default server, used for NGINX healthcheck and access to nginx stats server { + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + listen 127.0.0.1:{{ .StatusPort }}; set $proxy_upstream_name "internal"; @@ -565,17 +664,7 @@ http { } location /is-dynamic-lb-initialized { - content_by_lua_block { - local configuration = require("configuration") - local backend_data = configuration.get_backends_data() - if not backend_data then - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - return - end - - ngx.say("OK") - ngx.exit(ngx.HTTP_OK) - } + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; } location {{ .StatusPath }} { @@ -587,27 +676,136 @@ http { client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; proxy_buffering off; - content_by_lua_block { - configuration.call() - } + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; } location / { - content_by_lua_block { - ngx.exit(ngx.HTTP_NOT_FOUND) - } + return 404; + } + } +} + +stream { + lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;;"; + + lua_shared_dict tcp_udp_configuration_data 5M; + + {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} + + init_by_lua_file /etc/nginx/lua/ngx_conf_init_stream.lua; + + init_worker_by_lua_file /etc/nginx/lua/nginx/ngx_conf_init_tcp_udp.lua; + + lua_add_variable $proxy_upstream_name; + + log_format log_stream '{{ $cfg.LogFormatStream }}'; + + {{ if or $cfg.DisableAccessLog $cfg.DisableStreamAccessLog }} + access_log off; + {{ else }} + access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }}; + {{ end }} + + + error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; + {{ if $cfg.EnableRealIP }} + {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} + set_real_ip_from {{ $trusted_ip }}; + {{ end }} + {{ end }} + + upstream upstream_balancer { + server 0.0.0.1:1234; # placeholder + balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer_tcp_udp.lua; + } + + server { + listen 127.0.0.1:{{ .StreamPort }}; + + access_log off; + + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_content_tcp_udp.lua; + } + + # TCP services + {{ range $tcpServer := .TCPBackends }} + server { + preread_by_lua_block { + ngx.var.proxy_upstream_name="tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}"; + } + + {{ range $address := $all.Cfg.BindAddressIpv4 }} + listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ else }} + listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ end }} + {{ if $IsIPV6Enabled }} + {{ range $address := $all.Cfg.BindAddressIpv6 }} + listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ else }} + listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ end }} + {{ end }} + proxy_timeout {{ $cfg.ProxyStreamTimeout }}; + proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; + proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; + + proxy_pass upstream_balancer; + {{ if $tcpServer.Backend.ProxyProtocol.Encode }} + proxy_protocol on; + {{ end }} + } + {{ end }} + + # UDP services + {{ range $udpServer := .UDPBackends }} + server { + preread_by_lua_block { + ngx.var.proxy_upstream_name="udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}"; } + + {{ range $address := $all.Cfg.BindAddressIpv4 }} + listen {{ $address }}:{{ $udpServer.Port }} udp; + {{ else }} + listen {{ $udpServer.Port }} udp; + {{ end }} + {{ if $IsIPV6Enabled }} + {{ range $address := $all.Cfg.BindAddressIpv6 }} + listen {{ $address }}:{{ $udpServer.Port }} udp; + {{ else }} + listen [::]:{{ $udpServer.Port }} udp; + {{ end }} + {{ end }} + proxy_responses {{ $cfg.ProxyStreamResponses }}; + proxy_timeout {{ $cfg.ProxyStreamTimeout }}; + proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; + proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; + proxy_pass upstream_balancer; } + {{ end }} + + # Stream Snippets + {{ range $snippet := .StreamSnippets }} + {{ $snippet }} + {{ end }} } {{/* definition of templates to avoid repetitions */}} {{ define "CUSTOM_ERRORS" }} {{ $enableMetrics := .EnableMetrics }} + {{ $modsecurityEnabled := .ModsecurityEnabled }} {{ $upstreamName := .UpstreamName }} {{ range $errCode := .ErrorCodes }} location @custom_{{ $upstreamName }}_{{ $errCode }} { internal; + # Ensure that modsecurity will not run on custom error pages or they might be blocked + {{ if $modsecurityEnabled }} + modsecurity off; + {{ end }} + proxy_intercept_errors off; proxy_set_header X-Code {{ $errCode }}; @@ -626,11 +824,9 @@ http { rewrite (.*) / break; proxy_pass http://upstream_balancer; - log_by_lua_block { - {{ if $enableMetrics }} - monitor.call() - {{ end }} - } + {{ if $enableMetrics }} + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; + {{ end }} } {{ end }} {{ end }} @@ -690,9 +886,7 @@ http { ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; {{ end }} - ssl_certificate_by_lua_block { - certificate.call() - } + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; {{ if not (empty $server.AuthTLSError) }} # {{ $server.AuthTLSError }} @@ -741,8 +935,13 @@ http { ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; {{ end }} + {{ if not (empty $server.ServerSnippet) }} + # Custom code snippet configured for host {{ $server.Hostname }} + {{ $server.ServerSnippet }} + {{ end }} + {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics) }} + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics $all.Cfg.EnableModsecurity) }} {{ end }} {{ buildMirrorLocations $server.Locations }} @@ -779,13 +978,16 @@ http { access_log off; {{ end }} + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + {{ if $externalAuth.AuthCacheKey }} set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; set $cache_key ''; - rewrite_by_lua_block { - ngx.var.cache_key = ngx.encode_base64(ngx.sha1_bin(ngx.var.tmp_cache_key)) - } + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; proxy_cache auth_cache; @@ -861,6 +1063,10 @@ http { {{ $line }} {{- end }} + {{ if not (empty $externalAuth.AuthSnippet) }} + {{ $externalAuth.AuthSnippet }} + {{ end }} + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} # The target is an upstream with HTTP keepalive, that is why the @@ -889,6 +1095,11 @@ http { {{ template "CORS" $location }} {{ end }} + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; } {{ end }} @@ -901,7 +1112,6 @@ http { set $service_name {{ $ing.Service | quote }}; set $service_port {{ $ing.ServicePort | quote }}; set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; - set $global_rate_limit_exceeding n; {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} @@ -910,35 +1120,13 @@ http { mirror_request_body {{ $location.Mirror.RequestBody }}; {{ end }} - rewrite_by_lua_block { - lua_ingress.rewrite({{ locationConfigForLua $location $all }}) - balancer.rewrite() - plugins.run() - } + {{ locationConfigForLua $location $all }} - # be careful with `access_by_lua_block` and `satisfy any` directives as satisfy any - # will always succeed when there's `access_by_lua_block` that does not have any lua code doing `ngx.exit(ngx.DECLINED)` - # other authentication method such as basic auth or external auth useless - all requests will be allowed. - #access_by_lua_block { - #} + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; - header_filter_by_lua_block { - lua_ingress.header() - plugins.run() - } + header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; - body_filter_by_lua_block { - plugins.run() - } - - log_by_lua_block { - balancer.log() - {{ if $all.EnableMetrics }} - monitor.call() - {{ end }} - - plugins.run() - } + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; {{ if not $location.Logs.Access }} access_log off; @@ -970,6 +1158,8 @@ http { set $proxy_alternative_upstream_name ""; + {{ buildModSecurityForLocation $all.Cfg $location }} + {{ if isLocationAllowed $location }} {{ if gt (len $location.Denylist.CIDR) 0 }} {{ range $ip := $location.Denylist.CIDR }} @@ -1134,6 +1324,14 @@ http { grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; {{ end }} + {{/* Add any additional configuration defined */}} + {{ $location.ConfigurationSnippet }} + + {{ if not (empty $all.Cfg.LocationSnippet) }} + # Custom code snippet configured in the configuration configmap + {{ $all.Cfg.LocationSnippet }} + {{ end }} + {{ if $location.CustomHeaders }} # Custom Response Headers {{ range $k, $v := $location.CustomHeaders.Headers }} diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl new file mode 100644 index 0000000000..64e5a0c3f9 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl @@ -0,0 +1,1419 @@ +{{ $all := . }} +{{ $servers := .Servers }} +{{ $cfg := .Cfg }} +{{ $IsIPV6Enabled := .IsIPV6Enabled }} +{{ $healthzURI := .HealthzURI }} +{{ $backends := .Backends }} +{{ $proxyHeaders := .ProxySetHeaders }} +{{ $addHeaders := .AddHeaders }} + +# Configuration checksum: {{ $all.Cfg.Checksum }} + +# setup custom paths that do not require root access +pid {{ .PID }}; # OK + +{{ if $cfg.UseGeoIP2 }} +load_module /etc/nginx/modules/ngx_http_geoip2_module.so; # OK +{{ end }} + +{{ if $cfg.EnableBrotli }} +load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; # OK +load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; # OK +{{ end }} + +{{ if (shouldLoadAuthDigestModule $servers) }} +load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; # OK +{{ end }} + +{{ if (shouldLoadOpentelemetryModule $cfg $servers) }} +load_module /etc/nginx/modules/otel_ngx_module.so; # OK +{{ end }} + +daemon off; # OK + +worker_processes {{ $cfg.WorkerProcesses }}; # OK +{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} +worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; # OK +{{ end }} + +worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; # OK + +{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} +{{/* avoid waiting too long during a reload */}} +worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; # OK + +events { + multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; # OK + worker_connections {{ $cfg.MaxWorkerConnections }}; # OK + use epoll; # OK + {{ range $index , $v := $cfg.DebugConnections }} + debug_connection {{ $v }}; # OK + {{ end }} +} + +http { + {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} + opentelemetry_config {{ $cfg.OpentelemetryConfig }}; # OK + {{ end }} + + lua_package_path "/etc/nginx/lua/?.lua;;"; # OK + + {{ buildLuaSharedDictionaries $cfg $servers }} # OK + + lua_shared_dict luaconfig 5m; # OK + + init_by_lua_file /etc/nginx/lua/ngx_conf_init.lua; # OK + + init_worker_by_lua_file /etc/nginx/lua/ngx_conf_init_worker.lua; # OK + + {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} + {{/* we use the value of the real IP for the geo_ip module */}} + {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} + {{ if $cfg.UseProxyProtocol }} + real_ip_header proxy_protocol; # OK + {{ else }} + real_ip_header {{ $cfg.ForwardedForHeader }}; # OK + {{ end }} + + real_ip_recursive on; # OK + {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} + set_real_ip_from {{ $trusted_ip }}; # OK + {{ end }} + {{ end }} + + {{ if $cfg.UseGeoIP2 }} + # https://github.com/leev/ngx_http_geoip2_module#example-usage + + {{ range $index, $file := $all.MaxmindEditionFiles }} + {{ if eq $file "GeoLite2-Country.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_country_code source=$remote_addr country iso_code; + $geoip2_country_name source=$remote_addr country names en; + $geoip2_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_continent_code source=$remote_addr continent code; + $geoip2_continent_name source=$remote_addr continent names en; + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + } + {{ end }} + + {{ if eq $file "GeoIP2-Country.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_country_code source=$remote_addr country iso_code; + $geoip2_country_name source=$remote_addr country names en; + $geoip2_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_continent_code source=$remote_addr continent code; + $geoip2_continent_name source=$remote_addr continent names en; + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + } + {{ end }} + + {{ if eq $file "GeoLite2-City.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_city_country_code source=$remote_addr country iso_code; + $geoip2_city_country_name source=$remote_addr country names en; + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_city source=$remote_addr city names en; + $geoip2_city_geoname_id source=$remote_addr city geoname_id; + $geoip2_postal_code source=$remote_addr postal code; + $geoip2_dma_code source=$remote_addr location metro_code; + $geoip2_latitude source=$remote_addr location latitude; + $geoip2_longitude source=$remote_addr location longitude; + $geoip2_time_zone source=$remote_addr location time_zone; + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; + $geoip2_region_name source=$remote_addr subdivisions 0 names en; + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; + $geoip2_city_continent_code source=$remote_addr continent code; + $geoip2_city_continent_name source=$remote_addr continent names en; + } + {{ end }} + + {{ if eq $file "GeoIP2-City.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_city_country_code source=$remote_addr country iso_code; + $geoip2_city_country_name source=$remote_addr country names en; + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; + $geoip2_city source=$remote_addr city names en; + $geoip2_city_geoname_id source=$remote_addr city geoname_id; + $geoip2_postal_code source=$remote_addr postal code; + $geoip2_dma_code source=$remote_addr location metro_code; + $geoip2_latitude source=$remote_addr location latitude; + $geoip2_longitude source=$remote_addr location longitude; + $geoip2_time_zone source=$remote_addr location time_zone; + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; + $geoip2_region_name source=$remote_addr subdivisions 0 names en; + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; + $geoip2_city_continent_code source=$remote_addr continent code; + $geoip2_city_continent_name source=$remote_addr continent names en; + } + {{ end }} + + {{ if eq $file "GeoLite2-ASN.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_asn source=$remote_addr autonomous_system_number; + $geoip2_org source=$remote_addr autonomous_system_organization; + } + {{ end }} + + {{ if eq $file "GeoIP2-ASN.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_asn source=$remote_addr autonomous_system_number; + $geoip2_org source=$remote_addr autonomous_system_organization; + } + {{ end }} + + {{ if eq $file "GeoIP2-ISP.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_isp source=$remote_addr isp; + $geoip2_isp_org source=$remote_addr organization; + $geoip2_asn source=$remote_addr default=0 autonomous_system_number; + } + {{ end }} + + {{ if eq $file "GeoIP2-Connection-Type.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Connection-Type.mmdb { + $geoip2_connection_type connection_type; + } + {{ end }} + + {{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} + geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { + {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + {{ end }} + $geoip2_is_anon source=$remote_addr is_anonymous; + $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; + $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; + $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; + $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; + $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; + } + {{ end }} + + {{ end }} + + {{ end }} + + aio threads; # OK + + {{ if $cfg.EnableAioWrite }} + aio_write on; # OK + {{ end }} + + tcp_nopush on; # OK + tcp_nodelay on; # OK + + log_subrequest on; # OK + + reset_timedout_connection on; # OK + + keepalive_timeout {{ $cfg.KeepAlive }}s; # OK + keepalive_requests {{ $cfg.KeepAliveRequests }}; # OK + + client_body_temp_path /tmp/nginx/client-body; # OK + fastcgi_temp_path /tmp/nginx/fastcgi-temp; # OK + proxy_temp_path /tmp/nginx/proxy-temp; # OK + + client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; # OK + client_header_timeout {{ $cfg.ClientHeaderTimeout }}s; # OK + large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; # OK + client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; # OK + client_body_timeout {{ $cfg.ClientBodyTimeout }}s; # OK + + {{ if gt $cfg.GRPCBufferSizeKb 0 }} + grpc_buffer_size {{ $cfg.GRPCBufferSizeKb }}k; # OK + {{ end }} + + {{ if and (ne $cfg.HTTP2MaxHeaderSize "") (ne $cfg.HTTP2MaxFieldSize "") }} # OK + http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; # OK + http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; # OK + {{ end }} + + {{ if (gt $cfg.HTTP2MaxRequests 0) }} # OK + http2_max_requests {{ $cfg.HTTP2MaxRequests }}; # OK + {{ end }} + + http2_max_concurrent_streams {{ $cfg.HTTP2MaxConcurrentStreams }}; # OK + + types_hash_max_size 2048; # OK + server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; # OK + server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; # OK + map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; # OK + + proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }}; # OK + proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }}; # OK + + variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; # OK + variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; # OK + + underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; # OK + ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; # OK + + limit_req_status {{ $cfg.LimitReqStatusCode }}; # OK + limit_conn_status {{ $cfg.LimitConnStatusCode }}; # OK + + {{ buildOpentelemetry $cfg $servers }} + + include /etc/nginx/mime.types; # OK + default_type {{ $cfg.DefaultType }}; # OK + + {{ if $cfg.EnableBrotli }} + brotli on; # OK + brotli_comp_level {{ $cfg.BrotliLevel }}; # OK + brotli_min_length {{ $cfg.BrotliMinLength }}; # OK + brotli_types {{ $cfg.BrotliTypes }}; # OK + {{ end }} + + {{ if $cfg.UseGzip }} + gzip on; # OK + gzip_comp_level {{ $cfg.GzipLevel }}; # OK + {{- if $cfg.GzipDisable }} + gzip_disable "{{ $cfg.GzipDisable }}"; # OK + {{- end }} + gzip_http_version 1.1; # OK + gzip_min_length {{ $cfg.GzipMinLength}}; # OK + gzip_types {{ $cfg.GzipTypes }}; # OK + gzip_proxied any; # OK + gzip_vary on; # OK + {{ end }} + + # Custom headers for response + {{ range $k, $v := $addHeaders }} + more_set_headers {{ printf "%s: %s" $k $v | quote }}; # OK + {{ end }} + + server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; # OK + {{ if not $cfg.ShowServerTokens }} + more_clear_headers Server; # OK + {{ end }} + + # disable warnings + uninitialized_variable_warn off; # OK + + # Additional available variables: + # $namespace + # $ingress_name + # $service_name + # $service_port + log_format upstreaminfo {{ if $cfg.LogFormatEscapeNone }}escape=none {{ else if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ $cfg.LogFormatUpstream }}'; # OK + + {{/* map urls that should not appear in access.log */}} + {{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} + map $request_uri $loggable { # OK + {{ range $reqUri := $cfg.SkipAccessLogURLs }} + {{ $reqUri }} 0;{{ end }} # OK + default 1; # OK + } + + {{ if or $cfg.DisableAccessLog $cfg.DisableHTTPAccessLog }} + access_log off; # OK + {{ else }} + {{ if $cfg.EnableSyslog }} + access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable; # OK + {{ else }} + access_log {{ or $cfg.HTTPAccessLogPath $cfg.AccessLogPath }} upstreaminfo {{ $cfg.AccessLogParams }} if=$loggable; # OK + {{ end }} + {{ end }} + + {{ if $cfg.EnableSyslog }} + error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }}; # OK + {{ else }} + error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; # OK + {{ end }} + + {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} # OK + + # See https://www.nginx.com/blog/websocket-nginx + map $http_upgrade $connection_upgrade { # OK + default upgrade; # OK + {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} + # See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive + '' ''; # OK + {{ else }} + '' close; # OK + {{ end }} + } + + # Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server. + # If no such header is provided, it can provide a random value. + map $http_x_request_id $req_id { # OK + default $http_x_request_id; # OK + {{ if $cfg.GenerateRequestID }} + "" $request_id; # OK + {{ end }} + } + + {{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} + # We can't use $proxy_add_x_forwarded_for because the realip module + # replaces the remote_addr too soon + map $http_x_forwarded_for $full_x_forwarded_for { # OK + {{ if $all.Cfg.UseProxyProtocol }} + default "$http_x_forwarded_for, $proxy_protocol_addr"; # OK + '' "$proxy_protocol_addr"; # OK + {{ else }} + default "$http_x_forwarded_for, $realip_remote_addr"; # OK + '' "$realip_remote_addr"; # OK + {{ end}} + } + + {{ end }} + + # Create a variable that contains the literal $ character. + # This works because the geo module will not resolve variables. + geo $literal_dollar { # OK + default "$"; # OK + } + + server_name_in_redirect off; # OK + port_in_redirect off; # OK + + ssl_protocols {{ $cfg.SSLProtocols }}; # OK + + ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; # OK + + # turn on session caching to drastically improve performance + {{ if $cfg.SSLSessionCache }} + ssl_session_cache shared:SSL:{{ $cfg.SSLSessionCacheSize }}; # OK + ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; # OK + {{ end }} + + # allow configuring ssl session tickets + ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; # OK + + {{ if not (empty $cfg.SSLSessionTicketKey ) }} + ssl_session_ticket_key /etc/ingress-controller/tickets.key; # OK + {{ end }} + + # slightly reduce the time-to-first-byte + ssl_buffer_size {{ $cfg.SSLBufferSize }}; # OK + + {{ if not (empty $cfg.SSLCiphers) }} + # allow configuring custom ssl ciphers + ssl_ciphers '{{ $cfg.SSLCiphers }}'; # OK + ssl_prefer_server_ciphers on; # OK + {{ end }} + + {{ if not (empty $cfg.SSLDHParam) }} + # allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam + ssl_dhparam {{ $cfg.SSLDHParam }}; # OK + {{ end }} + + ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; # OK + + # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} + ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; # OK + ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; # OK + + {{ if and $cfg.CustomHTTPErrors (not $cfg.DisableProxyInterceptErrors) }} + proxy_intercept_errors on; # OK + {{ end }} + + {{ range $errCode := $cfg.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} # OK + + proxy_ssl_session_reuse on; # OK + + {{ if $cfg.AllowBackendServerHeader }} + proxy_pass_header Server; # OK + {{ end }} + + {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; # OK + {{ end }} + + upstream upstream_balancer { + ### Attention!!! + # + # We no longer create "upstream" section for every backend. + # Backends are handled dynamically using Lua. If you would like to debug + # and see what backends ingress-nginx has in its memory you can + # install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin. + # Once you have the plugin you can use "kubectl ingress-nginx backends" command to + # inspect current backends. + # + ### + + server 0.0.0.1; # OK + + balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer.lua; # OK + + {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} + keepalive {{ $cfg.UpstreamKeepaliveConnections }}; # OK + keepalive_time {{ $cfg.UpstreamKeepaliveTime }}; # OK + keepalive_timeout {{ $cfg.UpstreamKeepaliveTimeout }}s; # OK + keepalive_requests {{ $cfg.UpstreamKeepaliveRequests }}; # OK + {{ end }} + } + + {{ range $rl := (filterRateLimits $servers ) }} + # Ratelimit {{ $rl.Name }} + geo $remote_addr $allowlist_{{ $rl.ID }} { + default 0; + {{ range $ip := $rl.Allowlist }} + {{ $ip }} 1;{{ end }} + } + + # Ratelimit {{ $rl.Name }} + map $allowlist_{{ $rl.ID }} $limit_{{ $rl.ID }} { + 0 {{ $cfg.LimitConnZoneVariable }}; + 1 ""; + } + {{ end }} + + {{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} + {{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} + {{ range $zone := (buildRateLimitZones $servers) }} + {{ $zone }} + {{ end }} + + # Cache for internal auth checks + proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; # OK + + # Global filters + {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; # OK + {{ end }} + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + map $http_user_agent $block_ua { # OK + default 0; # OK + + {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; # OK + {{ end }} + } + {{ end }} + + {{ if gt (len $cfg.BlockReferers) 0 }} + map $http_referer $block_ref { # OK + default 0; # OK + + {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; # OK + {{ end }} + } + {{ end }} + + {{/* Build server redirects (from/to www) */}} + {{ range $redirect := .RedirectServers }} + ## start server {{ $redirect.From }} + server { + server_name {{ $redirect.From }}; + + {{ buildHTTPListener $all $redirect.From }} + {{ buildHTTPSListener $all $redirect.From }} + + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + if ($block_ua) { + return 403; + } + {{ end }} + {{ if gt (len $cfg.BlockReferers) 0 }} + if ($block_ref) { + return 403; + } + {{ end }} + + set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; + + return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; + } + ## end server {{ $redirect.From }} + {{ end }} + + {{ range $server := $servers }} + {{ range $location := $server.Locations }} + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} + upstream {{ buildAuthUpstreamName $location $server.Hostname }} { + {{- $externalAuth := $location.ExternalAuth }} + server {{ extractHostPort $externalAuth.URL }}; + + keepalive {{ $externalAuth.KeepaliveConnections }}; + keepalive_requests {{ $externalAuth.KeepaliveRequests }}; + keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; + } + ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} + {{ end }} + {{ end }} + {{ end }} + + {{ range $server := $servers }} + ## start server {{ $server.Hostname }} + server { + server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; + + {{ if $cfg.UseHTTP2 }} + http2 on; + {{ end }} + + {{ if gt (len $cfg.BlockUserAgents) 0 }} + if ($block_ua) { + return 403; + } + {{ end }} + {{ if gt (len $cfg.BlockReferers) 0 }} + if ($block_ref) { + return 403; + } + {{ end }} + + {{ template "SERVER" serverConfig $all $server }} + + {{ if not (empty $cfg.ServerSnippet) }} + # Custom code snippet configured in the configuration configmap + {{ $cfg.ServerSnippet }} + {{ end }} + + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics $cfg.EnableModsecurity) }} + } + ## end server {{ $server.Hostname }} + + {{ end }} + + # backend for when default-backend-service is not configured or it does not have endpoints + server { + listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; + {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} + set $proxy_upstream_name "internal"; + + access_log off; + + location / { + return 404; + } + } + + # default server, used for NGINX healthcheck and access to nginx stats + server { + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + + listen 127.0.0.1:{{ .StatusPort }}; + set $proxy_upstream_name "internal"; + + keepalive_timeout 0; + gzip off; + + access_log off; + + {{ if $cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + location {{ $healthzURI }} { + return 200; + } + + location /is-dynamic-lb-initialized { + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; + } + + location {{ .StatusPath }} { + stub_status on; + } + + location /configuration { + client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; + client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; + proxy_buffering off; + + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; + } + + location / { + return 404; + } + } +} + +stream { + lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;;"; + + lua_shared_dict tcp_udp_configuration_data 5M; + + {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} + + init_by_lua_file /etc/nginx/lua/ngx_conf_init_stream.lua; + + init_worker_by_lua_file /etc/nginx/lua/nginx/ngx_conf_init_tcp_udp.lua; + + lua_add_variable $proxy_upstream_name; + + log_format log_stream '{{ $cfg.LogFormatStream }}'; + + {{ if or $cfg.DisableAccessLog $cfg.DisableStreamAccessLog }} + access_log off; + {{ else }} + access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }}; + {{ end }} + + + error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; + {{ if $cfg.EnableRealIP }} + {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} + set_real_ip_from {{ $trusted_ip }}; + {{ end }} + {{ end }} + + upstream upstream_balancer { + server 0.0.0.1:1234; # placeholder + balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer_tcp_udp.lua; + } + + server { + listen 127.0.0.1:{{ .StreamPort }}; + + access_log off; + + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_content_tcp_udp.lua; + } + + # TCP services + {{ range $tcpServer := .TCPBackends }} + server { + preread_by_lua_block { + ngx.var.proxy_upstream_name="tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}"; + } + + {{ range $address := $all.Cfg.BindAddressIpv4 }} + listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ else }} + listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ end }} + {{ if $IsIPV6Enabled }} + {{ range $address := $all.Cfg.BindAddressIpv6 }} + listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ else }} + listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; + {{ end }} + {{ end }} + proxy_timeout {{ $cfg.ProxyStreamTimeout }}; + proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; + proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; + + proxy_pass upstream_balancer; + {{ if $tcpServer.Backend.ProxyProtocol.Encode }} + proxy_protocol on; + {{ end }} + } + {{ end }} + + # UDP services + {{ range $udpServer := .UDPBackends }} + server { + preread_by_lua_block { + ngx.var.proxy_upstream_name="udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}"; + } + + {{ range $address := $all.Cfg.BindAddressIpv4 }} + listen {{ $address }}:{{ $udpServer.Port }} udp; + {{ else }} + listen {{ $udpServer.Port }} udp; + {{ end }} + {{ if $IsIPV6Enabled }} + {{ range $address := $all.Cfg.BindAddressIpv6 }} + listen {{ $address }}:{{ $udpServer.Port }} udp; + {{ else }} + listen [::]:{{ $udpServer.Port }} udp; + {{ end }} + {{ end }} + proxy_responses {{ $cfg.ProxyStreamResponses }}; + proxy_timeout {{ $cfg.ProxyStreamTimeout }}; + proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; + proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; + proxy_pass upstream_balancer; + } + {{ end }} + + # Stream Snippets + {{ range $snippet := .StreamSnippets }} + {{ $snippet }} + {{ end }} +} + +{{/* definition of templates to avoid repetitions */}} +{{ define "CUSTOM_ERRORS" }} + {{ $enableMetrics := .EnableMetrics }} + {{ $modsecurityEnabled := .ModsecurityEnabled }} + {{ $upstreamName := .UpstreamName }} + {{ range $errCode := .ErrorCodes }} + location @custom_{{ $upstreamName }}_{{ $errCode }} { + internal; + + # Ensure that modsecurity will not run on custom error pages or they might be blocked + {{ if $modsecurityEnabled }} + modsecurity off; + {{ end }} + + proxy_intercept_errors off; + + proxy_set_header X-Code {{ $errCode }}; + proxy_set_header X-Format $http_accept; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Namespace $namespace; + proxy_set_header X-Ingress-Name $ingress_name; + proxy_set_header X-Service-Name $service_name; + proxy_set_header X-Service-Port $service_port; + proxy_set_header X-Request-ID $req_id; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $best_http_host; + + set $proxy_upstream_name {{ $upstreamName | quote }}; + + rewrite (.*) / break; + + proxy_pass http://upstream_balancer; + {{ if $enableMetrics }} + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; + {{ end }} + } + {{ end }} +{{ end }} + +{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} +{{ define "CORS" }} + {{ $cors := .CorsConfig }} + # Cors Preflight methods needs additional options and different Return Code + {{ if $cors.CorsAllowOrigin }} + {{ buildCorsOriginRegex $cors.CorsAllowOrigin }} + {{ end }} + if ($request_method = 'OPTIONS') { + set $cors ${cors}options; + } + + if ($cors = "true") { + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; + } + + if ($cors = "trueoptions") { + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; + more_set_headers 'Content-Type: text/plain charset=UTF-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } +{{ end }} + +{{/* definition of server-template to avoid repetitions with server-alias */}} +{{ define "SERVER" }} + {{ $all := .First }} + {{ $server := .Second }} + + {{ buildHTTPListener $all $server.Hostname }} + {{ buildHTTPSListener $all $server.Hostname }} + + set $proxy_upstream_name "-"; + + {{ if not ( empty $server.CertificateAuth.MatchCN ) }} + {{ if gt (len $server.CertificateAuth.MatchCN) 0 }} + if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { + return 403 "client certificate unauthorized"; + } + {{ end }} + {{ end }} + + {{ if eq $server.Hostname "_" }} + ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; + {{ end }} + + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; + + {{ if not (empty $server.AuthTLSError) }} + # {{ $server.AuthTLSError }} + return 403; + {{ else }} + + {{ if not (empty $server.CertificateAuth.CAFileName) }} + # PEM sha: {{ $server.CertificateAuth.CASHA }} + ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; + ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; + ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; + + {{ if not (empty $server.CertificateAuth.CRLFileName) }} + # PEM sha: {{ $server.CertificateAuth.CRLSHA }} + ssl_crl {{ $server.CertificateAuth.CRLFileName }}; + {{ end }} + + {{ if not (empty $server.CertificateAuth.ErrorPage)}} + error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; + {{ end }} + {{ end }} + + {{ if not (empty $server.ProxySSL.CAFileName) }} + # PEM sha: {{ $server.ProxySSL.CASHA }} + proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; + proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; + proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; + proxy_ssl_verify {{ $server.ProxySSL.Verify }}; + proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; + {{ if not (empty $server.ProxySSL.ProxySSLName) }} + proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; + proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; + {{ end }} + {{ end }} + + {{ if not (empty $server.ProxySSL.PemFileName) }} + proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; + proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; + {{ end }} + + {{ if not (empty $server.SSLCiphers) }} + ssl_ciphers {{ $server.SSLCiphers }}; + {{ end }} + + {{ if not (empty $server.SSLPreferServerCiphers) }} + ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; + {{ end }} + + {{ if not (empty $server.ServerSnippet) }} + # Custom code snippet configured for host {{ $server.Hostname }} + {{ $server.ServerSnippet }} + {{ end }} + + {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics $all.Cfg.EnableModsecurity) }} + {{ end }} + + {{ buildMirrorLocations $server.Locations }} + + {{ $enforceRegex := enforceRegexModifier $server.Locations }} + {{ range $location := $server.Locations }} + {{ $path := buildLocation $location $enforceRegex }} + {{ $proxySetHeader := proxySetHeader $location }} + {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + + {{ $externalAuth := $location.ExternalAuth }} + {{ if eq $applyGlobalAuth true }} + {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} + {{ end }} + + {{ if not (empty $location.Rewrite.AppRoot) }} + if ($uri = /) { + return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; + } + {{ end }} + + {{ if $authPath }} + location = {{ $authPath }} { + internal; + + {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} + opentelemetry on; + opentelemetry_propagate; + {{ end }} + + {{ if not $all.Cfg.EnableAuthAccessLog }} + access_log off; + {{ end }} + + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + + {{ if $externalAuth.AuthCacheKey }} + set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; + set $cache_key ''; + + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; + + proxy_cache auth_cache; + + {{- range $dur := $externalAuth.AuthCacheDuration }} + proxy_cache_valid {{ $dur }}; + {{- end }} + + proxy_cache_key "$cache_key"; + {{ end }} + + # ngx_auth_request module overrides variables in the parent request, + # therefore we have to explicitly set this variable again so that when the parent request + # resumes it has the correct value set for this variable so that Lua can pick backend correctly + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; + + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + proxy_set_header X-Forwarded-Proto ""; + proxy_set_header X-Request-ID $req_id; + + {{ if $externalAuth.Method }} + proxy_method {{ $externalAuth.Method }}; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Scheme $pass_access_scheme; + {{ end }} + + proxy_set_header Host {{ $externalAuth.Host }}; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Original-Method $request_method; + proxy_set_header X-Sent-From "nginx-ingress-controller"; + proxy_set_header X-Real-IP $remote_addr; + {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} + proxy_set_header X-Forwarded-For $full_x_forwarded_for; + {{ else }} + proxy_set_header X-Forwarded-For $remote_addr; + {{ end }} + + {{ if $externalAuth.RequestRedirect }} + proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; + {{ else }} + proxy_set_header X-Auth-Request-Redirect $request_uri; + {{ end }} + + {{ if $externalAuth.AuthCacheKey }} + proxy_buffering "on"; + {{ else }} + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; + {{ end }} + proxy_buffer_size {{ $location.Proxy.BufferSize }}; + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + + proxy_ssl_server_name on; + proxy_pass_request_headers on; + {{ if isValidByteSize $location.Proxy.BodySize true }} + client_max_body_size {{ $location.Proxy.BodySize }}; + {{ end }} + {{ if isValidByteSize $location.ClientBodyBufferSize false }} + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; + {{ end }} + + # Pass the extracted client certificate to the auth provider + {{ if not (empty $server.CertificateAuth.CAFileName) }} + {{ if $server.CertificateAuth.PassCertToUpstream }} + proxy_set_header ssl-client-cert $ssl_client_escaped_cert; + {{ end }} + proxy_set_header ssl-client-verify $ssl_client_verify; + proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; + proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; + {{ end }} + + {{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} + {{ $line }} + {{- end }} + + {{ if not (empty $externalAuth.AuthSnippet) }} + {{ $externalAuth.AuthSnippet }} + {{ end }} + + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} + # The target is an upstream with HTTP keepalive, that is why the + # Connection header is cleared and the HTTP version is set to 1.1 as + # the Nginx documentation suggests: + # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive + proxy_http_version 1.1; + proxy_set_header Connection ""; + set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; + {{ else }} + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; + set $target {{ $externalAuth.URL }}; + {{ end }} + proxy_pass $target; + } + {{ end }} + + {{ if isLocationAllowed $location }} + {{ if $externalAuth.SigninURL }} + location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { + internal; + + add_header Set-Cookie $auth_cookie; + + {{ if $location.CorsConfig.CorsEnabled }} + {{ template "CORS" $location }} + {{ end }} + + # Ensure that modsecurity will not run on an internal location as this is not accessible from outside + {{ if $all.Cfg.EnableModsecurity }} + modsecurity off; + {{ end }} + + return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; + } + {{ end }} + {{ end }} + + location {{ $path }} { + {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} + set $namespace {{ $ing.Namespace | quote}}; + set $ingress_name {{ $ing.Rule | quote }}; + set $service_name {{ $ing.Service | quote }}; + set $service_port {{ $ing.ServicePort | quote }}; + set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; + + {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} + + {{ if $location.Mirror.Source }} + mirror {{ $location.Mirror.Source }}; + mirror_request_body {{ $location.Mirror.RequestBody }}; + {{ end }} + + {{ locationConfigForLua $location $all }} + + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; + + header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; + + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; + + {{ if not $location.Logs.Access }} + access_log off; + {{ end }} + + {{ if $location.Logs.Rewrite }} + rewrite_log on; + {{ end }} + + {{ if $location.HTTP2PushPreload }} + http2_push_preload on; + {{ end }} + + port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; + + set $balancer_ewma_score -1; + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; + set $proxy_host $proxy_upstream_name; + set $pass_access_scheme $scheme; + + {{ if $all.Cfg.UseProxyProtocol }} + set $pass_server_port $proxy_protocol_server_port; + {{ else }} + set $pass_server_port $server_port; + {{ end }} + + set $best_http_host $http_host; + set $pass_port $pass_server_port; + + set $proxy_alternative_upstream_name ""; + + {{ buildModSecurityForLocation $all.Cfg $location }} + + {{ if isLocationAllowed $location }} + {{ if gt (len $location.Denylist.CIDR) 0 }} + {{ range $ip := $location.Denylist.CIDR }} + deny {{ $ip }};{{ end }} + {{ end }} + {{ if gt (len $location.Allowlist.CIDR) 0 }} + {{ range $ip := $location.Allowlist.CIDR }} + allow {{ $ip }};{{ end }} + deny all; + {{ end }} + + {{ if $location.CorsConfig.CorsEnabled }} + {{ template "CORS" $location }} + {{ end }} + + {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} + {{ if $authPath }} + # this location requires authentication + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + set $auth_cookie ''; + add_header Set-Cookie $auth_cookie; + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} + {{ $line }} + {{- end }} + # `auth_request` module does not support HTTP keepalives in upstream block: + # https://trac.nginx.org/nginx/ticket/1579 + access_by_lua_block { + local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) + if res.status == ngx.HTTP_OK then + ngx.var.auth_cookie = res.header['Set-Cookie'] + {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} + {{ $line }} + {{- end }} + return + end + if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then + ngx.exit(res.status) + end + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) + } + {{ else }} + auth_request {{ $authPath }}; + auth_request_set $auth_cookie $upstream_http_set_cookie; + {{ if $externalAuth.AlwaysSetCookie }} + add_header Set-Cookie $auth_cookie always; + {{ else }} + add_header Set-Cookie $auth_cookie; + {{ end }} + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} + {{ $line }} + {{- end }} + {{ end }} + {{ end }} + + {{ if $externalAuth.SigninURL }} + set_escape_uri $escaped_request_uri $request_uri; + error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; + {{ end }} + + {{ if $location.BasicDigestAuth.Secured }} + {{ if eq $location.BasicDigestAuth.Type "basic" }} + auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; + auth_basic_user_file {{ $location.BasicDigestAuth.File }}; + {{ else }} + auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; + auth_digest_user_file {{ $location.BasicDigestAuth.File }}; + {{ end }} + {{ $proxySetHeader }} Authorization ""; + {{ end }} + {{ end }} + + {{/* if the location contains a rate limit annotation, create one */}} + {{ $limits := buildRateLimit $location }} + {{ range $limit := $limits }} + {{ $limit }}{{ end }} + + {{ if isValidByteSize $location.Proxy.BodySize true }} + client_max_body_size {{ $location.Proxy.BodySize }}; + {{ end }} + {{ if isValidByteSize $location.ClientBodyBufferSize false }} + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; + {{ end }} + + {{/* By default use vhost as Host to upstream, but allow overrides */}} + {{ if not (empty $location.UpstreamVhost) }} + {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; + {{ else }} + {{ $proxySetHeader }} Host $best_http_host; + {{ end }} + + # Pass the extracted client certificate to the backend + {{ if not (empty $server.CertificateAuth.CAFileName) }} + {{ if $server.CertificateAuth.PassCertToUpstream }} + {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; + {{ end }} + {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; + {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; + {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; + {{ end }} + + # Allow websocket connections + {{ $proxySetHeader }} Upgrade $http_upgrade; + {{ if $location.Connection.Enabled}} + {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; + {{ else }} + {{ $proxySetHeader }} Connection $connection_upgrade; + {{ end }} + + {{ $proxySetHeader }} X-Request-ID $req_id; + {{ $proxySetHeader }} X-Real-IP $remote_addr; + {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} + {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; + {{ else }} + {{ $proxySetHeader }} X-Forwarded-For $remote_addr; + {{ end }} + {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; + {{ $proxySetHeader }} X-Forwarded-Port $pass_port; + {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; + {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; + {{ if $all.Cfg.ProxyAddOriginalURIHeader }} + {{ $proxySetHeader }} X-Original-URI $request_uri; + {{ end }} + {{ $proxySetHeader }} X-Scheme $pass_access_scheme; + + # Pass the original X-Forwarded-For + {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; + + # mitigate HTTPoxy Vulnerability + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ + {{ $proxySetHeader }} Proxy ""; + + # Custom headers to proxied server + {{ range $k, $v := $all.ProxySetHeaders }} + {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; + {{ end }} + + proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; + proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; + proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; + + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; + proxy_buffer_size {{ $location.Proxy.BufferSize }}; + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; + {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} + proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; + {{ end }} + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; + + proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; + proxy_cookie_path {{ $location.Proxy.CookiePath }}; + + # In case of errors try the next upstream server before returning an error + proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; + proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; + proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; + + {{ if or (eq $location.BackendProtocol "GRPC") (eq $location.BackendProtocol "GRPCS") }} + # Grpc settings + grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; + grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; + grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; + {{ end }} + + {{/* Add any additional configuration defined */}} + {{ $location.ConfigurationSnippet }} + + {{ if not (empty $all.Cfg.LocationSnippet) }} + # Custom code snippet configured in the configuration configmap + {{ $all.Cfg.LocationSnippet }} + {{ end }} + + {{ if $location.CustomHeaders }} + # Custom Response Headers + {{ range $k, $v := $location.CustomHeaders.Headers }} + more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; + {{ end }} + {{ end }} + + {{/* if we are sending the request to a custom default backend, we add the required headers */}} + {{ if (hasPrefix $location.Backend "custom-default-backend-") }} + proxy_set_header X-Code 503; + proxy_set_header X-Format $http_accept; + proxy_set_header X-Namespace $namespace; + proxy_set_header X-Ingress-Name $ingress_name; + proxy_set_header X-Service-Name $service_name; + proxy_set_header X-Service-Port $service_port; + proxy_set_header X-Request-ID $req_id; + {{ end }} + + {{ if $location.Satisfy }} + satisfy {{ $location.Satisfy }}; + {{ end }} + + {{/* if a location-specific error override is set, add the proxy_intercept here */}} + {{ if and $location.CustomHTTPErrors (not $location.DisableProxyInterceptErrors) }} + # Custom error pages per ingress + proxy_intercept_errors on; + {{ end }} + + {{ range $errCode := $location.CustomHTTPErrors }} + error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} + + {{ if (eq $location.BackendProtocol "FCGI") }} + include /etc/nginx/fastcgi_params; + {{ end }} + {{- if $location.FastCGI.Index -}} + fastcgi_index {{ $location.FastCGI.Index | quote }}; + {{- end -}} + {{ range $k, $v := $location.FastCGI.Params }} + fastcgi_param {{ $k }} {{ $v | quote }}; + {{ end }} + + {{ if not (empty $location.Redirect.URL) }} + return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; + {{ end }} + + {{ buildProxyPass $server.Hostname $all.Backends $location }} + {{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; + {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; + {{ end }} + {{ else }} + # Location denied. Reason: {{ $location.Denied | quote }} + return 503; + {{ end }} + {{ if not (empty $location.ProxySSL.CAFileName) }} + # PEM sha: {{ $location.ProxySSL.CASHA }} + proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; + proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; + proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; + proxy_ssl_verify {{ $location.ProxySSL.Verify }}; + proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; + {{ end }} + + {{ if not (empty $location.ProxySSL.ProxySSLName) }} + proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; + {{ end }} + {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} + proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; + {{ end }} + + {{ if not (empty $location.ProxySSL.PemFileName) }} + proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; + proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; + {{ end }} + } + {{ end }} + {{ end }} + + {{ if eq $server.Hostname "_" }} + # health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} + location {{ $all.HealthzURI }} { + + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + + access_log off; + return 200; + } + + # this is required to avoid error if nginx is being monitored + # with an external software (like sysdig) + location /nginx_status { + + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + + {{ range $v := $all.NginxStatusIpv4Whitelist }} + allow {{ $v }}; + {{ end }} + {{ if $all.IsIPV6Enabled -}} + {{ range $v := $all.NginxStatusIpv6Whitelist }} + allow {{ $v }}; + {{ end }} + {{ end -}} + deny all; + + access_log off; + stub_status on; + } + + {{ end }} + +{{ end }} diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index b10363a6fa..2b1b3a2dfc 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -25,6 +25,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/controller/config" ing_net "k8s.io/ingress-nginx/internal/net" + "k8s.io/ingress-nginx/pkg/apis/ingress" ) type seconds int @@ -112,3 +113,31 @@ func dictKbToStr(size int) string { } return fmt.Sprintf("%dK", size) } + +func shouldLoadAuthDigestModule(servers []*ingress.Server) bool { + for _, server := range servers { + for _, location := range server.Locations { + if !location.BasicDigestAuth.Secured { + continue + } + + if location.BasicDigestAuth.Type == "digest" { + return true + } + } + } + return false +} + +// shouldLoadOpentelemetryModule determines whether or not the Opentelemetry module needs to be loaded. +// It checks if `enable-opentelemetry` is set in the ConfigMap. +func shouldLoadOpentelemetryModule(servers []*ingress.Server) bool { + for _, server := range servers { + for _, location := range server.Locations { + if location.Opentelemetry.Enabled { + return true + } + } + } + return false +} diff --git a/magefiles/go.mod b/magefiles/go.mod index ae3732ea7d..0a43081049 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -8,29 +8,30 @@ require ( github.com/helm/helm v2.17.0+incompatible github.com/magefile/mage v1.15.0 github.com/vmware-labs/yaml-jsonpath v0.3.2 - golang.org/x/oauth2 v0.22.0 + golang.org/x/oauth2 v0.23.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/BurntSushi/toml v1.3.2 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.4 // indirect github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/gomega v1.34.1 // indirect + github.com/onsi/gomega v1.34.2 // indirect github.com/sergi/go-diff v1.3.1 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/net v0.28.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.31.0 // indirect + k8s.io/apimachinery v0.31.2 // indirect k8s.io/helm v2.17.0+incompatible // indirect ) diff --git a/magefiles/go.sum b/magefiles/go.sum index 9e3b9d2783..17ba71e9ff 100644 --- a/magefiles/go.sum +++ b/magefiles/go.sum @@ -5,8 +5,7 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -14,8 +13,7 @@ github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 h1:aRd8M7HJVZOqn/v github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -64,7 +62,7 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= @@ -82,16 +80,15 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -104,10 +101,10 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -139,6 +136,6 @@ gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/helm v2.17.0+incompatible h1:Bpn6o1wKLYqKM3+Osh8e+1/K2g/GsQJ4F4yNF2+deao= k8s.io/helm v2.17.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= From 47375b471a3b4be27fd69b3e3c871d167ee6bcf0 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Sun, 15 Sep 2024 19:21:34 -0300 Subject: [PATCH 09/16] Bootstrap server configs and a bunch of other configs --- go.mod | 2 +- go.work.sum | 1 - internal/ingress/controller/nginx.go | 12 +- .../template/crossplane/authlocation.go | 251 ++++ .../controller/template/crossplane/cors.go | 81 ++ .../template/crossplane/crossplane.go | 50 +- .../crossplane/crossplane_internal_test.go | 10 +- .../crossplane_internal_utils_test.go | 34 + .../template/crossplane/crossplane_test.go | 191 +++- .../controller/template/crossplane/events.go | 2 +- .../crossplane/extramodules/README.md | 2 +- .../crossplane/extramodules/opentelemetry.go | 71 ++ .../controller/template/crossplane/http.go | 113 +- .../template/crossplane/location.go | 756 +++++++++++++ .../controller/template/crossplane/server.go | 268 +++++ .../crossplane/testdata/nginx-new.tmpl | 1005 +++++++---------- .../controller/template/crossplane/utils.go | 595 ++++++++++ test/e2e-image/e2e.sh | 2 +- test/e2e/admission/admission.go | 9 + test/e2e/annotations/affinity.go | 27 +- test/e2e/annotations/affinitymode.go | 4 +- test/e2e/annotations/auth.go | 15 +- test/e2e/annotations/canary.go | 17 +- test/e2e/annotations/cors.go | 25 +- test/e2e/annotations/fastcgi.go | 9 +- test/e2e/annotations/fromtowwwredirect.go | 13 +- test/e2e/annotations/http2pushpreload.go | 4 + test/e2e/annotations/limitconnections.go | 2 +- test/e2e/annotations/mirror.go | 3 +- .../annotations/modsecurity/modsecurity.go | 3 + test/e2e/annotations/rewrite.go | 13 +- test/e2e/annotations/serversnippet.go | 3 + test/e2e/annotations/snippet.go | 3 + test/e2e/annotations/streamsnippet.go | 3 + test/e2e/annotations/upstreamhashby.go | 2 +- test/e2e/annotations/upstreamvhost.go | 3 +- test/e2e/annotations/xforwardedprefix.go | 3 +- .../defaultbackend/custom_default_backend.go | 3 +- test/e2e/framework/framework.go | 8 +- test/e2e/ingress/multiple_rules.go | 34 +- test/e2e/ingress/pathtype_exact.go | 51 +- test/e2e/ingress/pathtype_mixed.go | 79 +- test/e2e/ingress/without_host.go | 20 +- test/e2e/lua/dynamic_configuration.go | 2 +- test/e2e/metrics/metrics.go | 2 +- test/e2e/run-e2e-suite.sh | 1 + test/e2e/run-kind-e2e.sh | 2 + test/e2e/security/request_smuggling.go | 3 + test/e2e/settings/access_log.go | 16 + test/e2e/settings/badannotationvalues.go | 11 +- test/e2e/settings/configmap_change.go | 21 +- test/e2e/settings/custom_header.go | 6 +- test/e2e/settings/default_ssl_certificate.go | 7 +- test/e2e/settings/disable_catch_all.go | 6 +- test/e2e/settings/global_external_auth.go | 3 + test/e2e/settings/gzip.go | 2 +- test/e2e/settings/limit_rate.go | 2 +- test/e2e/settings/main_snippet.go | 3 + .../modsecurity/modsecurity_snippet.go | 3 + .../e2e/settings/no_tls_redirect_locations.go | 4 +- test/e2e/settings/proxy_host.go | 27 +- test/e2e/settings/proxy_protocol.go | 3 + test/e2e/settings/server_snippet.go | 3 + test/e2e/settings/ssl_ciphers.go | 2 +- test/e2e/settings/ssl_passthrough.go | 3 + test/e2e/settings/stream_snippet.go | 3 + test/e2e/settings/tls.go | 2 +- test/e2e/tcpudp/tcp.go | 3 + 68 files changed, 3132 insertions(+), 810 deletions(-) delete mode 100644 go.work.sum create mode 100644 internal/ingress/controller/template/crossplane/authlocation.go create mode 100644 internal/ingress/controller/template/crossplane/cors.go create mode 100644 internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go create mode 100644 internal/ingress/controller/template/crossplane/location.go create mode 100644 internal/ingress/controller/template/crossplane/server.go diff --git a/go.mod b/go.mod index b6a7c274d8..52ec37fbc7 100644 --- a/go.mod +++ b/go.mod @@ -135,7 +135,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/gengo/v2 v2.0.0-20240404160639-a0386bf69313 // indirect k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.17.2 // indirect sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index d1535915af..0000000000 --- a/go.work.sum +++ /dev/null @@ -1 +0,0 @@ -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index 20fad5afb8..6f138d7540 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -52,6 +52,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/controller/process" "k8s.io/ingress-nginx/internal/ingress/controller/store" ngx_template "k8s.io/ingress-nginx/internal/ingress/controller/template" + "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane" "k8s.io/ingress-nginx/internal/ingress/metric" "k8s.io/ingress-nginx/internal/ingress/status" ing_net "k8s.io/ingress-nginx/internal/net" @@ -158,7 +159,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro } onTemplateChange := func() { - template, err := ngx_template.NewTemplate(nginx.TemplatePath) + template, err := crossplane.NewTemplate() if err != nil { // this error is different from the rest because it must be clear why nginx is not working klog.ErrorS(err, "Error loading new template") @@ -170,7 +171,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro n.syncQueue.EnqueueTask(task.GetDummyObject("template-change")) } - ngxTpl, err := ngx_template.NewTemplate(nginx.TemplatePath) + ngxTpl, err := crossplane.NewTemplate() if err != nil { klog.Fatalf("Invalid NGINX configuration template: %v", err) } @@ -700,7 +701,7 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error { err = n.testTemplate(content) if err != nil { - return err + return fmt.Errorf("err %s content %s", err, string(content)) } if klog.V(2).Enabled() { @@ -868,13 +869,14 @@ func (n *NGINXController) configureDynamically(pcfg *ingress.Configuration) erro } } - streamConfigurationChanged := !reflect.DeepEqual(n.runningConfig.TCPEndpoints, pcfg.TCPEndpoints) || !reflect.DeepEqual(n.runningConfig.UDPEndpoints, pcfg.UDPEndpoints) + // TODO: (ricardo) - Disable in case this is crossplane, we don't support stream on this mode + /*streamConfigurationChanged := !reflect.DeepEqual(n.runningConfig.TCPEndpoints, pcfg.TCPEndpoints) || !reflect.DeepEqual(n.runningConfig.UDPEndpoints, pcfg.UDPEndpoints) if streamConfigurationChanged { err := updateStreamConfiguration(pcfg.TCPEndpoints, pcfg.UDPEndpoints) if err != nil { return err } - } + }*/ serversChanged := !reflect.DeepEqual(n.runningConfig.Servers, pcfg.Servers) if serversChanged { diff --git a/internal/ingress/controller/template/crossplane/authlocation.go b/internal/ingress/controller/template/crossplane/authlocation.go new file mode 100644 index 0000000000..64c15eeb65 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/authlocation.go @@ -0,0 +1,251 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + "strings" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + "k8s.io/ingress-nginx/internal/ingress/annotations/authreq" + "k8s.io/ingress-nginx/internal/ingress/controller/config" + "k8s.io/ingress-nginx/pkg/apis/ingress" +) + +type externalAuth struct { + URL string `json:"url"` + // Host contains the hostname defined in the URL + Host string `json:"host"` + SigninURL string `json:"signinUrl"` + SigninURLRedirectParam string `json:"signinUrlRedirectParam,omitempty"` + Method string `json:"method"` + ResponseHeaders []string `json:"responseHeaders,omitempty"` + RequestRedirect string `json:"requestRedirect"` + AuthSnippet string `json:"authSnippet"` + AuthCacheKey string `json:"authCacheKey"` + AuthCacheDuration []string `json:"authCacheDuration"` + KeepaliveConnections int `json:"keepaliveConnections"` + KeepaliveShareVars bool `json:"keepaliveShareVars"` + KeepaliveRequests int `json:"keepaliveRequests"` + KeepaliveTimeout int `json:"keepaliveTimeout"` + ProxySetHeaders map[string]string `json:"proxySetHeaders,omitempty"` + AlwaysSetCookie bool `json:"alwaysSetCookie,omitempty"` +} + +func buildExternalAuth(cfg any) *externalAuth { + switch v := cfg.(type) { + case config.GlobalExternalAuth: + return &externalAuth{ + AlwaysSetCookie: v.AlwaysSetCookie, + AuthCacheKey: v.AuthCacheKey, + AuthCacheDuration: v.AuthCacheDuration, + Method: v.Method, + Host: v.Host, + RequestRedirect: v.RequestRedirect, + ProxySetHeaders: v.ProxySetHeaders, + ResponseHeaders: v.ResponseHeaders, + URL: v.URL, + SigninURL: v.SigninURL, + SigninURLRedirectParam: v.SigninURLRedirectParam, + } + case authreq.Config: + return &externalAuth{ + AlwaysSetCookie: v.AlwaysSetCookie, + AuthCacheKey: v.AuthCacheKey, + AuthCacheDuration: v.AuthCacheDuration, + Method: v.Method, + Host: v.Host, + RequestRedirect: v.RequestRedirect, + ProxySetHeaders: v.ProxySetHeaders, + ResponseHeaders: v.ResponseHeaders, + URL: v.URL, + SigninURL: v.SigninURL, + SigninURLRedirectParam: v.SigninURLRedirectParam, + KeepaliveShareVars: v.KeepaliveShareVars, + KeepaliveConnections: v.KeepaliveConnections, + KeepaliveRequests: v.KeepaliveRequests, + KeepaliveTimeout: v.KeepaliveTimeout, + } + default: + return nil + } +} + +func (c *Template) buildAuthLocation(server *ingress.Server, + location *ingress.Location, locationConfig locationCfg) *ngx_crossplane.Directive { + locationDirectives := ngx_crossplane.Directives{ + buildDirective("internal"), + } + + if c.tplConfig.Cfg.EnableOpentelemetry || location.Opentelemetry.Enabled { + locationDirectives = append(locationDirectives, + buildDirective("opentelemetry", "on"), + buildDirective("opentelemetry_propagate"), + ) + } + + if !c.tplConfig.Cfg.EnableAuthAccessLog { + locationDirectives = append(locationDirectives, buildDirective("access_log", "off")) + } + + if locationConfig.externalAuth.AuthCacheKey != "" { + locationDirectives = append(locationDirectives, + buildDirective("set", "$tmp_cache_key", fmt.Sprintf("%s%s%s", server.Hostname, locationConfig.authPath, locationConfig.externalAuth.AuthCacheKey)), + buildDirective("set", "$cache_key", ""), + buildDirective("rewrite_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua"), + buildDirective("proxy_cache", "auth_cache"), + buildDirective("proxy_cache_key", "$cache_key"), + ) + for i := range locationConfig.externalAuth.AuthCacheDuration { + locationDirectives = append(locationDirectives, + buildDirective("proxy_cache_valid", strings.Split(locationConfig.externalAuth.AuthCacheDuration[i], " ")), + ) + } + } + + /* + ngx_auth_request module overrides variables in the parent request, + therefore we have to explicitly set this variable again so that when the parent request + resumes it has the correct value set for this variable so that Lua can pick backend correctly + */ + locationDirectives = append(locationDirectives, + buildDirective("set", "$proxy_upstream_name", location.Backend), + ) + + locationDirectives = append(locationDirectives, + buildDirective("proxy_pass_request_body", "off")) + + locationDirectives = append(locationDirectives, + buildDirective("proxy_ssl_server_name", "on")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_pass_request_headers", "on")) + + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "Content-Length", "")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Forwarded-Proto", "")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Request-ID", "$req_id")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "Host", locationConfig.externalAuth.Host)) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Original-URL", "$scheme://$http_host$request_uri")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Original-Method", "$request_method")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Sent-From", "nginx-ingress-controller")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Real-IP", "$remote_addr")) + + if locationConfig.externalAuth.Method != "" { + locationDirectives = append(locationDirectives, + buildDirective("proxy_method", locationConfig.externalAuth.Method)) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Original-URI", "$request_uri")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Scheme", "$pass_access_scheme")) + } + + if c.tplConfig.Cfg.UseForwardedHeaders && c.tplConfig.Cfg.ComputeFullForwardedFor { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Forwarded-For", "$full_x_forwarded_for")) + } else { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Forwarded-For", "$remote_addr")) + } + + if locationConfig.externalAuth.RequestRedirect != "" { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Auth-Request-Redirect", locationConfig.externalAuth.RequestRedirect)) + } else { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Auth-Request-Redirect", "$request_uri")) + } + + if locationConfig.externalAuth.Method != "" { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Original-URI", "$request_uri")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Scheme", "$pass_access_scheme")) + } + + if locationConfig.externalAuth.AuthCacheKey != "" { + locationDirectives = append(locationDirectives, + buildDirective("proxy_buffering", "on")) + } else { + locationDirectives = append(locationDirectives, + buildDirective("proxy_buffering", location.Proxy.ProxyBuffering)) + } + + locationDirectives = append(locationDirectives, + buildDirective("proxy_buffer_size", location.Proxy.BufferSize)) + locationDirectives = append(locationDirectives, + buildDirective("proxy_buffers", location.Proxy.BuffersNumber, location.Proxy.BufferSize)) + locationDirectives = append(locationDirectives, + buildDirective("proxy_request_buffering", location.Proxy.RequestBuffering)) + + if isValidByteSize(location.Proxy.BodySize, true) { + locationDirectives = append(locationDirectives, + buildDirective("client_max_body_size", location.Proxy.BodySize)) + } + + if isValidByteSize(location.ClientBodyBufferSize, false) { + locationDirectives = append(locationDirectives, + buildDirective("client_body_buffer_size", location.ClientBodyBufferSize)) + } + + if server.CertificateAuth.CAFileName != "" { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "ssl-client-verify", "$ssl_client_verify")) + + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "ssl-client-subject-dn", "$ssl_client_s_dn")) + + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "ssl-client-issuer-dn", "$ssl_client_i_dn")) + + if server.CertificateAuth.PassCertToUpstream { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "ssl-client-cert", "$ssl_client_escaped_cert")) + } + } + + for name, value := range locationConfig.externalAuth.ProxySetHeaders { + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", name, value)) + } + + if locationConfig.applyAuthUpstream && locationConfig.applyGlobalAuth { + locationDirectives = append(locationDirectives, + buildDirective("proxy_http_version", "1.1")) + locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "Connection", "")) + locationDirectives = append(locationDirectives, + buildDirective("set", "$target", + changeHostPort(locationConfig.externalAuth.URL, buildAuthUpstreamName(location, server.Hostname)))) + } else { + locationDirectives = append(locationDirectives, + buildDirective("proxy_http_version", location.Proxy.ProxyHTTPVersion)) + locationDirectives = append(locationDirectives, + buildDirective("set", "$target", locationConfig.externalAuth.URL)) + } + locationDirectives = append(locationDirectives, + buildDirective("proxy_pass", "$target")) + + return buildBlockDirective("location", + []string{"=", locationConfig.authPath}, locationDirectives) +} diff --git a/internal/ingress/controller/template/crossplane/cors.go b/internal/ingress/controller/template/crossplane/cors.go new file mode 100644 index 0000000000..932c2489bf --- /dev/null +++ b/internal/ingress/controller/template/crossplane/cors.go @@ -0,0 +1,81 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + "k8s.io/ingress-nginx/internal/ingress/annotations/cors" +) + +func buildCorsDirectives(locationcors cors.Config) ngx_crossplane.Directives { + directives := make(ngx_crossplane.Directives, 0) + if len(locationcors.CorsAllowOrigin) > 0 { + directives = append(directives, buildCorsOriginRegex(locationcors.CorsAllowOrigin)...) + + } + directives = append(directives, + buildBlockDirective("if", + []string{"$request_method", "=", "OPTIONS"}, ngx_crossplane.Directives{ + buildDirective("set", "$cors", "${cors}options"), + }, + ), + ) + + directives = append(directives, + commonCorsDirective(locationcors, false), + commonCorsDirective(locationcors, true), + ) + return directives +} + +// commonCorsDirective builds the common cors directives for a location +func commonCorsDirective(cfg cors.Config, options bool) *ngx_crossplane.Directive { + corsDir := "true" + if options { + corsDir = "trueoptions" + } + corsBlock := buildBlockDirective("if", []string{"$cors", "=", corsDir}, + ngx_crossplane.Directives{ + buildDirective("more_set_headers", "Access-Control-Allow-Origin: $http_origin"), + buildDirective("more_set_headers", fmt.Sprintf("Access-Control-Allow-Methods: %s", cfg.CorsAllowMethods)), + buildDirective("more_set_headers", fmt.Sprintf("Access-Control-Allow-Headers: %s", cfg.CorsAllowHeaders)), + buildDirective("more_set_headers", fmt.Sprintf("Access-Control-Max-Age: %d", cfg.CorsMaxAge)), + }, + ) + + if cfg.CorsAllowCredentials { + corsBlock.Block = append(corsBlock.Block, + buildDirective("more_set_headers", fmt.Sprintf("Access-Control-Allow-Credentials: %t", cfg.CorsAllowCredentials)), + ) + } + if cfg.CorsExposeHeaders != "" { + corsBlock.Block = append(corsBlock.Block, + buildDirective("more_set_headers", fmt.Sprintf("Access-Control-Expose-Headers: %s", cfg.CorsExposeHeaders)), + ) + } + + if options { + corsBlock.Block = append(corsBlock.Block, + buildDirective("more_set_headers", "Content-Type: text/plain charset=UTF-8"), + buildDirective("more_set_headers", "Content-Length: 0"), + buildDirective("return", "204"), + ) + } + return corsBlock +} diff --git a/internal/ingress/controller/template/crossplane/crossplane.go b/internal/ingress/controller/template/crossplane/crossplane.go index 1307de2f7a..13796fdb8d 100644 --- a/internal/ingress/controller/template/crossplane/crossplane.go +++ b/internal/ingress/controller/template/crossplane/crossplane.go @@ -18,10 +18,12 @@ package crossplane import ( "bytes" + "os" ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" "k8s.io/ingress-nginx/internal/ingress/controller/config" + "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane/extramodules" ) /* @@ -41,7 +43,7 @@ type Template struct { mimeFile string } -func NewTemplate() *Template { +func NewTemplate() (*Template, error) { lua := ngx_crossplane.Lua{} return &Template{ mimeFile: "/etc/nginx/mime.types", @@ -50,7 +52,7 @@ func NewTemplate() *Template { lua.RegisterBuilder(), }, }, - } + }, nil } func (c *Template) SetMimeFile(file string) { @@ -72,5 +74,49 @@ func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) { var buf bytes.Buffer err := ngx_crossplane.Build(&buf, *c.config, &ngx_crossplane.BuildOptions{}) + if err != nil { + return nil, err + } + + lua := ngx_crossplane.Lua{} + options := ngx_crossplane.ParseOptions{ + ParseComments: true, + ErrorOnUnknownDirectives: true, + StopParsingOnError: true, + DirectiveSources: []ngx_crossplane.MatchFunc{ + ngx_crossplane.DefaultDirectivesMatchFunc, + ngx_crossplane.MatchLuaLatest, + ngx_crossplane.MatchHeadersMoreLatest, + extramodules.BrotliMatchFn, + extramodules.OpentelemetryMatchFn, + ngx_crossplane.MatchGeoip2Latest, + }, + LexOptions: ngx_crossplane.LexOptions{ + Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, + }, + // Modules that needs to be ported: + // // https://github.com/openresty/set-misc-nginx-module?tab=readme-ov-file#set_escape_uri + IgnoreDirectives: []string{"set_escape_uri"}, + } + + tmpFile, err := os.CreateTemp("", "") + if err != nil { + return nil, err + } + defer func() { + _ = os.Remove(tmpFile.Name()) + _ = tmpFile.Close() + }() + + _, err = tmpFile.Write(buf.Bytes()) + if err != nil { + return nil, err + } + + _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) + if err != nil { + return nil, err + } + return buf.Bytes(), err } diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go index b8bc3258d0..73093c1a8e 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_internal_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_test.go @@ -41,14 +41,15 @@ func Test_Internal_buildEvents(t *testing.T) { Directive: "events", Block: ngx_crossplane.Directives{ buildDirective("worker_connections", 16384), - buildDirective("use", "epool"), + buildDirective("use", "epoll"), buildDirective("multi_accept", true), }, }, }, } - cplane := NewTemplate() + cplane, err := NewTemplate() + require.NoError(t, err) cplane.config = &c cplane.tplConfig = tplConfig cplane.buildEvents() @@ -72,7 +73,7 @@ func Test_Internal_buildEvents(t *testing.T) { Directive: "events", Block: ngx_crossplane.Directives{ buildDirective("worker_connections", 50), - buildDirective("use", "epool"), + buildDirective("use", "epoll"), buildDirective("multi_accept", false), buildDirective("debug_connection", "127.0.0.1/32"), buildDirective("debug_connection", "192.168.0.10"), @@ -81,7 +82,8 @@ func Test_Internal_buildEvents(t *testing.T) { }, } - cplane := NewTemplate() + cplane, err := NewTemplate() + require.NoError(t, err) cplane.config = &c cplane.tplConfig = tplConfig cplane.buildEvents() diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go index f31701781d..b5c2b69627 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go @@ -17,6 +17,7 @@ limitations under the License. package crossplane import ( + "reflect" "testing" ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" @@ -67,3 +68,36 @@ func Test_Internal_buildLuaDictionaries(t *testing.T) { require.Equal(t, "lua_shared_dict", directives[1].Directive) require.Equal(t, []string{"otherdict", "1025K"}, directives[1].Args) } + +func Test_Internal_buildCorsOriginRegex(t *testing.T) { + tests := []struct { + name string + corsOrigins []string + want ngx_crossplane.Directives + }{ + { + name: "wildcard returns a single directive", + corsOrigins: []string{"*"}, + want: ngx_crossplane.Directives{ + buildDirective("set", "$http_origin", "*"), + buildDirective("set", "$cors", "true"), + }, + }, + { + name: "multiple hosts should be changed properly", + corsOrigins: []string{"*.xpto.com", " lalala.com"}, + want: ngx_crossplane.Directives{ + buildBlockDirective("if", []string{"$http_origin", "~*", "([A-Za-z0-9\\-]+\\.xpto\\.com)", "|", "(lalala\\.com)"}, + ngx_crossplane.Directives{buildDirective("set", "$cors", "true")}, + ), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := buildCorsOriginRegex(tt.corsOrigins); !reflect.DeepEqual(got, tt.want) { + t.Errorf("buildCorsOriginRegex() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 08ea94276d..3d3fa745dd 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -24,10 +24,18 @@ import ( ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" "github.com/stretchr/testify/require" + "k8s.io/ingress-nginx/internal/ingress/annotations/authreq" + "k8s.io/ingress-nginx/internal/ingress/annotations/authtls" + "k8s.io/ingress-nginx/internal/ingress/annotations/cors" + "k8s.io/ingress-nginx/internal/ingress/annotations/mirror" + "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" + "k8s.io/ingress-nginx/internal/ingress/annotations/proxyssl" "k8s.io/ingress-nginx/internal/ingress/controller/config" "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane" "k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane/extramodules" + "k8s.io/ingress-nginx/internal/ingress/resolver" "k8s.io/ingress-nginx/pkg/apis/ingress" + utilingress "k8s.io/ingress-nginx/pkg/util/ingress" ) const mockMimeTypes = ` @@ -38,6 +46,28 @@ types { } ` +func defaultConfig() *config.TemplateConfig { + tplConfig := &config.TemplateConfig{ + Cfg: config.NewDefault(), + } + tplConfig.ListenPorts = &config.ListenPorts{ + HTTP: 80, + HTTPS: 443, + Health: 10245, + Default: 8080, + SSLProxy: 442, + } + defaultCertificate := &ingress.SSLCert{ + PemFileName: "bla.crt", + PemCertKey: "bla.key", + } + tplConfig.StatusPort = 10246 + tplConfig.StatusPath = "/status" + tplConfig.HealthzURI = "/healthz" + tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + return tplConfig +} + var resolvers = []net.IP{net.ParseIP("::1"), net.ParseIP("192.168.20.10")} // TestTemplate should be a roundtrip test. @@ -48,21 +78,21 @@ var resolvers = []net.IP{net.ParseIP("::1"), net.ParseIP("192.168.20.10")} func TestCrossplaneTemplate(t *testing.T) { lua := ngx_crossplane.Lua{} options := ngx_crossplane.ParseOptions{ + ParseComments: true, ErrorOnUnknownDirectives: true, StopParsingOnError: true, - IgnoreDirectives: []string{"more_clear_headers", "more_set_headers"}, // TODO: Add more_set_headers DirectiveSources: []ngx_crossplane.MatchFunc{ ngx_crossplane.DefaultDirectivesMatchFunc, ngx_crossplane.MatchLuaLatest, + ngx_crossplane.MatchHeadersMoreLatest, extramodules.BrotliMatchFn, + extramodules.OpentelemetryMatchFn, + ngx_crossplane.MatchGeoip2Latest, }, LexOptions: ngx_crossplane.LexOptions{ Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, }, - } - defaultCertificate := &ingress.SSLCert{ - PemFileName: "bla.crt", - PemCertKey: "bla.key", + IgnoreDirectives: []string{"set_escape_uri"}, } mimeFile, err := os.CreateTemp("", "") @@ -71,13 +101,11 @@ func TestCrossplaneTemplate(t *testing.T) { require.NoError(t, err) require.NoError(t, mimeFile.Close()) - tpl := crossplane.NewTemplate() + tpl, err := crossplane.NewTemplate() + require.NoError(t, err) t.Run("it should be able to marshall and unmarshall the default configuration", func(t *testing.T) { - tplConfig := &config.TemplateConfig{ - Cfg: config.NewDefault(), - } - tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + tplConfig := defaultConfig() tplConfig.Cfg.EnableBrotli = true tplConfig.Cfg.HideHeaders = []string{"x-fake-header", "x-another-fake-header"} tplConfig.Cfg.Resolver = resolvers @@ -101,11 +129,137 @@ func TestCrossplaneTemplate(t *testing.T) { require.NoError(t, err) }) - t.Run("it should set the right logging configs", func(t *testing.T) { - tplConfig := &config.TemplateConfig{ - Cfg: config.NewDefault(), + t.Run("it should be able to marshall and unmarshall with server config", func(t *testing.T) { + tplConfig := defaultConfig() + tplConfig.EnableMetrics = true + tplConfig.Cfg.EnableBrotli = true + tplConfig.Cfg.EnableOpentelemetry = true + tplConfig.Cfg.HideHeaders = []string{"x-fake-header", "x-another-fake-header"} + tplConfig.Cfg.Resolver = resolvers + tplConfig.Cfg.DisableIpv6DNS = true + tplConfig.IsIPV6Enabled = true + tplConfig.Cfg.BindAddressIpv6 = []string{"[::cabe:ca]"} + tplConfig.Cfg.BlockReferers = []string{"testlala.com"} + tplConfig.Cfg.ReusePort = true + tplConfig.BacklogSize = 5 + tplConfig.Cfg.BlockUserAgents = []string{"somebrowser"} + tplConfig.Cfg.UseForwardedHeaders = true + tplConfig.Cfg.LogFormatEscapeNone = true + tplConfig.Cfg.DisableAccessLog = true + tplConfig.Cfg.UpstreamKeepaliveConnections = 0 + tplConfig.Cfg.CustomHTTPErrors = []int{411, 412, 413} // Duplicated on purpose + tplConfig.RedirectServers = []*utilingress.Redirect{ + { + From: "www.xpto123.com", + To: "www.abcdefg.tld", + }, + } + tplConfig.Servers = []*ingress.Server{ + { + Hostname: "_", + }, + { + Hostname: "*.something.com", + Aliases: []string{"abc.com", "def.com"}, + Locations: []*ingress.Location{ + { + Mirror: mirror.Config{ + Source: "/mirror", + Host: "something.com", + Target: "http://www.mymirror.com", + RequestBody: "off", + }, + }, + { + DefaultBackendUpstreamName: "something", + CustomHTTPErrors: []int{403, 404, 403, 409}, // Duplicated on purpose! + }, + { + DefaultBackendUpstreamName: "otherthing", + CustomHTTPErrors: []int{403, 404, 403, 409}, // Duplicated on purpose! + }, + { + CorsConfig: cors.Config{ + CorsEnabled: true, + CorsAllowOrigin: []string{"xpto.com", "*.bla.com"}, + CorsAllowMethods: "GET,POST", + CorsAllowHeaders: "XPTO", + CorsMaxAge: 600, + CorsAllowCredentials: true, + CorsExposeHeaders: "XPTO", + }, + Backend: "somebackend", + ClientBodyBufferSize: "512k", + Proxy: proxy.Config{ + ProxyBuffering: "on", + RequestBuffering: "on", + BuffersNumber: 10, + BufferSize: "1024k", + ProxyHTTPVersion: "1.1", + NextUpstream: "10.10.10.10", + }, + ExternalAuth: authreq.Config{ + AuthCacheDuration: []string{"60s"}, + Host: "someauth.com", + URL: "http://someauth.com", + Method: "GET", + ProxySetHeaders: map[string]string{ + "someheader": "something", + }, + AuthCacheKey: "blabla", + SigninURL: "http://externallogin.tld", + }, + Path: "/xpto123", + }, + }, + }, + { + Hostname: "otherthing.com", + Aliases: []string{"abcde.com", "xpto.com"}, + CertificateAuth: authtls.Config{ + MatchCN: "CN=bla; listen xpto\"", + AuthSSLCert: resolver.AuthSSLCert{ + CAFileName: "/something/xpto.crt", + CRLFileName: "/something/xpto.crt", + }, + VerifyClient: "optional", + ValidationDepth: 2, + ErrorPage: "/xpto.html", + }, + ProxySSL: proxyssl.Config{ + AuthSSLCert: resolver.AuthSSLCert{ + CAFileName: "/something/xpto.crt", + PemFileName: "/something/mycert.crt", + }, + Ciphers: "HIGH:!aNULL:!MD5", + Protocols: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3", + Verify: "on", + VerifyDepth: 2, + ProxySSLName: "xpto.com", + ProxySSLServerName: "on", + }, + SSLCiphers: "HIGH:!aNULL:", + SSLPreferServerCiphers: "on", + }, } - tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + + tpl.SetMimeFile(mimeFile.Name()) + content, err := tpl.Write(tplConfig) + require.NoError(t, err) + + tmpFile, err := os.CreateTemp("", "") + require.NoError(t, err) + _, err = tmpFile.Write(content) + require.NoError(t, err) + require.NoError(t, tmpFile.Close()) + + _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) + require.NoError(t, err) + require.Equal(t, "bla", string(content)) + }) + + t.Run("it should set the right logging configs", func(t *testing.T) { + tplConfig := defaultConfig() tplConfig.Cfg.DisableAccessLog = false tplConfig.Cfg.HTTPAccessLogPath = "/lalala.log" @@ -124,10 +278,7 @@ func TestCrossplaneTemplate(t *testing.T) { }) t.Run("it should be able to marshall and unmarshall the specified configuration", func(t *testing.T) { - tplConfig := &config.TemplateConfig{ - Cfg: config.NewDefault(), - } - tplConfig.Cfg.DefaultSSLCertificate = defaultCertificate + tplConfig := defaultConfig() tplConfig.Cfg.WorkerCPUAffinity = "0001 0010 0100 1000" tplConfig.Cfg.LuaSharedDicts = map[string]int{ "configuration_data": 10240, @@ -186,7 +337,9 @@ func TestCrossplaneTemplate(t *testing.T) { tplConfig.Cfg.UpstreamKeepaliveTimeout = 200 tplConfig.Cfg.UpstreamKeepaliveRequests = 15 - tpl = crossplane.NewTemplate() + tpl, err = crossplane.NewTemplate() + require.NoError(t, err) + tpl.SetMimeFile(mimeFile.Name()) content, err := tpl.Write(tplConfig) require.NoError(t, err) diff --git a/internal/ingress/controller/template/crossplane/events.go b/internal/ingress/controller/template/crossplane/events.go index fa0c599e5e..ba0a76328a 100644 --- a/internal/ingress/controller/template/crossplane/events.go +++ b/internal/ingress/controller/template/crossplane/events.go @@ -25,7 +25,7 @@ func (c *Template) buildEvents() { Directive: "events", Block: ngx_crossplane.Directives{ buildDirective("worker_connections", c.tplConfig.Cfg.MaxWorkerConnections), - buildDirective("use", "epool"), + buildDirective("use", "epoll"), buildDirective("multi_accept", c.tplConfig.Cfg.EnableMultiAccept), }, } diff --git a/internal/ingress/controller/template/crossplane/extramodules/README.md b/internal/ingress/controller/template/crossplane/extramodules/README.md index 6bd8a4e6ba..b632776873 100644 --- a/internal/ingress/controller/template/crossplane/extramodules/README.md +++ b/internal/ingress/controller/template/crossplane/extramodules/README.md @@ -6,5 +6,5 @@ The generation of the files is done using go-crossplane generator ## Brotli ``` -go run ./cmd/generate/ -src-path=ngx_brotli/ -directive-map-name=brotliDirectives -match-func-name=BrotliMatchFn > ../ingress-crossplane/internal/ingress/controller/template/crossplane/extramodules/brotli.go +go run ./cmd/generate/ -src-path=ngx_brotli/ -directive-map-name=brotliDirectives -match-func-name=BrotliMatchFn > ../ingress-nginx/internal/ingress/controller/template/crossplane/extramodules/brotli.go ``` \ No newline at end of file diff --git a/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go b/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go new file mode 100644 index 0000000000..f3a9cde9a3 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go @@ -0,0 +1,71 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * Copyright (c) F5, Inc. + * + * This source code is licensed under the Apache License, Version 2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +// Code generated by generator; DO NOT EDIT. +// All the definitions are extracted from the source code +// Each bit mask describes these behaviors: +// - how many arguments the directive can take +// - whether or not it is a block directive +// - whether this is a flag (takes one argument that's either "on" or "off") +// - which contexts it's allowed to be in + +package extramodules + +var opentelemetryDirectives = map[string][]uint{ + "opentelemetry": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_attribute": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake2, + }, + "opentelemetry_capture_headers": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_config": { + ngxHTTPMainConf | ngxConfTake1, + }, + "opentelemetry_ignore_paths": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_operation_name": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_propagate": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfNoArgs | ngxConfTake1, + }, + "opentelemetry_sensitive_header_names": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_sensitive_header_values": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, + "opentelemetry_trust_incoming_spans": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxConfTake1, + }, +} + + +func OpentelemetryMatchFn(directive string) ([]uint, bool) { + m, ok := opentelemetryDirectives[directive] + return m, ok +} diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index dc3e43dcee..5da0b248a2 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -22,6 +22,8 @@ import ( "strings" ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + + utilingress "k8s.io/ingress-nginx/pkg/util/ingress" ) func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { @@ -124,7 +126,7 @@ func (c *Template) buildHTTP() { httpBlock = append(httpBlock, buildDirective("gzip_comp_level", cfg.GzipLevel)) httpBlock = append(httpBlock, buildDirective("gzip_http_version", "1.1")) httpBlock = append(httpBlock, buildDirective("gzip_min_length", cfg.GzipMinLength)) - httpBlock = append(httpBlock, buildDirective("gzip_types", cfg.GzipTypes)) + httpBlock = append(httpBlock, buildDirective("gzip_types", strings.Split(cfg.GzipTypes, " "))) httpBlock = append(httpBlock, buildDirective("gzip_proxied", "any")) httpBlock = append(httpBlock, buildDirective("gzip_vary", "on")) @@ -140,10 +142,23 @@ func (c *Template) buildHTTP() { httpBlock = append(httpBlock, buildDirective("brotli_types", cfg.BrotliTypes)) } + if (c.tplConfig.Cfg.EnableOpentelemetry || shouldLoadOpentelemetryModule(c.tplConfig.Servers)) && + cfg.OpentelemetryOperationName != "" { + httpBlock = append(httpBlock, buildDirective("opentelemetry_operation_name", cfg.OpentelemetryOperationName)) + } + if !cfg.ShowServerTokens { httpBlock = append(httpBlock, buildDirective("more_clear_headers", "Server")) } + if cfg.UseGeoIP2 && c.tplConfig.MaxmindEditionFiles != nil && len(*c.tplConfig.MaxmindEditionFiles) > 0 { + geoipDirectives := buildGeoIPDirectives(cfg.GeoIP2AutoReloadMinutes, *c.tplConfig.MaxmindEditionFiles) + // We do this to avoid adding empty blocks + if len(geoipDirectives) > 0 { + httpBlock = append(httpBlock, geoipDirectives...) + } + } + httpBlock = append(httpBlock, buildBlockDirective( "geo", []string{"$literal_dollar"}, @@ -153,11 +168,9 @@ func (c *Template) buildHTTP() { )) if len(c.tplConfig.AddHeaders) > 0 { - additionalHeaders := make([]string, 0) for headerName, headerValue := range c.tplConfig.AddHeaders { - additionalHeaders = append(additionalHeaders, fmt.Sprintf("%s: %s", headerName, headerValue)) + httpBlock = append(httpBlock, buildDirective("more_set_headers", fmt.Sprintf("%s: %s", headerName, headerValue))) } - httpBlock = append(httpBlock, buildDirective("more_set_headers", additionalHeaders)) } escape := "" @@ -257,15 +270,6 @@ func (c *Template) buildHTTP() { httpBlock = append(httpBlock, buildDirective("proxy_pass_header", "Server")) } - if cfg.EnableBrotli { - httpBlock = append(httpBlock, - buildDirective("brotli", "on"), - buildDirective("brotli_comp_level", cfg.BrotliLevel), - buildDirective("brotli_min_length", cfg.BrotliMinLength), - buildDirective("brotli_types", strings.Split(cfg.BrotliTypes, " ")), - ) - } - for k := range cfg.HideHeaders { httpBlock = append(httpBlock, buildDirective("proxy_hide_header", cfg.HideHeaders[k])) } @@ -284,6 +288,30 @@ func (c *Template) buildHTTP() { } httpBlock = append(httpBlock, buildBlockDirective("upstream", []string{"upstream_balancer"}, blockUpstreamDirectives)) + // Adding Rate limit + for _, rl := range filterRateLimits(c.tplConfig.Servers) { + id := fmt.Sprintf("$allowlist_%s", rl.ID) + httpBlock = append(httpBlock, buildDirective("#", "Ratelimit", rl.Name)) + rlDirectives := ngx_crossplane.Directives{ + buildDirective("default", 0), + } + for _, ip := range rl.Allowlist { + rlDirectives = append(rlDirectives, buildDirective(ip, "1")) + } + mapRateLimitDirective := buildMapDirective(id, fmt.Sprintf("$limit_%s", rl.ID), ngx_crossplane.Directives{ + buildDirective("0", cfg.LimitConnZoneVariable), + buildDirective("1", ""), + }) + httpBlock = append(httpBlock, buildBlockDirective("geo", []string{"$remote_addr", id}, rlDirectives), mapRateLimitDirective) + } + + zoneRL := buildRateLimitZones(c.tplConfig.Servers) + if len(zoneRL) > 0 { + httpBlock = append(httpBlock, zoneRL...) + } + + // End of Rate limit configs + for i := range cfg.BlockCIDRs { httpBlock = append(httpBlock, buildDirective("deny", strings.TrimSpace(cfg.BlockCIDRs[i]))) } @@ -309,6 +337,65 @@ func (c *Template) buildHTTP() { fmt.Sprintf("@custom_upstream-default-backend_%d", v))) } + if redirectServers, ok := c.tplConfig.RedirectServers.([]*utilingress.Redirect); ok { + for _, server := range redirectServers { + httpBlock = append(httpBlock, buildStartServer(server.From)) + serverBlock := c.buildRedirectServer(server) + httpBlock = append(httpBlock, serverBlock) + httpBlock = append(httpBlock, buildEndServer(server.From)) + } + } + + /* + {{ range $server := $servers }} + {{ range $location := $server.Locations }} + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} + upstream {{ buildAuthUpstreamName $location $server.Hostname }} { + {{- $externalAuth := $location.ExternalAuth }} + server {{ extractHostPort $externalAuth.URL }}; + + keepalive {{ $externalAuth.KeepaliveConnections }}; + keepalive_requests {{ $externalAuth.KeepaliveRequests }}; + keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; + } + ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} + {{ end }} + {{ end }} + {{ end }} + */ + for _, server := range c.tplConfig.Servers { + for _, location := range server.Locations { + if shouldApplyAuthUpstream(location, cfg) && !shouldApplyGlobalAuth(location, cfg.GlobalExternalAuth.URL) { + authUpstreamBlock := buildBlockDirective("upstream", + []string{buildAuthUpstreamName(location, server.Hostname)}, ngx_crossplane.Directives{ + buildDirective("server", extractHostPort(location.ExternalAuth.URL)), + buildDirective("keepalive", location.ExternalAuth.KeepaliveConnections), + buildDirective("keepalive_requests", location.ExternalAuth.KeepaliveRequests), + buildDirective("keepalive_timeout", seconds(location.ExternalAuth.KeepaliveTimeout)), + }, + ) + httpBlock = append(httpBlock, + buildStartAuthUpstream(server.Hostname, location.Path), + authUpstreamBlock, + buildEndAuthUpstream(server.Hostname, location.Path), + ) + } + } + } + + for _, server := range c.tplConfig.Servers { + httpBlock = append(httpBlock, buildStartServer(server.Hostname)) + serverBlock := c.buildServerDirective(server) + httpBlock = append(httpBlock, serverBlock) + httpBlock = append(httpBlock, buildEndServer(server.Hostname)) + } + + httpBlock = append(httpBlock, c.buildDefaultBackend()) + httpBlock = append(httpBlock, c.buildHealthAndStatsServer()) + c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ Directive: "http", Block: httpBlock, diff --git a/internal/ingress/controller/template/crossplane/location.go b/internal/ingress/controller/template/crossplane/location.go new file mode 100644 index 0000000000..af2ee433ba --- /dev/null +++ b/internal/ingress/controller/template/crossplane/location.go @@ -0,0 +1,756 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + "sort" + "strconv" + "strings" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + "k8s.io/apimachinery/pkg/util/sets" + + "k8s.io/ingress-nginx/internal/ingress/controller/config" + "k8s.io/ingress-nginx/pkg/apis/ingress" +) + +func buildMirrorLocationDirective(locs []*ingress.Location) ngx_crossplane.Directives { + mirrorDirectives := make(ngx_crossplane.Directives, 0) + + mapped := sets.Set[string]{} + + for _, loc := range locs { + if loc.Mirror.Source == "" || loc.Mirror.Target == "" || loc.Mirror.Host == "" { + continue + } + + if mapped.Has(loc.Mirror.Source) { + continue + } + + mapped.Insert(loc.Mirror.Source) + mirrorDirectives = append(mirrorDirectives, buildBlockDirective("location", + []string{"=", loc.Mirror.Source}, + ngx_crossplane.Directives{ + buildDirective("internal"), + buildDirective("proxy_set_header", "Host", loc.Mirror.Host), + buildDirective("proxy_pass", loc.Mirror.Target), + })) + } + return mirrorDirectives +} + +// buildCustomErrorLocationsPerServer is a utility function which will collect all +// custom error codes for all locations of a server block, deduplicates them, +// and returns a set which is unique by default-upstream and error code. It returns an array +// of errorLocations, each of which contain the upstream name and a list of +// error codes for that given upstream, so that sufficiently unique +// @custom error location blocks can be created in the template +func buildCustomErrorLocationsPerServer(server *ingress.Server, enableMetrics bool) ngx_crossplane.Directives { + type errorLocation struct { + UpstreamName string + Codes []int + } + + codesMap := make(map[string]map[int]bool) + for _, loc := range server.Locations { + backendUpstream := loc.DefaultBackendUpstreamName + + var dedupedCodes map[int]bool + if existingMap, ok := codesMap[backendUpstream]; ok { + dedupedCodes = existingMap + } else { + dedupedCodes = make(map[int]bool) + } + + for _, code := range loc.CustomHTTPErrors { + dedupedCodes[code] = true + } + codesMap[backendUpstream] = dedupedCodes + } + + errorLocations := []errorLocation{} + + for upstream, dedupedCodes := range codesMap { + codesForUpstream := []int{} + for code := range dedupedCodes { + codesForUpstream = append(codesForUpstream, code) + } + sort.Ints(codesForUpstream) + errorLocations = append(errorLocations, errorLocation{ + UpstreamName: upstream, + Codes: codesForUpstream, + }) + } + + sort.Slice(errorLocations, func(i, j int) bool { + return errorLocations[i].UpstreamName < errorLocations[j].UpstreamName + }) + + errorLocationsDirectives := make(ngx_crossplane.Directives, 0) + for i := range errorLocations { + errorLocationsDirectives = append(errorLocationsDirectives, buildCustomErrorLocation(errorLocations[i].UpstreamName, errorLocations[i].Codes, enableMetrics)...) + } + return errorLocationsDirectives + +} + +func buildCustomErrorLocation(upstreamName string, errorCodes []int, enableMetrics bool) ngx_crossplane.Directives { + directives := make(ngx_crossplane.Directives, len(errorCodes)) + for i := range errorCodes { + locationDirectives := ngx_crossplane.Directives{ + buildDirective("internal"), + buildDirective("proxy_intercept_errors", "off"), + buildDirective("proxy_set_header", "X-Code", errorCodes[i]), + buildDirective("proxy_set_header", "X-Format", "$http_accept"), + buildDirective("proxy_set_header", "X-Original-URI", "$request_uri"), + buildDirective("proxy_set_header", "X-Namespace", "$namespace"), + buildDirective("proxy_set_header", "X-Ingress-Name", "$ingress_name"), + buildDirective("proxy_set_header", "X-Service-Name", "$service_name"), + buildDirective("proxy_set_header", "X-Service-Port", "$service_port"), + buildDirective("proxy_set_header", "X-Request-ID", "$req_id"), + buildDirective("proxy_set_header", "X-Forwarded-For", "$remote_addr"), + buildDirective("proxy_set_header", "Host", "$best_http_host"), + buildDirective("set", "$proxy_upstream_name", upstreamName), + buildDirective("rewrite", "(.*)", "/", "break"), + buildDirective("proxy_pass", "http://upstream_balancer"), + } + + if enableMetrics { + locationDirectives = append(locationDirectives, buildDirective("log_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_log.lua")) + } + locationName := fmt.Sprintf("@custom_%s_%d", upstreamName, errorCodes[i]) + directives[i] = buildBlockDirective("location", []string{locationName}, locationDirectives) + } + + return directives +} + +type locationCfg struct { + pathLocation []string + authPath string + externalAuth *externalAuth + proxySetHeader string + applyGlobalAuth bool + applyAuthUpstream bool +} + +func (c *Template) buildServerLocations(server *ingress.Server, locations []*ingress.Location) ngx_crossplane.Directives { + serverLocations := make(ngx_crossplane.Directives, 0) + + cfg := c.tplConfig.Cfg + enforceRegexModifier := false + needsRewrite := func(loc *ingress.Location) bool { + return loc.Rewrite.Target != "" && + loc.Rewrite.Target != loc.Path + } + + for _, location := range locations { + if needsRewrite(location) || location.Rewrite.UseRegex { + enforceRegexModifier = true + break + } + } + + for _, location := range locations { + locationConfig := locationCfg{ + pathLocation: buildLocation(location, enforceRegexModifier), + proxySetHeader: getProxySetHeader(location), + authPath: buildAuthLocation(location, cfg.GlobalExternalAuth.URL), + applyGlobalAuth: shouldApplyGlobalAuth(location, cfg.GlobalExternalAuth.URL), + applyAuthUpstream: shouldApplyAuthUpstream(location, cfg), + externalAuth: &externalAuth{}, + } + + if location.Rewrite.AppRoot != "" { + serverLocations = append(serverLocations, + buildBlockDirective("if", []string{"$uri", "=", "/"}, + ngx_crossplane.Directives{ + buildDirective("return", "302", fmt.Sprintf("$scheme://$http_host%s", location.Rewrite.AppRoot)), + })) + } + + if locationConfig.applyGlobalAuth { + locationConfig.externalAuth = buildExternalAuth(cfg.GlobalExternalAuth) + } else { + locationConfig.externalAuth = buildExternalAuth(location.ExternalAuth) + } + if locationConfig.authPath != "" { + serverLocations = append(serverLocations, c.buildAuthLocation(server, location, locationConfig)) + } + if location.Denied == nil && locationConfig.externalAuth != nil && locationConfig.externalAuth.SigninURL != "" { + directives := ngx_crossplane.Directives{ + buildDirective("internal"), + buildDirective("add_header", "Set-Cookie", "$auth_cookie"), + } + if location.CorsConfig.CorsEnabled { + directives = append(directives, buildCorsDirectives(location.CorsConfig)...) + } + directives = append(directives, + buildDirective("return", + "302", + buildAuthSignURL(locationConfig.externalAuth.SigninURL, locationConfig.externalAuth.SigninURLRedirectParam))) + + serverLocations = append(serverLocations, buildBlockDirective("location", + []string{buildAuthSignURLLocation(location.Path, locationConfig.externalAuth.SigninURL)}, directives)) + + } + serverLocations = append(serverLocations, c.buildLocation(server, location, locationConfig)) + + } + + return serverLocations +} + +func (c *Template) buildLocation(server *ingress.Server, + location *ingress.Location, locationConfig locationCfg) *ngx_crossplane.Directive { + ing := getIngressInformation(location.Ingress, server.Hostname, location.IngressPath) + cfg := c.tplConfig + locationDirectives := ngx_crossplane.Directives{ + buildDirective("set", "$namespace", ing.Namespace), + buildDirective("set", "$ingress_name", ing.Rule), + buildDirective("set", "$service_name", ing.Service), + buildDirective("set", "$service_port", ing.ServicePort), + buildDirective("set", "$balancer_ewma_score", "-1"), + buildDirective("set", "$proxy_upstream_name", location.Backend), + buildDirective("set", "$proxy_host", "$proxy_upstream_name"), + buildDirective("set", "$pass_access_scheme", "$scheme"), + buildDirective("set", "$best_http_host", "$http_host"), + buildDirective("set", "$pass_port", "$pass_server_port"), + buildDirective("set", "$proxy_alternative_upstream_name", ""), + buildDirective("set", "$location_path", strings.ReplaceAll(ing.Path, `$`, `${literal_dollar}`)), + } + + locationDirectives = append(locationDirectives, locationConfigForLua(location, *c.tplConfig)...) + locationDirectives = append(locationDirectives, buildCertificateDirectives(location)...) + + if cfg.Cfg.UseProxyProtocol { + locationDirectives = append(locationDirectives, + buildDirective("set", "$pass_server_port", "$proxy_protocol_server_port")) + } else { + locationDirectives = append(locationDirectives, + buildDirective("set", "$pass_server_port", "$server_port")) + } + + locationDirectives = append(locationDirectives, + buildOpentelemetryForLocationDirectives(cfg.Cfg.EnableOpentelemetry, cfg.Cfg.OpentelemetryTrustIncomingSpan, location)...) + + locationDirectives = append(locationDirectives, + buildDirective("rewrite_by_lua_file", "/etc/nginx/lua/nginx/ngx_rewrite.lua"), + buildDirective("header_filter_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua"), + buildDirective("log_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_log_block.lua"), + buildDirective("rewrite_log", location.Logs.Rewrite), + // buildDirective("http2_push_preload", location.HTTP2PushPreload), // This directive is deprecated, keeping out of new crossplane + buildDirective("port_in_redirect", location.UsePortInRedirects)) + + if location.Mirror.Source != "" { + locationDirectives = append(locationDirectives, + buildDirective("mirror", location.Mirror.Source), + buildDirective("mirror_request_body", location.Mirror.RequestBody), + ) + } + + if !location.Logs.Access { + locationDirectives = append(locationDirectives, + buildDirective("access_log", "off"), + ) + } + if location.Denied != nil { + locationDirectives = append(locationDirectives, + buildDirectiveWithComment("return", fmt.Sprintf("Location denied. Reason: %s", *location.Denied), "503")) + } else { + locationDirectives = append(locationDirectives, c.buildAllowedLocation(server, location, locationConfig)...) + } + + return buildBlockDirective("location", locationConfig.pathLocation, locationDirectives) +} + +func (c *Template) buildAllowedLocation(server *ingress.Server, location *ingress.Location, locationConfig locationCfg) ngx_crossplane.Directives { + dir := make(ngx_crossplane.Directives, 0) + proxySetHeader := locationConfig.proxySetHeader + for _, ip := range location.Denylist.CIDR { + dir = append(dir, buildDirective("deny", ip)) + } + if len(location.Allowlist.CIDR) > 0 { + for _, ip := range location.Allowlist.CIDR { + dir = append(dir, buildDirective("allow", ip)) + } + dir = append(dir, buildDirective("deny", "all")) + } + + if location.CorsConfig.CorsEnabled { + dir = append(dir, buildCorsDirectives(location.CorsConfig)...) + } + // TODO: Implement the build Auth Location + if !isLocationInLocationList(location, c.tplConfig.Cfg.NoAuthLocations) { + dir = append(dir, buildAuthLocationConfig(location, locationConfig)...) + } + + dir = append(dir, buildRateLimit(location)...) + + if isValidByteSize(location.Proxy.BodySize, true) { + dir = append(dir, buildDirective("client_max_body_size", location.Proxy.BodySize)) + } + if isValidByteSize(location.ClientBodyBufferSize, false) { + dir = append(dir, buildDirective("client_body_buffer_size", location.ClientBodyBufferSize)) + } + + if location.UpstreamVhost != "" { + dir = append(dir, buildDirective(proxySetHeader, "Host", location.UpstreamVhost)) + } else { + dir = append(dir, buildDirective(proxySetHeader, "Host", "$best_http_host")) + } + + if server.CertificateAuth.CAFileName != "" { + dir = append(dir, + buildDirective(proxySetHeader, "ssl-client-verify", "$ssl_client_verify"), + buildDirective(proxySetHeader, "ssl-client-subject-dn", "$ssl_client_s_dn"), + buildDirective(proxySetHeader, "ssl-client-issuer-dn", "$ssl_client_i_dn"), + ) + + if server.CertificateAuth.PassCertToUpstream { + dir = append(dir, buildDirective(proxySetHeader, "ssl-client-cert", "$ssl_client_escaped_cert")) + } + } + + dir = append(dir, + buildDirective(proxySetHeader, "Upgrade", "$http_upgrade"), + buildDirective(proxySetHeader, "X-Request-ID", "$req_id"), + buildDirective(proxySetHeader, "X-Real-IP", "$remote_addr"), + buildDirective(proxySetHeader, "X-Forwarded-Host", "$best_http_host"), + buildDirective(proxySetHeader, "X-Forwarded-Port", "$pass_port"), + buildDirective(proxySetHeader, "X-Forwarded-Proto", "$pass_access_scheme"), + buildDirective(proxySetHeader, "X-Forwarded-Scheme", "$pass_access_scheme"), + buildDirective(proxySetHeader, "X-Real-IP", "$remote_addr"), + buildDirective(proxySetHeader, "X-Scheme", "$pass_access_scheme"), + buildDirective(proxySetHeader, "X-Original-Forwarded-For", + fmt.Sprintf("$http_%s", strings.ToLower(strings.ReplaceAll(c.tplConfig.Cfg.ForwardedForHeader, "-", "_")))), + buildDirectiveWithComment(proxySetHeader, + "mitigate HTTProxy Vulnerability - https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/", "Proxy", ""), + buildDirective("proxy_connect_timeout", seconds(location.Proxy.ConnectTimeout)), + buildDirective("proxy_read_timeout", seconds(location.Proxy.ReadTimeout)), + buildDirective("proxy_send_timeout", seconds(location.Proxy.SendTimeout)), + buildDirective("proxy_buffering", location.Proxy.ProxyBuffering), + buildDirective("proxy_buffer_size", location.Proxy.BufferSize), + buildDirective("proxy_buffers", location.Proxy.BuffersNumber, location.Proxy.BufferSize), + buildDirective("proxy_request_buffering", location.Proxy.RequestBuffering), + buildDirective("proxy_http_version", location.Proxy.ProxyHTTPVersion), + buildDirective("proxy_cookie_domain", strings.Split(location.Proxy.CookieDomain, " ")), + buildDirective("proxy_cookie_path", strings.Split(location.Proxy.CookiePath, " ")), + buildDirective("proxy_next_upstream_timeout", location.Proxy.NextUpstreamTimeout), + buildDirective("proxy_next_upstream_tries", location.Proxy.NextUpstreamTries), + buildDirective("proxy_next_upstream", buildNextUpstream(location.Proxy.NextUpstream, c.tplConfig.Cfg.RetryNonIdempotent)), + ) + + if isValidByteSize(location.Proxy.ProxyMaxTempFileSize, true) { + dir = append(dir, buildDirective("proxy_max_temp_file_size", location.Proxy.ProxyMaxTempFileSize)) + } + + if c.tplConfig.Cfg.UseForwardedHeaders && c.tplConfig.Cfg.ComputeFullForwardedFor { + dir = append(dir, buildDirective(proxySetHeader, "X-Forwarded-For", "$full_x_forwarded_for")) + } else { + dir = append(dir, buildDirective(proxySetHeader, "X-Forwarded-For", "$remote_addr")) + } + + if c.tplConfig.Cfg.ProxyAddOriginalURIHeader { + dir = append(dir, buildDirective(proxySetHeader, "X-Original-URI", "$request_uri")) + } + + if location.Connection.Enabled { + dir = append(dir, buildDirective(proxySetHeader, "Connection", location.Connection.Header)) + } else { + dir = append(dir, buildDirective(proxySetHeader, "Connection", "$connection_upgrade")) + } + + for k, v := range c.tplConfig.ProxySetHeaders { + dir = append(dir, buildDirective(proxySetHeader, k, v)) + } + + for k, v := range location.CustomHeaders.Headers { + dir = append(dir, buildDirective("more_set_headers", fmt.Sprintf("%s: %s", k, strings.ReplaceAll(v, `$`, `${literal_dollar}`)))) + } + + if strings.HasPrefix(location.Backend, "custom-default-backend-") { + dir = append(dir, + buildDirective("proxy_set_header", "X-Code", "503"), + buildDirective("proxy_set_header", "X-Format", "$http_accept"), + buildDirective("proxy_set_header", "X-Namespace", "$namespace"), + buildDirective("proxy_set_header", "X-Ingress-Name", "$ingress_name"), + buildDirective("proxy_set_header", "X-Service-Name", "$service_name"), + buildDirective("proxy_set_header", "X-Service-Port", "$service_port"), + buildDirective("proxy_set_header", "X-Request-ID", "$req_id"), + ) + } + + if location.Satisfy != "" { + dir = append(dir, buildDirective("satisfy", location.Satisfy)) + } + + if len(location.CustomHTTPErrors) > 0 && !location.DisableProxyInterceptErrors { + dir = append(dir, buildDirective("proxy_intercept_errors", "on")) + } + + for _, errorcode := range location.CustomHTTPErrors { + dir = append(dir, buildDirective( + "error_page", + errorcode, "=", + fmt.Sprintf("@custom_%s_%d", location.DefaultBackendUpstreamName, errorcode)), + ) + } + + switch location.BackendProtocol { + case "GRPC", "GRPCS": + dir = append(dir, + buildDirective("grpc_connect_timeout", seconds(location.Proxy.ConnectTimeout)), + buildDirective("grpc_send_timeout", seconds(location.Proxy.SendTimeout)), + buildDirective("grpc_read_timeout", seconds(location.Proxy.ReadTimeout)), + ) + case "FCGI": + dir = append(dir, buildDirective("include", "/etc/nginx/fastcgi_params")) + if location.FastCGI.Index != "" { + dir = append(dir, buildDirective("fastcgi_index", location.FastCGI.Index)) + } + for k, v := range location.FastCGI.Params { + dir = append(dir, buildDirective("fastcgi_param", k, v)) + } + } + + if location.Redirect.URL != "" { + dir = append(dir, buildDirective("return", location.Redirect.Code, location.Redirect.URL)) + } + + dir = append(dir, buildProxyPass(c.tplConfig.Backends, location)...) + + if location.Proxy.ProxyRedirectFrom == "default" || location.Proxy.ProxyRedirectFrom == "off" { + dir = append(dir, buildDirective("proxy_redirect", location.Proxy.ProxyRedirectFrom)) + } else if location.Proxy.ProxyRedirectTo != "off" { + dir = append(dir, buildDirective("proxy_redirect", location.Proxy.ProxyRedirectFrom, location.Proxy.ProxyRedirectTo)) + } + + return dir +} + +func buildCertificateDirectives(location *ingress.Location) ngx_crossplane.Directives { + cert := make(ngx_crossplane.Directives, 0) + if location.ProxySSL.CAFileName != "" { + cert = append(cert, + buildDirectiveWithComment( + "proxy_ssl_trusted_certificate", + fmt.Sprintf("#PEM sha: %s", location.ProxySSL.CASHA), + location.ProxySSL.CAFileName, + ), + buildDirective("proxy_ssl_ciphers", location.ProxySSL.Ciphers), + buildDirective("proxy_ssl_protocols", strings.Split(location.ProxySSL.Protocols, " ")), + buildDirective("proxy_ssl_verify", location.ProxySSL.Verify), + buildDirective("proxy_ssl_verify_depth", location.ProxySSL.VerifyDepth), + ) + } + if location.ProxySSL.ProxySSLName != "" { + cert = append(cert, buildDirective("proxy_ssl_name", location.ProxySSL.ProxySSLName)) + } + if location.ProxySSL.ProxySSLServerName != "" { + cert = append(cert, buildDirective("proxy_ssl_server_name", location.ProxySSL.ProxySSLServerName)) + } + if location.ProxySSL.PemFileName != "" { + cert = append(cert, + buildDirective("proxy_ssl_certificate", location.ProxySSL.PemFileName), + buildDirective("proxy_ssl_certificate_key", location.ProxySSL.PemFileName), + ) + } + return cert +} + +type ingressInformation struct { + Namespace string + Path string + Rule string + Service string + ServicePort string + Annotations map[string]string +} + +func getIngressInformation(ing *ingress.Ingress, hostname, ingressPath string) *ingressInformation { + if ing == nil { + return &ingressInformation{} + } + + info := &ingressInformation{ + Namespace: ing.GetNamespace(), + Rule: ing.GetName(), + Annotations: ing.Annotations, + Path: ingressPath, + } + + if ingressPath == "" { + ingressPath = "/" + info.Path = "/" + } + + if ing.Spec.DefaultBackend != nil && ing.Spec.DefaultBackend.Service != nil { + info.Service = ing.Spec.DefaultBackend.Service.Name + if ing.Spec.DefaultBackend.Service.Port.Number > 0 { + info.ServicePort = strconv.Itoa(int(ing.Spec.DefaultBackend.Service.Port.Number)) + } else { + info.ServicePort = ing.Spec.DefaultBackend.Service.Port.Name + } + } + + for _, rule := range ing.Spec.Rules { + if rule.HTTP == nil { + continue + } + + if hostname != "_" && rule.Host == "" { + continue + } + + host := "_" + if rule.Host != "" { + host = rule.Host + } + + if hostname != host { + continue + } + + for _, rPath := range rule.HTTP.Paths { + if ingressPath != rPath.Path { + continue + } + + if rPath.Backend.Service == nil { + continue + } + + if info.Service != "" && rPath.Backend.Service.Name == "" { + // empty rule. Only contains a Path and PathType + return info + } + + info.Service = rPath.Backend.Service.Name + if rPath.Backend.Service.Port.Number > 0 { + info.ServicePort = strconv.Itoa(int(rPath.Backend.Service.Port.Number)) + } else { + info.ServicePort = rPath.Backend.Service.Port.Name + } + + return info + } + } + + return info +} + +func buildOpentelemetryForLocationDirectives(isOTEnabled, isOTTrustSet bool, location *ingress.Location) ngx_crossplane.Directives { + isOTEnabledInLoc := location.Opentelemetry.Enabled + isOTSetInLoc := location.Opentelemetry.Set + directives := make(ngx_crossplane.Directives, 0) + if isOTEnabled { + if isOTSetInLoc && !isOTEnabledInLoc { + return ngx_crossplane.Directives{ + buildDirective("opentelemetry", "off"), + } + } + } else if !isOTSetInLoc || !isOTEnabledInLoc { + return directives + } + + if location != nil { + directives = append(directives, + buildDirective("opentelemetry", "on"), + buildDirective("opentelemetry_propagate"), + ) + if location.Opentelemetry.OperationName != "" { + directives = append(directives, + buildDirective("opentelemetry_operation_name", location.Opentelemetry.OperationName)) + } + + if (!isOTTrustSet && !location.Opentelemetry.TrustSet) || + (location.Opentelemetry.TrustSet && !location.Opentelemetry.TrustEnabled) { + directives = append(directives, + buildDirective("opentelemetry_trust_incoming_spans", "off"), + ) + } else { + directives = append(directives, + buildDirective("opentelemetry_trust_incoming_spans", "on"), + ) + } + } + + return directives +} + +// buildRateLimit produces an array of limit_req to be used inside the Path of +// Ingress rules. The order: connections by IP first, then RPS, and RPM last. +func buildRateLimit(loc *ingress.Location) ngx_crossplane.Directives { + limits := make(ngx_crossplane.Directives, 0) + + if loc.RateLimit.Connections.Limit > 0 { + limits = append(limits, buildDirective("limit_conn", loc.RateLimit.Connections.Name, loc.RateLimit.Connections.Limit)) + } + + if loc.RateLimit.RPS.Limit > 0 { + limits = append(limits, + buildDirective( + "limit_req", + fmt.Sprintf("zone=%s", loc.RateLimit.RPS.Name), + fmt.Sprintf("burst=%d", loc.RateLimit.RPS.Burst), + "nodelay", + ), + ) + } + + if loc.RateLimit.RPM.Limit > 0 { + limits = append(limits, + buildDirective( + "limit_req", + fmt.Sprintf("zone=%s", loc.RateLimit.RPM.Name), + fmt.Sprintf("burst=%d", loc.RateLimit.RPM.Burst), + "nodelay", + ), + ) + } + + if loc.RateLimit.LimitRateAfter > 0 { + limits = append(limits, + buildDirective( + "limit_rate_after", + fmt.Sprintf("%dk", loc.RateLimit.LimitRateAfter), + ), + ) + } + + if loc.RateLimit.LimitRate > 0 { + limits = append(limits, + buildDirective( + "limit_rate", + fmt.Sprintf("%dk", loc.RateLimit.LimitRate), + ), + ) + } + + return limits +} + +// locationConfigForLua formats some location specific configuration into Lua table represented as string +func locationConfigForLua(location *ingress.Location, all config.TemplateConfig) ngx_crossplane.Directives { + /* Lua expects the following vars + force_ssl_redirect = string_to_bool(ngx.var.force_ssl_redirect), + ssl_redirect = string_to_bool(ngx.var.ssl_redirect), + force_no_ssl_redirect = string_to_bool(ngx.var.force_no_ssl_redirect), + preserve_trailing_slash = string_to_bool(ngx.var.preserve_trailing_slash), + use_port_in_redirects = string_to_bool(ngx.var.use_port_in_redirects), + */ + + return ngx_crossplane.Directives{ + buildDirective("set", "$force_ssl_redirect", strconv.FormatBool(location.Rewrite.ForceSSLRedirect)), + buildDirective("set", "$ssl_redirect", strconv.FormatBool(location.Rewrite.SSLRedirect)), + buildDirective("set", "$force_no_ssl_redirect", strconv.FormatBool(isLocationInLocationList(location, all.Cfg.NoTLSRedirectLocations))), + buildDirective("set", "$preserve_trailing_slash", strconv.FormatBool(location.Rewrite.PreserveTrailingSlash)), + buildDirective("set", "$use_port_in_redirects", strconv.FormatBool(location.UsePortInRedirects)), + } +} + +func isLocationInLocationList(loc *ingress.Location, rawLocationList string) bool { + locationList := strings.Split(rawLocationList, ",") + + for _, locationListItem := range locationList { + locationListItem = strings.Trim(locationListItem, " ") + if locationListItem == "" { + continue + } + if strings.HasPrefix(loc.Path, locationListItem) { + return true + } + } + + return false +} + +func buildAuthLocationConfig(location *ingress.Location, locationConfig locationCfg) ngx_crossplane.Directives { + directives := make(ngx_crossplane.Directives, 0) + if locationConfig.authPath != "" { + if locationConfig.applyAuthUpstream && !locationConfig.applyGlobalAuth { + directives = append(directives, buildDirective("set", "$auth_cookie", "")) + directives = append(directives, buildDirective("add_header", "Set-Cookie", "$auth_cookie")) + directives = append(directives, buildAuthResponseHeaders(locationConfig.proxySetHeader, locationConfig.externalAuth.ResponseHeaders, true)...) + if len(locationConfig.externalAuth.ResponseHeaders) > 0 { + directives = append(directives, buildDirective("set", "$auth_response_headers", strings.Join(locationConfig.externalAuth.ResponseHeaders, ","))) + } + directives = append(directives, + buildDirective("set", "$auth_path", locationConfig.authPath), + buildDirective("set", "$auth_keepalive_share_vars", strconv.FormatBool(locationConfig.externalAuth.KeepaliveShareVars)), + buildDirective("access_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_external_auth.lua"), + ) + } else { + directives = append(directives, + buildDirective("auth_request", locationConfig.authPath), + buildDirective("auth_request_set", "$auth_cookie", "$upstream_http_set_cookie"), + ) + cookieDirective := buildDirective("add_header", "Set-Cookie", "$auth_cookie") + if locationConfig.externalAuth.AlwaysSetCookie { + cookieDirective.Args = append(cookieDirective.Args, "always") + } + directives = append(directives, cookieDirective) + directives = append(directives, buildAuthResponseHeaders(locationConfig.proxySetHeader, locationConfig.externalAuth.ResponseHeaders, false)...) + } + } + + if locationConfig.externalAuth.SigninURL != "" { + directives = append(directives, + buildDirective("set_escape_uri", "$escaped_request_uri", "$request_uri"), + buildDirective("error_page", "401", "=", buildAuthSignURLLocation(location.Path, locationConfig.externalAuth.SigninURL)), + ) + } + if location.BasicDigestAuth.Secured { + var authDirective, authFileDirective string + if location.BasicDigestAuth.Type == "basic" { + authDirective, authFileDirective = "auth_basic", "auth_basic_user_file" + } else { + authDirective, authFileDirective = "auth_digest", "auth_digest_user_file" + } + + directives = append(directives, + buildDirective(authDirective, location.BasicDigestAuth.Realm), + buildDirective(authFileDirective, location.BasicDigestAuth.File), + buildDirective(locationConfig.proxySetHeader, "Authorization", ""), + ) + } + + return directives + /* + Missing this Lua script + # `auth_request` module does not support HTTP keepalives in upstream block: + # https://trac.nginx.org/nginx/ticket/1579 + access_by_lua_block { + local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) + if res.status == ngx.HTTP_OK then + ngx.var.auth_cookie = res.header['Set-Cookie'] + {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} # IF 4 + {{ $line }} + {{- end }} # END IF 4 + return + end + if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then + ngx.exit(res.status) + end + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) + } + + */ +} diff --git a/internal/ingress/controller/template/crossplane/server.go b/internal/ingress/controller/template/crossplane/server.go new file mode 100644 index 0000000000..541e156f0f --- /dev/null +++ b/internal/ingress/controller/template/crossplane/server.go @@ -0,0 +1,268 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crossplane + +import ( + "fmt" + "strings" + + ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + + "k8s.io/ingress-nginx/pkg/apis/ingress" + utilingress "k8s.io/ingress-nginx/pkg/util/ingress" + "k8s.io/utils/ptr" +) + +func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane.Directive { + cfg := c.tplConfig.Cfg + serverName := buildServerName(server.Hostname) + serverBlock := ngx_crossplane.Directives{ + buildDirective("server_name", serverName, server.Aliases), + buildDirective("http2", cfg.UseHTTP2), + buildDirective("set", "$proxy_upstream_name", "-"), + buildDirective("ssl_certificate_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_certificate.lua"), + } + + serverBlock = append(serverBlock, buildListener(*c.tplConfig, server.Hostname)...) + serverBlock = append(serverBlock, c.buildBlockers()...) + + if server.Hostname == "_" { + serverBlock = append(serverBlock, buildDirective("ssl_reject_handshake", cfg.SSLRejectHandshake)) + } + + if server.CertificateAuth.MatchCN != "" { + matchCNBlock := buildBlockDirective("if", + []string{"$ssl_client_s_dn", "!~", server.CertificateAuth.MatchCN}, + ngx_crossplane.Directives{ + buildDirective("return", "403", "client certificate unauthorized"), + }) + serverBlock = append(serverBlock, matchCNBlock) + } + + if server.AuthTLSError != "" { + serverBlock = append(serverBlock, buildDirective("return", 403)) + } else { + + serverBlock = append(serverBlock, c.buildCertificateDirectives(server)...) + serverBlock = append(serverBlock, buildCustomErrorLocationsPerServer(server, c.tplConfig.EnableMetrics)...) + serverBlock = append(serverBlock, buildMirrorLocationDirective(server.Locations)...) + + // The other locations should come here! + serverBlock = append(serverBlock, c.buildServerLocations(server, server.Locations)...) + + } + + // "/healthz" location + if server.Hostname == "_" { + dirs := ngx_crossplane.Directives{ + buildDirective("access_log", "off"), + buildDirective("return", "200"), + } + if cfg.EnableOpentelemetry { + dirs = append(dirs, buildDirective("opentelemetry", "off")) + } + healthLocation := buildBlockDirective("location", + []string{c.tplConfig.HealthzURI}, dirs) + serverBlock = append(serverBlock, healthLocation) + + // "/nginx_status" location + statusLocationDirs := ngx_crossplane.Directives{} + if cfg.EnableOpentelemetry { + statusLocationDirs = append(statusLocationDirs, buildDirective("opentelemetry", "off")) + } + + for _, v := range c.tplConfig.NginxStatusIpv4Whitelist { + statusLocationDirs = append(statusLocationDirs, buildDirective("allow", v)) + } + + if c.tplConfig.IsIPV6Enabled { + for _, v := range c.tplConfig.NginxStatusIpv6Whitelist { + statusLocationDirs = append(statusLocationDirs, buildDirective("allow", v)) + } + } + statusLocationDirs = append(statusLocationDirs, + buildDirective("deny", "all"), + buildDirective("access_log", "off"), + buildDirective("stub_status", "on")) + + // End of "nginx_status" location + + serverBlock = append(serverBlock, buildBlockDirective("location", []string{"/nginx_status"}, statusLocationDirs)) + + } + + // DO NOT MOVE! THIS IS THE END DIRECTIVE OF SERVERS + serverBlock = append(serverBlock, buildCustomErrorLocation("upstream-default-backend", cfg.CustomHTTPErrors, c.tplConfig.EnableMetrics)...) + + return &ngx_crossplane.Directive{ + Directive: "server", + Block: serverBlock, + } +} + +func (c *Template) buildCertificateDirectives(server *ingress.Server) ngx_crossplane.Directives { + certDirectives := make(ngx_crossplane.Directives, 0) + + if server.CertificateAuth.CAFileName != "" { + certAuth := server.CertificateAuth + certDirectives = append(certDirectives, buildDirective("ssl_client_certificate", certAuth.CAFileName)) + certDirectives = append(certDirectives, buildDirective("ssl_verify_client", certAuth.VerifyClient)) + certDirectives = append(certDirectives, buildDirective("ssl_verify_depth", certAuth.ValidationDepth)) + if certAuth.CRLFileName != "" { + certDirectives = append(certDirectives, buildDirective("ssl_crl", certAuth.CRLFileName)) + } + if certAuth.ErrorPage != "" { + certDirectives = append(certDirectives, buildDirective("error_page", "495", "496", "=", certAuth.ErrorPage)) + } + } + + prxSSL := server.ProxySSL + if prxSSL.CAFileName != "" { + certDirectives = append(certDirectives, buildDirective("proxy_ssl_trusted_certificate", prxSSL.CAFileName)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_ciphers", prxSSL.Ciphers)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_protocols", strings.Split(prxSSL.Protocols, " "))) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_verify", prxSSL.Verify)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_verify_depth", prxSSL.VerifyDepth)) + if prxSSL.ProxySSLName != "" { + certDirectives = append(certDirectives, buildDirective("proxy_ssl_name", prxSSL.ProxySSLName)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_server_name", prxSSL.ProxySSLServerName)) + } + } + if prxSSL.PemFileName != "" { + certDirectives = append(certDirectives, buildDirective("proxy_ssl_certificate", prxSSL.PemFileName)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_certificate_key", prxSSL.PemFileName)) + } + if server.SSLCiphers != "" { + certDirectives = append(certDirectives, buildDirective("ssl_ciphers", server.SSLCiphers)) + } + + if server.SSLPreferServerCiphers != "" { + certDirectives = append(certDirectives, buildDirective("ssl_prefer_server_ciphers", server.SSLPreferServerCiphers)) + } + + return certDirectives +} + +// buildRedirectServer builds the server blocks for redirections +func (c *Template) buildRedirectServer(server *utilingress.Redirect) *ngx_crossplane.Directive { + serverBlock := ngx_crossplane.Directives{ + buildDirective("server_name", server.From), + buildDirective("ssl_certificate_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_certificate.lua"), + buildDirective("set_by_lua_file", "$redirect_to", "/etc/nginx/lua/nginx/ngx_srv_redirect.lua", server.To), + } + serverBlock = append(serverBlock, buildListener(*c.tplConfig, server.From)...) + serverBlock = append(serverBlock, c.buildBlockers()...) + serverBlock = append(serverBlock, buildDirective("return", c.tplConfig.Cfg.HTTPRedirectCode, "$redirect_to")) + + return &ngx_crossplane.Directive{ + Directive: "server", + Block: serverBlock, + } +} + +// buildDefaultBackend builds the default catch all server +func (c *Template) buildDefaultBackend() *ngx_crossplane.Directive { + var reusePort *string + if c.tplConfig.Cfg.ReusePort { + reusePort = ptr.To("reuseport") + } + serverBlock := ngx_crossplane.Directives{ + buildDirective("listen", c.tplConfig.ListenPorts.Default, "default_server", reusePort, fmt.Sprintf("backlog=%d", c.tplConfig.BacklogSize)), + } + if c.tplConfig.IsIPV6Enabled { + serverBlock = append(serverBlock, buildDirective( + "listen", + fmt.Sprintf("[::]:%d", c.tplConfig.ListenPorts.Default), + "default_server", reusePort, + fmt.Sprintf("backlog=%d", c.tplConfig.BacklogSize), + )) + } + serverBlock = append(serverBlock, buildDirective("set", "$proxy_upstream_name", "internal")) + serverBlock = append(serverBlock, buildDirective("access_log", "off")) + serverBlock = append(serverBlock, buildBlockDirective("location", []string{"/"}, ngx_crossplane.Directives{ + buildDirective("return", "404"), + })) + + return &ngx_crossplane.Directive{ + Directive: "server", + Block: serverBlock, + } +} + +func (c *Template) buildHealthAndStatsServer() *ngx_crossplane.Directive { + serverBlock := ngx_crossplane.Directives{ + buildDirective("listen", fmt.Sprintf("127.0.0.1:%d", c.tplConfig.StatusPort)), + buildDirective("set", "$proxy_upstream_name", "internal"), + buildDirective("keepalive_timeout", "0"), + buildDirective("gzip", "off"), + buildDirective("access_log", "off"), + buildBlockDirective( + "location", + []string{c.tplConfig.HealthzURI}, ngx_crossplane.Directives{ + buildDirective("return", "200"), + }), + buildBlockDirective( + "location", + []string{"/is-dynamic-lb-initialized"}, ngx_crossplane.Directives{ + buildDirective("content_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua"), + }), + buildBlockDirective( + "location", + []string{c.tplConfig.StatusPath}, ngx_crossplane.Directives{ + buildDirective("stub_status", "on"), + }), + buildBlockDirective( + "location", + []string{"/configuration"}, ngx_crossplane.Directives{ + buildDirective("client_max_body_size", luaConfigurationRequestBodySize(c.tplConfig.Cfg)), + buildDirective("client_body_buffer_size", luaConfigurationRequestBodySize(c.tplConfig.Cfg)), + buildDirective("proxy_buffering", "off"), + buildDirective("content_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_configuration.lua"), + }), + buildBlockDirective( + "location", + []string{"/"}, ngx_crossplane.Directives{ + buildDirective("return", "404"), + }), + } + if c.tplConfig.Cfg.EnableOpentelemetry { + serverBlock = append(serverBlock, buildDirective("opentelemetry", "off")) + } + + return &ngx_crossplane.Directive{ + Directive: "server", + Block: serverBlock, + } +} + +func (c *Template) buildBlockers() ngx_crossplane.Directives { + blockers := make(ngx_crossplane.Directives, 0) + if len(c.tplConfig.Cfg.BlockUserAgents) > 0 { + uaDirectives := buildBlockDirective("if", []string{"$block_ua"}, ngx_crossplane.Directives{ + buildDirective("return", "403"), + }) + blockers = append(blockers, uaDirectives) + } + + if len(c.tplConfig.Cfg.BlockReferers) > 0 { + refDirectives := buildBlockDirective("if", []string{"$block_ref"}, ngx_crossplane.Directives{ + buildDirective("return", "403"), + }) + blockers = append(blockers, refDirectives) + } + return blockers +} diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl index 64e5a0c3f9..547fd12dac 100644 --- a/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl +++ b/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl @@ -86,113 +86,113 @@ http { {{ range $index, $file := $all.MaxmindEditionFiles }} {{ if eq $file "GeoLite2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; - $geoip2_country_name source=$remote_addr country names en; - $geoip2_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_continent_code source=$remote_addr continent code; - $geoip2_continent_name source=$remote_addr continent names en; - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + $geoip2_country_code source=$remote_addr country iso_code; # OK + $geoip2_country_name source=$remote_addr country names en; # OK + $geoip2_country_geoname_id source=$remote_addr country geoname_id; # OK + $geoip2_continent_code source=$remote_addr continent code; # OK + $geoip2_continent_name source=$remote_addr continent names en; # OK + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; # OK } {{ end }} {{ if eq $file "GeoIP2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; - $geoip2_country_name source=$remote_addr country names en; - $geoip2_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_continent_code source=$remote_addr continent code; - $geoip2_continent_name source=$remote_addr continent names en; - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; + $geoip2_country_code source=$remote_addr country iso_code; # OK + $geoip2_country_name source=$remote_addr country names en; # OK + $geoip2_country_geoname_id source=$remote_addr country geoname_id; # OK + $geoip2_continent_code source=$remote_addr continent code; # OK + $geoip2_continent_name source=$remote_addr continent names en; # OK + $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; # OK } {{ end }} {{ if eq $file "GeoLite2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; - $geoip2_city_country_name source=$remote_addr country names en; - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_city source=$remote_addr city names en; - $geoip2_city_geoname_id source=$remote_addr city geoname_id; - $geoip2_postal_code source=$remote_addr postal code; - $geoip2_dma_code source=$remote_addr location metro_code; - $geoip2_latitude source=$remote_addr location latitude; - $geoip2_longitude source=$remote_addr location longitude; - $geoip2_time_zone source=$remote_addr location time_zone; - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; - $geoip2_region_name source=$remote_addr subdivisions 0 names en; - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; - $geoip2_city_continent_code source=$remote_addr continent code; - $geoip2_city_continent_name source=$remote_addr continent names en; + $geoip2_city_country_code source=$remote_addr country iso_code; # OK + $geoip2_city_country_name source=$remote_addr country names en; # OK + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; # OK + $geoip2_city source=$remote_addr city names en; # OK + $geoip2_city_geoname_id source=$remote_addr city geoname_id; # OK + $geoip2_postal_code source=$remote_addr postal code; # OK + $geoip2_dma_code source=$remote_addr location metro_code; # OK + $geoip2_latitude source=$remote_addr location latitude; # OK + $geoip2_longitude source=$remote_addr location longitude; # OK + $geoip2_time_zone source=$remote_addr location time_zone; # OK + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; # OK + $geoip2_region_name source=$remote_addr subdivisions 0 names en; # OK + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; # OK + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; # OK + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; # OK + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; # OK + $geoip2_city_continent_code source=$remote_addr continent code; # OK + $geoip2_city_continent_name source=$remote_addr continent names en; # OK } {{ end }} {{ if eq $file "GeoIP2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; - $geoip2_city_country_name source=$remote_addr country names en; - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_city source=$remote_addr city names en; - $geoip2_city_geoname_id source=$remote_addr city geoname_id; - $geoip2_postal_code source=$remote_addr postal code; - $geoip2_dma_code source=$remote_addr location metro_code; - $geoip2_latitude source=$remote_addr location latitude; - $geoip2_longitude source=$remote_addr location longitude; - $geoip2_time_zone source=$remote_addr location time_zone; - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; - $geoip2_region_name source=$remote_addr subdivisions 0 names en; - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; - $geoip2_city_continent_code source=$remote_addr continent code; - $geoip2_city_continent_name source=$remote_addr continent names en; + $geoip2_city_country_code source=$remote_addr country iso_code; # OK + $geoip2_city_country_name source=$remote_addr country names en; # OK + $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; # OK + $geoip2_city source=$remote_addr city names en; # OK + $geoip2_city_geoname_id source=$remote_addr city geoname_id; # OK + $geoip2_postal_code source=$remote_addr postal code; # OK + $geoip2_dma_code source=$remote_addr location metro_code; # OK + $geoip2_latitude source=$remote_addr location latitude; # OK + $geoip2_longitude source=$remote_addr location longitude; # OK + $geoip2_time_zone source=$remote_addr location time_zone; # OK + $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; # OK + $geoip2_region_name source=$remote_addr subdivisions 0 names en; # OK + $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; # OK + $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; # OK + $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; # OK + $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; # OK + $geoip2_city_continent_code source=$remote_addr continent code; # OK + $geoip2_city_continent_name source=$remote_addr continent names en; # OK } {{ end }} {{ if eq $file "GeoLite2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; - $geoip2_org source=$remote_addr autonomous_system_organization; + $geoip2_asn source=$remote_addr autonomous_system_number; # OK + $geoip2_org source=$remote_addr autonomous_system_organization; # OK } {{ end }} {{ if eq $file "GeoIP2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; - $geoip2_org source=$remote_addr autonomous_system_organization; + $geoip2_asn source=$remote_addr autonomous_system_number; # OK + $geoip2_org source=$remote_addr autonomous_system_organization; # OK } {{ end }} {{ if eq $file "GeoIP2-ISP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_isp source=$remote_addr isp; - $geoip2_isp_org source=$remote_addr organization; - $geoip2_asn source=$remote_addr default=0 autonomous_system_number; + $geoip2_isp source=$remote_addr isp; # OK + $geoip2_isp_org source=$remote_addr organization; # OK + $geoip2_asn source=$remote_addr default=0 autonomous_system_number; # OK } {{ end }} @@ -203,16 +203,16 @@ http { {{ end }} {{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { + geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { # OK {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; + auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK {{ end }} - $geoip2_is_anon source=$remote_addr is_anonymous; - $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; - $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; - $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; - $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; - $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; + $geoip2_is_anon source=$remote_addr is_anonymous; # OK + $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; # OK + $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; # OK + $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; # OK + $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; # OK + $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; # OK } {{ end }} @@ -252,7 +252,7 @@ http { {{ if and (ne $cfg.HTTP2MaxHeaderSize "") (ne $cfg.HTTP2MaxFieldSize "") }} # OK http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; # OK - http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; # OK + http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; # OK {{ end }} {{ if (gt $cfg.HTTP2MaxRequests 0) }} # OK @@ -519,28 +519,28 @@ http { {{/* Build server redirects (from/to www) */}} {{ range $redirect := .RedirectServers }} ## start server {{ $redirect.From }} - server { - server_name {{ $redirect.From }}; + server { #OK + server_name {{ $redirect.From }}; # OK - {{ buildHTTPListener $all $redirect.From }} - {{ buildHTTPSListener $all $redirect.From }} + {{ buildHTTPListener $all $redirect.From }} # OK + {{ buildHTTPSListener $all $redirect.From }} # OK - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; # OK {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { - return 403; + if ($block_ua) { # OK + return 403; # OK } {{ end }} {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { - return 403; + if ($block_ref) { # OK + return 403; #OK } {{ end }} - set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; + set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; # OK - return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; + return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; # OK } ## end server {{ $redirect.From }} {{ end }} @@ -567,234 +567,111 @@ http { {{ range $server := $servers }} ## start server {{ $server.Hostname }} server { - server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; + server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; OK {{ if $cfg.UseHTTP2 }} - http2 on; + http2 on; OK {{ end }} {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { - return 403; + if ($block_ua) { OK + return 403; OK } {{ end }} {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { - return 403; + if ($block_ref) { OK + return 403; OK } {{ end }} {{ template "SERVER" serverConfig $all $server }} - {{ if not (empty $cfg.ServerSnippet) }} - # Custom code snippet configured in the configuration configmap - {{ $cfg.ServerSnippet }} - {{ end }} - - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics $cfg.EnableModsecurity) }} + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics) }} # OK } ## end server {{ $server.Hostname }} {{ end }} # backend for when default-backend-service is not configured or it does not have endpoints - server { - listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; - {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} - set $proxy_upstream_name "internal"; + server { # OK + listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; # OK + {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} # OK + set $proxy_upstream_name "internal"; # OK - access_log off; + access_log off; # OK - location / { - return 404; + location / { # OK + return 404; # OK } } # default server, used for NGINX healthcheck and access to nginx stats - server { - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; - {{ end }} + server { # OK - listen 127.0.0.1:{{ .StatusPort }}; - set $proxy_upstream_name "internal"; + listen 127.0.0.1:{{ .StatusPort }}; # OK + set $proxy_upstream_name "internal"; # OK - keepalive_timeout 0; - gzip off; + keepalive_timeout 0; # OK + gzip off; # OK - access_log off; + access_log off; # OK {{ if $cfg.EnableOpentelemetry }} - opentelemetry off; + opentelemetry off; # OK {{ end }} - location {{ $healthzURI }} { - return 200; + location {{ $healthzURI }} { # OK + return 200; # OK } - location /is-dynamic-lb-initialized { - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; + location /is-dynamic-lb-initialized { # OK + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; # OK } - location {{ .StatusPath }} { - stub_status on; + location {{ .StatusPath }} { # OK + stub_status on; # OK } - location /configuration { - client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; - client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; - proxy_buffering off; + location /configuration { # OK + client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; # OK + client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; # OK + proxy_buffering off; # OK - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; + content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; # OK } - location / { - return 404; + location / { # OK + return 404; # OK } } } -stream { - lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;;"; - - lua_shared_dict tcp_udp_configuration_data 5M; - - {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} - - init_by_lua_file /etc/nginx/lua/ngx_conf_init_stream.lua; - - init_worker_by_lua_file /etc/nginx/lua/nginx/ngx_conf_init_tcp_udp.lua; - - lua_add_variable $proxy_upstream_name; - - log_format log_stream '{{ $cfg.LogFormatStream }}'; - - {{ if or $cfg.DisableAccessLog $cfg.DisableStreamAccessLog }} - access_log off; - {{ else }} - access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }}; - {{ end }} - - - error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; - {{ if $cfg.EnableRealIP }} - {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} - set_real_ip_from {{ $trusted_ip }}; - {{ end }} - {{ end }} - - upstream upstream_balancer { - server 0.0.0.1:1234; # placeholder - balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer_tcp_udp.lua; - } - - server { - listen 127.0.0.1:{{ .StreamPort }}; - - access_log off; - - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_content_tcp_udp.lua; - } - - # TCP services - {{ range $tcpServer := .TCPBackends }} - server { - preread_by_lua_block { - ngx.var.proxy_upstream_name="tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}"; - } - - {{ range $address := $all.Cfg.BindAddressIpv4 }} - listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ else }} - listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ end }} - {{ if $IsIPV6Enabled }} - {{ range $address := $all.Cfg.BindAddressIpv6 }} - listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ else }} - listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ end }} - {{ end }} - proxy_timeout {{ $cfg.ProxyStreamTimeout }}; - proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; - proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; - - proxy_pass upstream_balancer; - {{ if $tcpServer.Backend.ProxyProtocol.Encode }} - proxy_protocol on; - {{ end }} - } - {{ end }} - - # UDP services - {{ range $udpServer := .UDPBackends }} - server { - preread_by_lua_block { - ngx.var.proxy_upstream_name="udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}"; - } - - {{ range $address := $all.Cfg.BindAddressIpv4 }} - listen {{ $address }}:{{ $udpServer.Port }} udp; - {{ else }} - listen {{ $udpServer.Port }} udp; - {{ end }} - {{ if $IsIPV6Enabled }} - {{ range $address := $all.Cfg.BindAddressIpv6 }} - listen {{ $address }}:{{ $udpServer.Port }} udp; - {{ else }} - listen [::]:{{ $udpServer.Port }} udp; - {{ end }} - {{ end }} - proxy_responses {{ $cfg.ProxyStreamResponses }}; - proxy_timeout {{ $cfg.ProxyStreamTimeout }}; - proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; - proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; - proxy_pass upstream_balancer; - } - {{ end }} - - # Stream Snippets - {{ range $snippet := .StreamSnippets }} - {{ $snippet }} - {{ end }} -} - {{/* definition of templates to avoid repetitions */}} {{ define "CUSTOM_ERRORS" }} {{ $enableMetrics := .EnableMetrics }} - {{ $modsecurityEnabled := .ModsecurityEnabled }} {{ $upstreamName := .UpstreamName }} {{ range $errCode := .ErrorCodes }} - location @custom_{{ $upstreamName }}_{{ $errCode }} { - internal; - - # Ensure that modsecurity will not run on custom error pages or they might be blocked - {{ if $modsecurityEnabled }} - modsecurity off; - {{ end }} - - proxy_intercept_errors off; - - proxy_set_header X-Code {{ $errCode }}; - proxy_set_header X-Format $http_accept; - proxy_set_header X-Original-URI $request_uri; - proxy_set_header X-Namespace $namespace; - proxy_set_header X-Ingress-Name $ingress_name; - proxy_set_header X-Service-Name $service_name; - proxy_set_header X-Service-Port $service_port; - proxy_set_header X-Request-ID $req_id; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $best_http_host; - - set $proxy_upstream_name {{ $upstreamName | quote }}; - - rewrite (.*) / break; - - proxy_pass http://upstream_balancer; + location @custom_{{ $upstreamName }}_{{ $errCode }} { # OK + internal; # OK + proxy_intercept_errors off; # OK + + proxy_set_header X-Code {{ $errCode }}; # OK + proxy_set_header X-Format $http_accept; # OK + proxy_set_header X-Original-URI $request_uri; # OK + proxy_set_header X-Namespace $namespace; # OK + proxy_set_header X-Ingress-Name $ingress_name; # OK + proxy_set_header X-Service-Name $service_name;# OK + proxy_set_header X-Service-Port $service_port; # OK + proxy_set_header X-Request-ID $req_id;# OK + proxy_set_header X-Forwarded-For $remote_addr; # OK + proxy_set_header Host $best_http_host; # OK + + set $proxy_upstream_name {{ $upstreamName | quote }}; # OK + + rewrite (.*) / break; # OK + + proxy_pass http://upstream_balancer; # OK {{ if $enableMetrics }} - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; # OK {{ end }} } {{ end }} @@ -807,29 +684,29 @@ stream { {{ if $cors.CorsAllowOrigin }} {{ buildCorsOriginRegex $cors.CorsAllowOrigin }} {{ end }} - if ($request_method = 'OPTIONS') { - set $cors ${cors}options; + if ($request_method = 'OPTIONS') { # OK + set $cors ${cors}options; # OK } - if ($cors = "true") { - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; + if ($cors = "true") { # OK + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; # OK + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} # OK + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; # OK + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; # OK + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} # OK + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; # OK } - if ($cors = "trueoptions") { - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; - more_set_headers 'Content-Type: text/plain charset=UTF-8'; - more_set_headers 'Content-Length: 0'; - return 204; + if ($cors = "trueoptions") { # OK + more_set_headers 'Access-Control-Allow-Origin: $http_origin'; # OK + {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} # OK + more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; # OK + more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; # OK + {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} # OK + more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; # OK + more_set_headers 'Content-Type: text/plain charset=UTF-8'; # OK + more_set_headers 'Content-Length: 0'; # OK + return 204; # OK } {{ end }} @@ -838,321 +715,300 @@ stream { {{ $all := .First }} {{ $server := .Second }} - {{ buildHTTPListener $all $server.Hostname }} - {{ buildHTTPSListener $all $server.Hostname }} + {{ buildHTTPListener $all $server.Hostname }} # OK + {{ buildHTTPSListener $all $server.Hostname }} # OK - set $proxy_upstream_name "-"; + set $proxy_upstream_name "-"; # OK {{ if not ( empty $server.CertificateAuth.MatchCN ) }} {{ if gt (len $server.CertificateAuth.MatchCN) 0 }} - if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { - return 403 "client certificate unauthorized"; + if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { # OK + return 403 "client certificate unauthorized"; # OK } {{ end }} {{ end }} {{ if eq $server.Hostname "_" }} - ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; + ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; # OK {{ end }} - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; + ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; # OK {{ if not (empty $server.AuthTLSError) }} - # {{ $server.AuthTLSError }} + # {{ $server.AuthTLSError }} # NOT, WHERE THIS IF ENDS?? Couldn't reproduce this config on my ingress return 403; {{ else }} {{ if not (empty $server.CertificateAuth.CAFileName) }} # PEM sha: {{ $server.CertificateAuth.CASHA }} - ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; - ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; - ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; + ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; # OK + ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; # OK + ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; # OK {{ if not (empty $server.CertificateAuth.CRLFileName) }} # PEM sha: {{ $server.CertificateAuth.CRLSHA }} - ssl_crl {{ $server.CertificateAuth.CRLFileName }}; + ssl_crl {{ $server.CertificateAuth.CRLFileName }}; # OK {{ end }} {{ if not (empty $server.CertificateAuth.ErrorPage)}} - error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; + error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; # OK {{ end }} {{ end }} {{ if not (empty $server.ProxySSL.CAFileName) }} # PEM sha: {{ $server.ProxySSL.CASHA }} - proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; - proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; - proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; - proxy_ssl_verify {{ $server.ProxySSL.Verify }}; - proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; + proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; # OK + proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; # OK + proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; # OK + proxy_ssl_verify {{ $server.ProxySSL.Verify }}; # OK + proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; # OK {{ if not (empty $server.ProxySSL.ProxySSLName) }} - proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; - proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; + proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; # OK + proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; # OK {{ end }} {{ end }} {{ if not (empty $server.ProxySSL.PemFileName) }} - proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; - proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; + proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; # OK + proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; # OK {{ end }} {{ if not (empty $server.SSLCiphers) }} - ssl_ciphers {{ $server.SSLCiphers }}; + ssl_ciphers {{ $server.SSLCiphers }}; # OK {{ end }} {{ if not (empty $server.SSLPreferServerCiphers) }} - ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; - {{ end }} - - {{ if not (empty $server.ServerSnippet) }} - # Custom code snippet configured for host {{ $server.Hostname }} - {{ $server.ServerSnippet }} + ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; # OK {{ end }} - {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics $all.Cfg.EnableModsecurity) }} + {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} # OK + {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics) }} # OK {{ end }} - {{ buildMirrorLocations $server.Locations }} + {{ buildMirrorLocations $server.Locations }} # OK - {{ $enforceRegex := enforceRegexModifier $server.Locations }} + {{ $enforceRegex := enforceRegexModifier $server.Locations }} # OK {{ range $location := $server.Locations }} - {{ $path := buildLocation $location $enforceRegex }} - {{ $proxySetHeader := proxySetHeader $location }} - {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} + {{ $path := buildLocation $location $enforceRegex }} # OK + {{ $proxySetHeader := proxySetHeader $location }} # OK + {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} # OK + {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} # OK + {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} # OK - {{ $externalAuth := $location.ExternalAuth }} + {{ $externalAuth := $location.ExternalAuth }} # OK {{ if eq $applyGlobalAuth true }} - {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} + {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} # OK {{ end }} {{ if not (empty $location.Rewrite.AppRoot) }} - if ($uri = /) { - return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; + if ($uri = /) { # OK + return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; # OK } {{ end }} {{ if $authPath }} location = {{ $authPath }} { - internal; + internal; # OK {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} - opentelemetry on; - opentelemetry_propagate; + opentelemetry on; # OK + opentelemetry_propagate; # OK {{ end }} {{ if not $all.Cfg.EnableAuthAccessLog }} - access_log off; - {{ end }} - - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; + access_log off; # OK {{ end }} {{ if $externalAuth.AuthCacheKey }} - set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; - set $cache_key ''; + set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; # OK + set $cache_key ''; # OK - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; # OK - proxy_cache auth_cache; + proxy_cache auth_cache; # OK {{- range $dur := $externalAuth.AuthCacheDuration }} - proxy_cache_valid {{ $dur }}; + proxy_cache_valid {{ $dur }}; # OK {{- end }} - proxy_cache_key "$cache_key"; + proxy_cache_key "$cache_key"; # OK {{ end }} # ngx_auth_request module overrides variables in the parent request, # therefore we have to explicitly set this variable again so that when the parent request # resumes it has the correct value set for this variable so that Lua can pick backend correctly - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; # OK - proxy_pass_request_body off; - proxy_set_header Content-Length ""; - proxy_set_header X-Forwarded-Proto ""; - proxy_set_header X-Request-ID $req_id; + proxy_pass_request_body off; # OK + proxy_set_header Content-Length ""; # OK + proxy_set_header X-Forwarded-Proto ""; # OK + proxy_set_header X-Request-ID $req_id; # OK {{ if $externalAuth.Method }} - proxy_method {{ $externalAuth.Method }}; - proxy_set_header X-Original-URI $request_uri; - proxy_set_header X-Scheme $pass_access_scheme; + proxy_method {{ $externalAuth.Method }}; + proxy_set_header X-Original-URI $request_uri; # OK + proxy_set_header X-Scheme $pass_access_scheme; # OK {{ end }} - proxy_set_header Host {{ $externalAuth.Host }}; - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; - proxy_set_header X-Original-Method $request_method; - proxy_set_header X-Sent-From "nginx-ingress-controller"; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host {{ $externalAuth.Host }}; # OK + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; # OK + proxy_set_header X-Original-Method $request_method; # OK + proxy_set_header X-Sent-From "nginx-ingress-controller"; # OK + proxy_set_header X-Real-IP $remote_addr; # OK {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - proxy_set_header X-Forwarded-For $full_x_forwarded_for; + proxy_set_header X-Forwarded-For $full_x_forwarded_for; # OK {{ else }} - proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; # OK {{ end }} {{ if $externalAuth.RequestRedirect }} - proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; + proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; # OK {{ else }} - proxy_set_header X-Auth-Request-Redirect $request_uri; + proxy_set_header X-Auth-Request-Redirect $request_uri; # OK {{ end }} {{ if $externalAuth.AuthCacheKey }} - proxy_buffering "on"; + proxy_buffering "on"; # OK {{ else }} - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; # OK {{ end }} - proxy_buffer_size {{ $location.Proxy.BufferSize }}; - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; + proxy_buffer_size {{ $location.Proxy.BufferSize }}; # OK + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; # OK + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; # OK - proxy_ssl_server_name on; - proxy_pass_request_headers on; + proxy_ssl_server_name on; # OK + proxy_pass_request_headers on; # OK {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; + client_max_body_size {{ $location.Proxy.BodySize }}; # OK {{ end }} {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; # OK {{ end }} # Pass the extracted client certificate to the auth provider {{ if not (empty $server.CertificateAuth.CAFileName) }} {{ if $server.CertificateAuth.PassCertToUpstream }} - proxy_set_header ssl-client-cert $ssl_client_escaped_cert; + proxy_set_header ssl-client-cert $ssl_client_escaped_cert; # OK {{ end }} - proxy_set_header ssl-client-verify $ssl_client_verify; - proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; - proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; + proxy_set_header ssl-client-verify $ssl_client_verify; # OK + proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; # OK + proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; # OK {{ end }} {{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} - {{ $line }} + {{ $line }} # OK {{- end }} - {{ if not (empty $externalAuth.AuthSnippet) }} - {{ $externalAuth.AuthSnippet }} - {{ end }} - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} # The target is an upstream with HTTP keepalive, that is why the # Connection header is cleared and the HTTP version is set to 1.1 as # the Nginx documentation suggests: # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - proxy_http_version 1.1; - proxy_set_header Connection ""; - set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; + proxy_http_version 1.1; # OK + proxy_set_header Connection ""; # OK + set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; # OK {{ else }} - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; - set $target {{ $externalAuth.URL }}; + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; # OK + set $target {{ $externalAuth.URL }}; # OK {{ end }} - proxy_pass $target; + proxy_pass $target; # OK } {{ end }} {{ if isLocationAllowed $location }} {{ if $externalAuth.SigninURL }} location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { - internal; + internal; # OK - add_header Set-Cookie $auth_cookie; + add_header Set-Cookie $auth_cookie; # OK {{ if $location.CorsConfig.CorsEnabled }} - {{ template "CORS" $location }} - {{ end }} - - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; + {{ template "CORS" $location }} # OK {{ end }} - return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; + return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; # OK } {{ end }} {{ end }} location {{ $path }} { {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} - set $namespace {{ $ing.Namespace | quote}}; - set $ingress_name {{ $ing.Rule | quote }}; - set $service_name {{ $ing.Service | quote }}; - set $service_port {{ $ing.ServicePort | quote }}; - set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; + set $namespace {{ $ing.Namespace | quote}}; # OK + set $ingress_name {{ $ing.Rule | quote }}; # OK + set $service_name {{ $ing.Service | quote }}; # OK + set $service_port {{ $ing.ServicePort | quote }}; # OK + set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; # OK - {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} + {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} # OK {{ if $location.Mirror.Source }} - mirror {{ $location.Mirror.Source }}; - mirror_request_body {{ $location.Mirror.RequestBody }}; + mirror {{ $location.Mirror.Source }}; # OK + mirror_request_body {{ $location.Mirror.RequestBody }}; # OK {{ end }} - {{ locationConfigForLua $location $all }} + {{ locationConfigForLua $location $all }} # OK - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; + rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; # OK - header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; + header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; # OK - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; + log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; # OK {{ if not $location.Logs.Access }} - access_log off; + access_log off; # OK {{ end }} {{ if $location.Logs.Rewrite }} - rewrite_log on; + rewrite_log on; # OK {{ end }} {{ if $location.HTTP2PushPreload }} - http2_push_preload on; + http2_push_preload on; # OK {{ end }} - port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; + port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; # OK - set $balancer_ewma_score -1; - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; - set $proxy_host $proxy_upstream_name; - set $pass_access_scheme $scheme; + set $balancer_ewma_score -1; # OK + set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; # OK + set $proxy_host $proxy_upstream_name; # OK + set $pass_access_scheme $scheme; # OK {{ if $all.Cfg.UseProxyProtocol }} - set $pass_server_port $proxy_protocol_server_port; + set $pass_server_port $proxy_protocol_server_port; # OK {{ else }} - set $pass_server_port $server_port; + set $pass_server_port $server_port; # OK {{ end }} - set $best_http_host $http_host; - set $pass_port $pass_server_port; + set $best_http_host $http_host; # OK + set $pass_port $pass_server_port; # OK - set $proxy_alternative_upstream_name ""; + set $proxy_alternative_upstream_name ""; # OK - {{ buildModSecurityForLocation $all.Cfg $location }} + {{ if isLocationAllowed $location }} # 1 + {{ if gt (len $location.Denylist.CIDR) 0 }} # 2 + {{ range $ip := $location.Denylist.CIDR }} # 3 + deny {{ $ip }};{{ end }} # 2 # OK + {{ end }} # 1 + {{ if gt (len $location.Allowlist.CIDR) 0 }} # 2 + {{ range $ip := $location.Allowlist.CIDR }} # 3 + allow {{ $ip }};{{ end }} # 2 # OK + deny all; # OK + {{ end }} # 1 - {{ if isLocationAllowed $location }} - {{ if gt (len $location.Denylist.CIDR) 0 }} - {{ range $ip := $location.Denylist.CIDR }} - deny {{ $ip }};{{ end }} - {{ end }} - {{ if gt (len $location.Allowlist.CIDR) 0 }} - {{ range $ip := $location.Allowlist.CIDR }} - allow {{ $ip }};{{ end }} - deny all; - {{ end }} + {{ if $location.CorsConfig.CorsEnabled }} # 2 + {{ template "CORS" $location }} # OK + {{ end }} # 1 - {{ if $location.CorsConfig.CorsEnabled }} - {{ template "CORS" $location }} - {{ end }} - - {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} - {{ if $authPath }} + {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} # 2 + {{ if $authPath }} # 3 # this location requires authentication - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} + {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} # 4 set $auth_cookie ''; add_header Set-Cookie $auth_cookie; - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} # 5 {{ $line }} - {{- end }} + {{- end }} # 4 # `auth_request` module does not support HTTP keepalives in upstream block: # https://trac.nginx.org/nginx/ticket/1579 access_by_lua_block { @@ -1172,224 +1028,217 @@ stream { {{ else }} auth_request {{ $authPath }}; auth_request_set $auth_cookie $upstream_http_set_cookie; - {{ if $externalAuth.AlwaysSetCookie }} + {{ if $externalAuth.AlwaysSetCookie }} # 5 add_header Set-Cookie $auth_cookie always; {{ else }} add_header Set-Cookie $auth_cookie; - {{ end }} - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} + {{ end }} # 4 + {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} # 5 {{ $line }} - {{- end }} - {{ end }} - {{ end }} + {{- end }} # 4 + {{ end }} # 3 + {{ end }} # 2 - {{ if $externalAuth.SigninURL }} + {{ if $externalAuth.SigninURL }} # 3 set_escape_uri $escaped_request_uri $request_uri; error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; - {{ end }} + {{ end }} # 2 - {{ if $location.BasicDigestAuth.Secured }} - {{ if eq $location.BasicDigestAuth.Type "basic" }} + {{ if $location.BasicDigestAuth.Secured }} # 3 + {{ if eq $location.BasicDigestAuth.Type "basic" }} # 4 auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; auth_basic_user_file {{ $location.BasicDigestAuth.File }}; {{ else }} auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; auth_digest_user_file {{ $location.BasicDigestAuth.File }}; - {{ end }} + {{ end }} # 3 {{ $proxySetHeader }} Authorization ""; - {{ end }} - {{ end }} + {{ end }} # 2 + {{ end }} # 1 {{/* if the location contains a rate limit annotation, create one */}} {{ $limits := buildRateLimit $location }} - {{ range $limit := $limits }} - {{ $limit }}{{ end }} + {{ range $limit := $limits }} # 2 # OK + {{ $limit }}{{ end }} # 1 {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; + client_max_body_size {{ $location.Proxy.BodySize }}; # OK {{ end }} {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; - {{ end }} + client_body_buffer_size {{ $location.ClientBodyBufferSize }}; # OK + {{ end }} # 1 {{/* By default use vhost as Host to upstream, but allow overrides */}} {{ if not (empty $location.UpstreamVhost) }} - {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; + {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; # OK {{ else }} - {{ $proxySetHeader }} Host $best_http_host; - {{ end }} + {{ $proxySetHeader }} Host $best_http_host; # OK + {{ end }} # 1 # Pass the extracted client certificate to the backend - {{ if not (empty $server.CertificateAuth.CAFileName) }} - {{ if $server.CertificateAuth.PassCertToUpstream }} - {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; - {{ end }} - {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; - {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; - {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; - {{ end }} + {{ if not (empty $server.CertificateAuth.CAFileName) }} # 2 + {{ if $server.CertificateAuth.PassCertToUpstream }} # 3 + {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; # OK + {{ end }} # 2 + {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; # OK + {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; # OK + {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; # OK + {{ end }} # 1 # Allow websocket connections - {{ $proxySetHeader }} Upgrade $http_upgrade; + {{ $proxySetHeader }} Upgrade $http_upgrade; # OK {{ if $location.Connection.Enabled}} - {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; + {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; # OK {{ else }} - {{ $proxySetHeader }} Connection $connection_upgrade; + {{ $proxySetHeader }} Connection $connection_upgrade; # OK {{ end }} - {{ $proxySetHeader }} X-Request-ID $req_id; - {{ $proxySetHeader }} X-Real-IP $remote_addr; + {{ $proxySetHeader }} X-Request-ID $req_id; # OK + {{ $proxySetHeader }} X-Real-IP $remote_addr; # OK {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; + {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; # OK {{ else }} - {{ $proxySetHeader }} X-Forwarded-For $remote_addr; - {{ end }} - {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; - {{ $proxySetHeader }} X-Forwarded-Port $pass_port; - {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; - {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; + {{ $proxySetHeader }} X-Forwarded-For $remote_addr; # OK + {{ end }} # 1 + {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; # OK + {{ $proxySetHeader }} X-Forwarded-Port $pass_port; # OK + {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; # OK + {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; # OK {{ if $all.Cfg.ProxyAddOriginalURIHeader }} - {{ $proxySetHeader }} X-Original-URI $request_uri; - {{ end }} - {{ $proxySetHeader }} X-Scheme $pass_access_scheme; + {{ $proxySetHeader }} X-Original-URI $request_uri; # OK + {{ end }} # 1 + {{ $proxySetHeader }} X-Scheme $pass_access_scheme; # OK # Pass the original X-Forwarded-For - {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; + {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; # OK # mitigate HTTPoxy Vulnerability # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - {{ $proxySetHeader }} Proxy ""; + {{ $proxySetHeader }} Proxy ""; # OK # Custom headers to proxied server {{ range $k, $v := $all.ProxySetHeaders }} - {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; - {{ end }} + {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; # OK + {{ end }} # 1 - proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; - proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; - proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; + proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; OK + proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; # OK + proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; # OK - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; - proxy_buffer_size {{ $location.Proxy.BufferSize }}; - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; + proxy_buffering {{ $location.Proxy.ProxyBuffering }}; # OK + proxy_buffer_size {{ $location.Proxy.BufferSize }}; # OK + proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; # OK {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} - proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; + proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; # OK {{ end }} - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; + proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; # OK + proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; # OK - proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; - proxy_cookie_path {{ $location.Proxy.CookiePath }}; + proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; # OK + proxy_cookie_path {{ $location.Proxy.CookiePath }}; # OK # In case of errors try the next upstream server before returning an error - proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; - proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; + proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; # OK + proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; # OK + proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; # OK {{ if or (eq $location.BackendProtocol "GRPC") (eq $location.BackendProtocol "GRPCS") }} # Grpc settings - grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; - grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; - grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; - {{ end }} + grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; # OK + grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; # OK + grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; # OK + {{ end }} # 1 - {{/* Add any additional configuration defined */}} - {{ $location.ConfigurationSnippet }} - - {{ if not (empty $all.Cfg.LocationSnippet) }} - # Custom code snippet configured in the configuration configmap - {{ $all.Cfg.LocationSnippet }} - {{ end }} - - {{ if $location.CustomHeaders }} + + {{ if $location.CustomHeaders }} # 2 # Custom Response Headers - {{ range $k, $v := $location.CustomHeaders.Headers }} - more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; - {{ end }} - {{ end }} + {{ range $k, $v := $location.CustomHeaders.Headers }} # 3 + more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; # OK + {{ end }} # 2 + {{ end }} # 1 {{/* if we are sending the request to a custom default backend, we add the required headers */}} {{ if (hasPrefix $location.Backend "custom-default-backend-") }} - proxy_set_header X-Code 503; - proxy_set_header X-Format $http_accept; - proxy_set_header X-Namespace $namespace; - proxy_set_header X-Ingress-Name $ingress_name; - proxy_set_header X-Service-Name $service_name; - proxy_set_header X-Service-Port $service_port; - proxy_set_header X-Request-ID $req_id; - {{ end }} + proxy_set_header X-Code 503; # OK + proxy_set_header X-Format $http_accept; # OK + proxy_set_header X-Namespace $namespace; # OK + proxy_set_header X-Ingress-Name $ingress_name; # OK + proxy_set_header X-Service-Name $service_name; # OK + proxy_set_header X-Service-Port $service_port; # OK + proxy_set_header X-Request-ID $req_id; # OK + {{ end }} # 1 {{ if $location.Satisfy }} - satisfy {{ $location.Satisfy }}; - {{ end }} + satisfy {{ $location.Satisfy }}; # OK + {{ end }} # 1 {{/* if a location-specific error override is set, add the proxy_intercept here */}} {{ if and $location.CustomHTTPErrors (not $location.DisableProxyInterceptErrors) }} # Custom error pages per ingress - proxy_intercept_errors on; - {{ end }} + proxy_intercept_errors on; # OK + {{ end }} # 1 {{ range $errCode := $location.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} + error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} # OK {{ if (eq $location.BackendProtocol "FCGI") }} - include /etc/nginx/fastcgi_params; - {{ end }} + include /etc/nginx/fastcgi_params; OK + {{ end }} # 1 {{- if $location.FastCGI.Index -}} - fastcgi_index {{ $location.FastCGI.Index | quote }}; - {{- end -}} + fastcgi_index {{ $location.FastCGI.Index | quote }}; # OK + {{- end -}} # 1 {{ range $k, $v := $location.FastCGI.Params }} - fastcgi_param {{ $k }} {{ $v | quote }}; - {{ end }} + fastcgi_param {{ $k }} {{ $v | quote }}; # OK + {{ end }} # 1 {{ if not (empty $location.Redirect.URL) }} - return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; - {{ end }} + return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; # OK + {{ end }} # 1 - {{ buildProxyPass $server.Hostname $all.Backends $location }} + {{ buildProxyPass $server.Hostname $all.Backends $location }} # OK {{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; - {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; - {{ end }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; # OK + {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} + proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; # OK + {{ end }} # 1 {{ else }} - # Location denied. Reason: {{ $location.Denied | quote }} - return 503; - {{ end }} - {{ if not (empty $location.ProxySSL.CAFileName) }} - # PEM sha: {{ $location.ProxySSL.CASHA }} - proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; - proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; - proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; - proxy_ssl_verify {{ $location.ProxySSL.Verify }}; - proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; - {{ end }} - - {{ if not (empty $location.ProxySSL.ProxySSLName) }} - proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; - {{ end }} - {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} - proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; - {{ end }} - - {{ if not (empty $location.ProxySSL.PemFileName) }} - proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; - proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; - {{ end }} + # Location denied. Reason: {{ $location.Denied | quote }} # OK + return 503; # OK + {{ end }} # 0 + {{ if not (empty $location.ProxySSL.CAFileName) }} # 1 + # PEM sha: {{ $location.ProxySSL.CASHA }} # OK + proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; # OK + proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; # OK + proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; # OK + proxy_ssl_verify {{ $location.ProxySSL.Verify }}; # OK + proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; # OK + {{ end }} # 0 + + {{ if not (empty $location.ProxySSL.ProxySSLName) }} # 1 + proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; # OK + {{ end }} # 0 + {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} # 1 + proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; # OK + {{ end }} # 0 + + {{ if not (empty $location.ProxySSL.PemFileName) }} # 1 + proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; # OK + proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; # OK + {{ end }} # 0 } - {{ end }} - {{ end }} + {{ end }} # End range + {{ end }} # Maybe that missing if... {{ if eq $server.Hostname "_" }} # health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} - location {{ $all.HealthzURI }} { + location {{ $all.HealthzURI }} { # OK {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; + opentelemetry off; # OK {{ end }} - access_log off; - return 200; + access_log off; # OK + return 200; # OK } # this is required to avoid error if nginx is being monitored @@ -1397,21 +1246,21 @@ stream { location /nginx_status { {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; + opentelemetry off; # OK {{ end }} {{ range $v := $all.NginxStatusIpv4Whitelist }} - allow {{ $v }}; + allow {{ $v }}; # OK {{ end }} {{ if $all.IsIPV6Enabled -}} {{ range $v := $all.NginxStatusIpv6Whitelist }} - allow {{ $v }}; + allow {{ $v }}; # OK {{ end }} {{ end -}} - deny all; + deny all; # OK - access_log off; - stub_status on; + access_log off; # OK + stub_status on; # OK } {{ end }} diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index 2b1b3a2dfc..ea0ade3c9b 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -17,18 +17,72 @@ limitations under the License. package crossplane import ( + "crypto/sha1" + "encoding/base64" + "encoding/hex" "fmt" "net" + "net/url" + "regexp" "strconv" + "strings" ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" + networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/klog/v2" + "k8s.io/utils/ptr" + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/annotations/ratelimit" "k8s.io/ingress-nginx/internal/ingress/controller/config" ing_net "k8s.io/ingress-nginx/internal/net" "k8s.io/ingress-nginx/pkg/apis/ingress" ) +const ( + slash = "/" + nonIdempotent = "non_idempotent" + defBufferSize = 65535 + writeIndentOnEmptyLines = true // backward-compatibility + httpProtocol = "HTTP" + autoHTTPProtocol = "AUTO_HTTP" + httpsProtocol = "HTTPS" + grpcProtocol = "GRPC" + grpcsProtocol = "GRPCS" + fcgiProtocol = "FCGI" +) + +var ( + nginxSizeRegex = regexp.MustCompile(`^\d+[kKmM]?$`) + nginxOffsetRegex = regexp.MustCompile(`^\d+[kKmMgG]?$`) + defaultGlobalAuthRedirectParam = "rd" +) + type seconds int +type minutes int + +func buildDirectiveWithComment(directive string, comment string, args ...any) *ngx_crossplane.Directive { + dir := buildDirective(directive, args...) + dir.Comment = ptr.To(comment) + return dir +} + +func buildStartServer(name string) *ngx_crossplane.Directive { + return buildDirective("##", "start", "server", name) +} + +func buildEndServer(name string) *ngx_crossplane.Directive { + return buildDirective("##", "end", "server", name) +} + +func buildStartAuthUpstream(name, location string) *ngx_crossplane.Directive { + return buildDirective("##", "start", "auth", "upstream", name, location) +} + +func buildEndAuthUpstream(name, location string) *ngx_crossplane.Directive { + return buildDirective("##", "end", "auth", "upstream", name, location) +} func buildDirective(directive string, args ...any) *ngx_crossplane.Directive { argsVal := make([]string, 0) @@ -36,6 +90,10 @@ func buildDirective(directive string, args ...any) *ngx_crossplane.Directive { switch v := args[k].(type) { case string: argsVal = append(argsVal, v) + case *string: + if v != nil { + argsVal = append(argsVal, *v) + } case []string: argsVal = append(argsVal, v...) case int: @@ -44,6 +102,8 @@ func buildDirective(directive string, args ...any) *ngx_crossplane.Directive { argsVal = append(argsVal, boolToStr(v)) case seconds: argsVal = append(argsVal, strconv.Itoa(int(v))+"s") + case minutes: + argsVal = append(argsVal, strconv.Itoa(int(v))+"m") } } return &ngx_crossplane.Directive{ @@ -141,3 +201,538 @@ func shouldLoadOpentelemetryModule(servers []*ingress.Server) bool { } return false } + +func buildServerName(hostname string) string { + if !strings.HasPrefix(hostname, "*") { + return hostname + } + + hostname = strings.Replace(hostname, "*.", "", 1) + parts := strings.Split(hostname, ".") + + return `~^(?[\w-]+)\.` + strings.Join(parts, "\\.") + `$` +} + +func buildListener(tc config.TemplateConfig, hostname string) ngx_crossplane.Directives { + listenDirectives := make(ngx_crossplane.Directives, 0) + + co := commonListenOptions(&tc, hostname) + + addrV4 := []string{""} + if len(tc.Cfg.BindAddressIpv4) > 0 { + addrV4 = tc.Cfg.BindAddressIpv4 + } + listenDirectives = append(listenDirectives, httpListener(addrV4, co, &tc, false)...) + listenDirectives = append(listenDirectives, httpListener(addrV4, co, &tc, true)...) + + if tc.IsIPV6Enabled { + addrV6 := []string{"[::]"} + if len(tc.Cfg.BindAddressIpv6) > 0 { + addrV6 = tc.Cfg.BindAddressIpv6 + } + listenDirectives = append(listenDirectives, httpListener(addrV6, co, &tc, false)...) + listenDirectives = append(listenDirectives, httpListener(addrV6, co, &tc, true)...) + } + + return listenDirectives +} + +// commonListenOptions defines the common directives that should be added to NGINX listeners +func commonListenOptions(template *config.TemplateConfig, hostname string) []string { + var out []string + + if template.Cfg.UseProxyProtocol { + out = append(out, "proxy_protocol") + } + + if hostname != "_" { + return out + } + + out = append(out, "default_server") + + if template.Cfg.ReusePort { + out = append(out, "reuseport") + } + out = append(out, fmt.Sprintf("backlog=%d", template.BacklogSize)) + return out +} + +func httpListener(addresses []string, co []string, tc *config.TemplateConfig, ssl bool) ngx_crossplane.Directives { + listeners := make(ngx_crossplane.Directives, 0) + port := tc.ListenPorts.HTTP + isTLSProxy := tc.IsSSLPassthroughEnabled + // If this is a SSL listener we should mutate the port properly + if ssl { + port = tc.ListenPorts.HTTPS + if isTLSProxy { + port = tc.ListenPorts.SSLProxy + } + } + for _, address := range addresses { + var listenAddress string + if address == "" { + listenAddress = fmt.Sprintf("%d", port) + } else { + listenAddress = fmt.Sprintf("%s:%d", address, port) + } + if ssl { + if isTLSProxy { + co = append(co, "proxy_protocol") + } + co = append(co, "ssl") + } + listenDirective := buildDirective("listen", listenAddress, co) + listeners = append(listeners, listenDirective) + } + + return listeners +} + +func luaConfigurationRequestBodySize(cfg config.Configuration) string { + size := cfg.LuaSharedDicts["configuration_data"] + if size < cfg.LuaSharedDicts["certificate_data"] { + size = cfg.LuaSharedDicts["certificate_data"] + } + size += 1024 + + return dictKbToStr(size) +} + +func buildLocation(location *ingress.Location, enforceRegex bool) []string { + path := location.Path + if enforceRegex { + return []string{"~*", fmt.Sprintf("^%s", path)} + } + + if location.PathType != nil && *location.PathType == networkingv1.PathTypeExact { + return []string{"=", path} + } + + return []string{path} +} + +func getProxySetHeader(location *ingress.Location) string { + if location.BackendProtocol == grpcProtocol || location.BackendProtocol == grpcsProtocol { + return "grpc_set_header" + } + + return "proxy_set_header" +} + +func buildAuthLocation(location *ingress.Location, globalExternalAuthURL string) string { + if (location.ExternalAuth.URL == "") && (!shouldApplyGlobalAuth(location, globalExternalAuthURL)) { + return "" + } + + str := base64.URLEncoding.EncodeToString([]byte(location.Path)) + // removes "=" after encoding + str = strings.ReplaceAll(str, "=", "") + + pathType := "default" + if location.PathType != nil { + pathType = string(*location.PathType) + } + + return fmt.Sprintf("/_external-auth-%v-%v", str, pathType) +} + +// shouldApplyGlobalAuth returns true only in case when ExternalAuth.URL is not set and +// GlobalExternalAuth is set and enabled +func shouldApplyGlobalAuth(location *ingress.Location, globalExternalAuthURL string) bool { + return location.ExternalAuth.URL == "" && + globalExternalAuthURL != "" && + location.EnableGlobalAuth +} + +// shouldApplyAuthUpstream returns true only in case when ExternalAuth.URL and +// ExternalAuth.KeepaliveConnections are all set +func shouldApplyAuthUpstream(location *ingress.Location, cfg config.Configuration) bool { + if location.ExternalAuth.URL == "" || location.ExternalAuth.KeepaliveConnections == 0 { + return false + } + + // Unfortunately, `auth_request` module ignores keepalive in upstream block: https://trac.nginx.org/nginx/ticket/1579 + // The workaround is to use `ngx.location.capture` Lua subrequests but it is not supported with HTTP/2 + if cfg.UseHTTP2 { + return false + } + return true +} + +func isValidByteSize(s string, isOffset bool) bool { + s = strings.TrimSpace(s) + if s == "" { + return false + } + + if isOffset { + return nginxOffsetRegex.MatchString(s) + } + + return nginxSizeRegex.MatchString(s) +} + +func buildAuthUpstreamName(input *ingress.Location, host string) string { + authPath := buildAuthLocation(input, "") + if authPath == "" || host == "" { + return "" + } + + return fmt.Sprintf("%s-%s", host, authPath[2:]) +} + +// changeHostPort will change the host:port part of the url to value +func changeHostPort(newURL, value string) string { + if newURL == "" { + return "" + } + + authURL, err := parser.StringToURL(newURL) + if err != nil { + klog.Errorf("expected a valid URL but %s was returned", newURL) + return "" + } + + authURL.Host = value + + return authURL.String() +} + +func buildAuthSignURLLocation(location, authSignURL string) string { + hasher := sha1.New() // #nosec + hasher.Write([]byte(location)) + hasher.Write([]byte(authSignURL)) + return "@" + hex.EncodeToString(hasher.Sum(nil)) +} + +func buildAuthSignURL(authSignURL, authRedirectParam string) string { + u, err := url.Parse(authSignURL) + if err != nil { + klog.Errorf("error parsing authSignURL: %v", err) + return "" + } + q := u.Query() + if authRedirectParam == "" { + authRedirectParam = defaultGlobalAuthRedirectParam + } + if len(q) == 0 { + return fmt.Sprintf("%v?%v=$pass_access_scheme://$http_host$escaped_request_uri", authSignURL, authRedirectParam) + } + + if q.Get(authRedirectParam) != "" { + return authSignURL + } + + return fmt.Sprintf("%v&%v=$pass_access_scheme://$http_host$escaped_request_uri", authSignURL, authRedirectParam) +} + +func buildCorsOriginRegex(corsOrigins []string) ngx_crossplane.Directives { + if len(corsOrigins) == 1 && corsOrigins[0] == "*" { + return ngx_crossplane.Directives{ + buildDirective("set", "$http_origin", "*"), + buildDirective("set", "$cors", "true"), + } + } + + originsArray := []string{"("} + for i, origin := range corsOrigins { + originTrimmed := strings.TrimSpace(origin) + if originTrimmed != "" { + originsArray = append(originsArray, buildOriginRegex(originTrimmed)) + } + if i != len(corsOrigins)-1 { + originsArray = append(originsArray, "|") + } + } + originsArray = append(originsArray, ")$") + + // originsArray should be converted to a single string, as it is a single directive for if. + origins := strings.Join(originsArray, "") + return ngx_crossplane.Directives{ + buildBlockDirective("if", []string{"$http_origin", "~*", origins}, ngx_crossplane.Directives{ + buildDirective("set", "$cors", "true"), + }), + } +} + +func buildOriginRegex(origin string) string { + origin = regexp.QuoteMeta(origin) + origin = strings.Replace(origin, "\\*", `[A-Za-z0-9\-]+`, 1) + return fmt.Sprintf("(%s)", origin) +} + +func buildNextUpstream(nextUpstream string, retryNonIdempotent bool) []string { + parts := strings.Split(nextUpstream, " ") + + nextUpstreamCodes := make([]string, 0, len(parts)) + for _, v := range parts { + if v != "" && v != nonIdempotent { + nextUpstreamCodes = append(nextUpstreamCodes, v) + } + + if v == nonIdempotent { + retryNonIdempotent = true + } + } + + if retryNonIdempotent { + nextUpstreamCodes = append(nextUpstreamCodes, nonIdempotent) + } + + return nextUpstreamCodes +} + +func buildProxyPass(backends []*ingress.Backend, location *ingress.Location) ngx_crossplane.Directives { + path := location.Path + proto := "http://" + proxyPass := "proxy_pass" + + switch strings.ToUpper(location.BackendProtocol) { + case autoHTTPProtocol: + proto = "$scheme://" + case httpsProtocol: + proto = "https://" + case grpcProtocol: + proto = "grpc://" + proxyPass = "grpc_pass" + case grpcsProtocol: + proto = "grpcs://" + proxyPass = "grpc_pass" + case fcgiProtocol: + proto = "" + proxyPass = "fastcgi_pass" + } + + upstreamName := "upstream_balancer" + + for _, backend := range backends { + if backend.Name == location.Backend { + if backend.SSLPassthrough { + proto = "https://" + + if location.BackendProtocol == grpcsProtocol { + proto = "grpcs://" + } + } + + break + } + } + + if location.Backend == "upstream-default-backend" { + proto = "http://" + proxyPass = "proxy_pass" + } + + // defProxyPass returns the default proxy_pass, just the name of the upstream + defProxyPass := buildDirective(proxyPass, fmt.Sprintf("%s%s", proto, upstreamName)) + + // if the path in the ingress rule is equals to the target: no special rewrite + if path == location.Rewrite.Target { + return ngx_crossplane.Directives{defProxyPass} + } + + if location.Rewrite.Target != "" { + proxySetHeader := "proxy_set_header" + dir := make(ngx_crossplane.Directives, 0) + if location.BackendProtocol == grpcProtocol || location.BackendProtocol == grpcsProtocol { + proxySetHeader = "grpc_set_header" + } + + if location.XForwardedPrefix != "" { + dir = append(dir, + buildDirective(proxySetHeader, "X-Forwarded-Prefix", location.XForwardedPrefix), + ) + } + + dir = append(dir, + buildDirective("rewrite", fmt.Sprintf("(?i)%s", path), location.Rewrite.Target, "break"), + buildDirective(proxyPass, fmt.Sprintf("%s%s", proto, upstreamName)), + ) + return dir + } + + // default proxy_pass + return ngx_crossplane.Directives{defProxyPass} +} + +func buildGeoIPDirectives(reloadTime int, files []string) ngx_crossplane.Directives { + + directives := make(ngx_crossplane.Directives, 0) + buildGeoIPBlock := func(file string, directives ngx_crossplane.Directives) *ngx_crossplane.Directive { + if reloadTime > 0 && file != "GeoIP2-Connection-Type.mmdb" { + directives = append(directives, buildDirective("auto_reload", minutes(reloadTime))) + } + fileName := fmt.Sprintf("/etc/ingress-controller/geoip/%s", file) + return buildBlockDirective("geoip2", []string{fileName}, directives) + } + + for _, file := range files { + if file == "GeoLite2-Country.mmdb" || file == "GeoIP2-Country.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_country_code", "source=$remote_addr", "country", "iso_code"), + buildDirective("$geoip2_country_name", "source=$remote_addr", "country", "names", "en"), + buildDirective("$geoip2_country_geoname_id", "source=$remote_addr", "country", "geoname_id"), + buildDirective("$geoip2_continent_code", "source=$remote_addr", "continent", "code"), + buildDirective("$geoip2_continent_name", "source=$remote_addr", "continent", "names", "en"), + buildDirective("$geoip2_continent_geoname_id", "source=$remote_addr", "continent", "geoname_id"), + })) + } + if file == "GeoLite2-City.mmdb" || file == "GeoIP2-City.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_city_country_code", "source=$remote_addr", "country", "iso_code"), + buildDirective("$geoip2_city_country_name", "source=$remote_addr", "country", "names", "en"), + buildDirective("$geoip2_city_country_geoname_id", "source=$remote_addr", "country", "geoname_id"), + buildDirective("$geoip2_city_continent_code", "source=$remote_addr", "continent", "code"), + buildDirective("$geoip2_city_continent_name", "source=$remote_addr", "continent", "names", "en"), + buildDirective("$geoip2_city", "source=$remote_addr", "city", "names", "en"), + buildDirective("$geoip2_city_geoname_id", "source=$remote_addr", "city", "geoname_id"), + buildDirective("$geoip2_postal_code", "source=$remote_addr", "postal", "code"), + buildDirective("$geoip2_dma_code", "source=$remote_addr", "location", "metro_code"), + buildDirective("$geoip2_latitude", "source=$remote_addr", "location", "latitude"), + buildDirective("$geoip2_longitude", "source=$remote_addr", "location", "longitude"), + buildDirective("$geoip2_time_zone", "source=$remote_addr", "location", "time_zone"), + buildDirective("$geoip2_region_code", "source=$remote_addr", "subdivisions", "0", "iso_code"), + buildDirective("$geoip2_region_name", "source=$remote_addr", "subdivisions", "0", "names", "en"), + buildDirective("$geoip2_region_geoname_id", "source=$remote_addr", "subdivisions", "0", "geoname_id"), + buildDirective("$geoip2_subregion_code", "source=$remote_addr", "subdivisions", "1", "iso_code"), + buildDirective("$geoip2_subregion_name", "source=$remote_addr", "subdivisions", "1", "names", "en"), + buildDirective("$geoip2_subregion_geoname_id", "source=$remote_addr", "subdivisions", "1", "geoname_id"), + })) + } + if file == "GeoLite2-ASN.mmdb" || file == "GeoIP2-ASN.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_asn", "source=$remote_addr", "autonomous_system_number"), + buildDirective("$geoip2_org", "source=$remote_addr", "autonomous_system_organization"), + })) + } + if file == "GeoIP2-ISP.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_isp", "source=$remote_addr", "isp"), + buildDirective("$geoip2_isp_org", "source=$remote_addr", "organization"), + buildDirective("$geoip2_asn", "source=$remote_addr", "autonomous_system_number"), + })) + } + if file == "GeoIP2-Anonymous-IP.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_is_anon", "source=$remote_addr", "is_anonymous"), + buildDirective("$geoip2_is_anonymous", "source=$remote_addr", "default=0", "is_anonymous"), + buildDirective("$geoip2_is_anonymous_vpn", "source=$remote_addr", "default=0", "is_anonymous_vpn"), + buildDirective("$geoip2_is_hosting_provider", "source=$remote_addr", "default=0", "is_hosting_provider"), + buildDirective("$geoip2_is_public_proxy", "source=$remote_addr", "default=0", "is_public_proxy"), + buildDirective("$geoip2_is_tor_exit_node", "source=$remote_addr", "default=0", "is_tor_exit_node"), + })) + } + if file == "GeoIP2-Connection-Type.mmdb" { + directives = append(directives, buildGeoIPBlock(file, ngx_crossplane.Directives{ + buildDirective("$geoip2_connection_type", "connection_type"), + })) + } + } + return directives +} + +func filterRateLimits(servers []*ingress.Server) []ratelimit.Config { + ratelimits := []ratelimit.Config{} + found := sets.Set[string]{} + + for _, server := range servers { + for _, loc := range server.Locations { + if loc.RateLimit.ID != "" && !found.Has(loc.RateLimit.ID) { + found.Insert(loc.RateLimit.ID) + ratelimits = append(ratelimits, loc.RateLimit) + } + } + } + return ratelimits +} + +// buildRateLimitZones produces an array of limit_conn_zone in order to allow +// rate limiting of request. Each Ingress rule could have up to three zones, one +// for connection limit by IP address, one for limiting requests per minute, and +// one for limiting requests per second. +func buildRateLimitZones(servers []*ingress.Server) ngx_crossplane.Directives { + zones := make(map[string]bool) + directives := make(ngx_crossplane.Directives, 0) + for _, server := range servers { + for _, loc := range server.Locations { + zoneID := fmt.Sprintf("$limit_%s", loc.RateLimit.ID) + if loc.RateLimit.Connections.Limit > 0 { + zoneArg := fmt.Sprintf("zone=%s:%dm", loc.RateLimit.Connections.Name, loc.RateLimit.Connections.SharedSize) + zone := fmt.Sprintf("limit_conn_zone %s %s", zoneID, zoneArg) + if _, ok := zones[zone]; !ok { + zones[zone] = true + directives = append(directives, buildDirective("limit_conn_zone", zoneID, zoneArg)) + } + } + + if loc.RateLimit.RPM.Limit > 0 { + zoneArg := fmt.Sprintf("zone=%s:%dm", loc.RateLimit.RPM.Name, loc.RateLimit.RPM.SharedSize) + zoneRate := fmt.Sprintf("rate=%dr/m", loc.RateLimit.RPM.Limit) + zone := fmt.Sprintf("limit_req_zone %s %s %s", zoneID, zoneArg, zoneRate) + if _, ok := zones[zone]; !ok { + zones[zone] = true + directives = append(directives, buildDirective("limit_req_zone", zoneID, zoneArg, zoneRate)) + } + } + + if loc.RateLimit.RPS.Limit > 0 { + zoneArg := fmt.Sprintf("zone=%s:%dm", loc.RateLimit.RPS.Name, loc.RateLimit.RPS.SharedSize) + zoneRate := fmt.Sprintf("rate=%dr/s", loc.RateLimit.RPS.Limit) + zone := fmt.Sprintf("limit_req_zone %s %s %s", zoneID, zoneArg, zoneRate) + if _, ok := zones[zone]; !ok { + zones[zone] = true + directives = append(directives, buildDirective("limit_req_zone", zoneID, zoneArg, zoneRate)) + } + } + } + } + return directives +} + +// buildAuthResponseHeaders sets HTTP response headers when `auth-url` is used. +// Based on `auth-keepalive` value we use auth_request_set Nginx directives, or +// we use Lua and Nginx variables instead. +// +// NOTE: Unfortunately auth_request module ignores the keepalive directive (see: +// https://trac.nginx.org/nginx/ticket/1579), that is why we mimic the same +// functionality with access_by_lua_block. +// TODO: This function is duplicated with the non-crossplane and we should consolidate +func buildAuthResponseHeaders(proxySetHeader string, headers []string, lua bool) ngx_crossplane.Directives { + res := make(ngx_crossplane.Directives, 0) + + if len(headers) == 0 { + return res + } + + for i, h := range headers { + authHeader := fmt.Sprintf("$authHeader%d", i) + if lua { + res = append(res, buildDirective("set", authHeader, "")) + } else { + hvar := strings.ToLower(h) + hvar = strings.NewReplacer("-", "_").Replace(hvar) + res = append(res, buildDirective("auth_request_set", + authHeader, + fmt.Sprintf("$upstream_http_%s", hvar))) + } + res = append(res, buildDirective(proxySetHeader, h, authHeader)) + } + return res +} + +// extractHostPort will extract the host:port part from the URL specified by url +func extractHostPort(newURL string) string { + if newURL == "" { + return "" + } + + authURL, err := parser.StringToURL(newURL) + if err != nil { + klog.Errorf("expected a valid URL but %s was returned", newURL) + return "" + } + + return authURL.Host +} diff --git a/test/e2e-image/e2e.sh b/test/e2e-image/e2e.sh index f8ecd5337d..f793c76819 100755 --- a/test/e2e-image/e2e.sh +++ b/test/e2e-image/e2e.sh @@ -24,7 +24,7 @@ E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS:-""} reportFile="report-e2e-test-suite.xml" ginkgo_args=( - "--fail-fast" + # "--fail-fast" "--flake-attempts=2" "--junit-report=${reportFile}" "--nodes=${E2E_NODES}" diff --git a/test/e2e/admission/admission.go b/test/e2e/admission/admission.go index 873e6719da..870df21b27 100644 --- a/test/e2e/admission/admission.go +++ b/test/e2e/admission/admission.go @@ -100,6 +100,9 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller", }) ginkgo.It("should return an error if there is an error validating the ingress definition", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support snippets") + } disableSnippet := f.AllowSnippetConfiguration() defer disableSnippet() @@ -208,6 +211,9 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller", }) ginkgo.It("should return an error if the Ingress V1 definition contains invalid annotations", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crissplane does not support snippets") + } disableSnippet := f.AllowSnippetConfiguration() defer disableSnippet() @@ -222,6 +228,9 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller", }) ginkgo.It("should not return an error for an invalid Ingress when it has unknown class", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support snippets") + } disableSnippet := f.AllowSnippetConfiguration() defer disableSnippet() out, err := createIngress(f.Namespace, invalidV1IngressWithOtherClass) diff --git a/test/e2e/annotations/affinity.go b/test/e2e/annotations/affinity.go index b64581ef62..d2adc86a5f 100644 --- a/test/e2e/annotations/affinity.go +++ b/test/e2e/annotations/affinity.go @@ -58,7 +58,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -80,7 +80,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -115,7 +115,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -181,7 +181,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -212,7 +212,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) local, err := time.LoadLocation("GMT") @@ -243,7 +243,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -265,7 +265,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -289,7 +289,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -312,7 +312,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -393,7 +393,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { // server alias sort by sort.Strings(), see: internal/ingress/annotations/alias/main.go:60 - return strings.Contains(server, fmt.Sprintf("server_name %s %s %s ;", host, alias1, alias2)) + return strings.Contains(server, fmt.Sprintf("server_name %s %s %s ;", host, alias1, alias2)) || + strings.Contains(server, fmt.Sprintf("server_name %s %s %s;", host, alias1, alias2)) }) f.HTTPTestClient(). @@ -430,7 +431,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -453,7 +454,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.HTTPTestClient(). @@ -475,7 +476,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) && + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && strings.Contains(server, "listen 443") }) diff --git a/test/e2e/annotations/affinitymode.go b/test/e2e/annotations/affinitymode.go index e6253b6ffa..a49a767219 100644 --- a/test/e2e/annotations/affinitymode.go +++ b/test/e2e/annotations/affinitymode.go @@ -56,7 +56,7 @@ var _ = framework.DescribeAnnotation("affinitymode", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) // Check configuration @@ -89,7 +89,7 @@ var _ = framework.DescribeAnnotation("affinitymode", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) // Check configuration diff --git a/test/e2e/annotations/auth.go b/test/e2e/annotations/auth.go index ddda1dce5f..fd1734f354 100644 --- a/test/e2e/annotations/auth.go +++ b/test/e2e/annotations/auth.go @@ -270,6 +270,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() { }) ginkgo.It(`should set snippet "proxy_set_header My-Custom-Header 42;" when external auth is configured`, func() { + if framework.IsCrossplane() { + ginkgo.Skip("crossplane does not support snippets") + } host := authHost annotations := map[string]string{ @@ -290,6 +293,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() { }) ginkgo.It(`should not set snippet "proxy_set_header My-Custom-Header 42;" when external auth is not configured`, func() { + if framework.IsCrossplane() { + ginkgo.Skip("crossplane does not support snippets") + } host := authHost disableSnippet := f.AllowSnippetConfiguration() defer disableSnippet() @@ -325,7 +331,8 @@ var _ = framework.DescribeAnnotation("auth-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `proxy_set_header 'My-Custom-Header' '42';`) + return strings.Contains(server, `proxy_set_header 'My-Custom-Header' '42';`) || + strings.Contains(server, `proxy_set_header My-Custom-Header 42;`) }) }) @@ -531,7 +538,8 @@ http { f.UpdateIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("proxy_set_header '%s' $authHeader0;", rewriteHeader)) + return strings.Contains(server, fmt.Sprintf("proxy_set_header '%s' $authHeader0;", rewriteHeader)) || + strings.Contains(server, fmt.Sprintf("proxy_set_header %s $authHeader0;", rewriteHeader)) }) f.HTTPTestClient(). @@ -893,6 +901,9 @@ http { }) ginkgo.It("should add error to the config", func() { + if framework.IsCrossplane() { + ginkgo.Skip("crossplane does not allows injecting invalid configuration") + } f.WaitForNginxServer(host, func(server string) bool { return strings.Contains(server, "could not parse auth-url annotation: invalid url host") }) diff --git a/test/e2e/annotations/canary.go b/test/e2e/annotations/canary.go index ea733dbf43..443a3a486e 100644 --- a/test/e2e/annotations/canary.go +++ b/test/e2e/annotations/canary.go @@ -1091,13 +1091,22 @@ var _ = framework.DescribeAnnotation("canary-*", func() { f.WaitForNginxServer("_", func(server string) bool { - upstreamName := fmt.Sprintf(`set $proxy_upstream_name "%s-%s-%s";`, f.Namespace, framework.HTTPBunService, "80") - canaryUpstreamName := fmt.Sprintf(`set $proxy_upstream_name "%s-%s-%s";`, f.Namespace, canaryService, "80") + upstreamName := fmt.Sprintf(`set $proxy_upstream_name "%s-%s-80";`, f.Namespace, framework.HTTPBunService) + upstreamNameCrossplane := fmt.Sprintf(`set $proxy_upstream_name %s-%s-80;`, f.Namespace, framework.HTTPBunService) - return strings.Contains(server, fmt.Sprintf(`set $ingress_name "%v";`, host)) && + canaryUpstreamName := fmt.Sprintf(`set $proxy_upstream_name "%s-%s-80";`, f.Namespace, canaryService) + canaryUpstreamNameCrossplane := fmt.Sprintf(`set $proxy_upstream_name %s-%s-80;`, f.Namespace, canaryService) + + return (strings.Contains(server, fmt.Sprintf(`set $ingress_name "%v";`, host)) && !strings.Contains(server, `set $proxy_upstream_name "upstream-default-backend";`) && !strings.Contains(server, canaryUpstreamName) && - strings.Contains(server, upstreamName) + strings.Contains(server, upstreamName)) || + // Crossplane assertion + (strings.Contains(server, fmt.Sprintf(`set $ingress_name %s;`, host)) && + !strings.Contains(server, `set $proxy_upstream_name "pstream-default-backend;`) && + !strings.Contains(server, canaryUpstreamNameCrossplane) && + strings.Contains(server, upstreamNameCrossplane)) + }) }) diff --git a/test/e2e/annotations/cors.go b/test/e2e/annotations/cors.go index 58f4445f70..1db7d53741 100644 --- a/test/e2e/annotations/cors.go +++ b/test/e2e/annotations/cors.go @@ -48,13 +48,21 @@ var _ = framework.DescribeAnnotation("cors-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS';") && + return (strings.Contains(server, "more_set_headers 'Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS';") && strings.Contains(server, "more_set_headers 'Access-Control-Allow-Origin: $http_origin';") && strings.Contains(server, "more_set_headers 'Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';") && strings.Contains(server, "more_set_headers 'Access-Control-Max-Age: 1728000';") && strings.Contains(server, "more_set_headers 'Access-Control-Allow-Credentials: true';") && strings.Contains(server, "set $http_origin *;") && - strings.Contains(server, "$cors 'true';") + strings.Contains(server, "$cors 'true';")) || + // Assertions for crossplane mode + (strings.Contains(server, `more_set_headers "Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS";`) && + strings.Contains(server, `more_set_headers "Access-Control-Allow-Origin: $http_origin";`) && + strings.Contains(server, `more_set_headers "Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization";`) && + strings.Contains(server, `more_set_headers "Access-Control-Max-Age: 1728000";`) && + strings.Contains(server, `more_set_headers "Access-Control-Allow-Credentials: true";`) && + strings.Contains(server, "set $http_origin *;") && + strings.Contains(server, "$cors true;")) }) f.HTTPTestClient(). @@ -76,7 +84,9 @@ var _ = framework.DescribeAnnotation("cors-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Methods: POST, GET';") + return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Methods: POST, GET';") || + strings.Contains(server, `more_set_headers "Access-Control-Allow-Methods: POST, GET";`) + }) }) @@ -92,7 +102,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "more_set_headers 'Access-Control-Max-Age: 200';") + return strings.Contains(server, "more_set_headers 'Access-Control-Max-Age: 200';") || + strings.Contains(server, `more_set_headers "Access-Control-Max-Age: 200";`) }) }) @@ -151,7 +162,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Headers: DNT, User-Agent';") + return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Headers: DNT, User-Agent';") || + strings.Contains(server, `more_set_headers "Access-Control-Allow-Headers: DNT, User-Agent";`) }) }) @@ -167,7 +179,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "more_set_headers 'Access-Control-Expose-Headers: X-CustomResponseHeader, X-CustomSecondHeader';") + return strings.Contains(server, "more_set_headers 'Access-Control-Expose-Headers: X-CustomResponseHeader, X-CustomSecondHeader';") || + strings.Contains(server, `more_set_headers "Access-Control-Expose-Headers: X-CustomResponseHeader, X-CustomSecondHeader";`) }) }) diff --git a/test/e2e/annotations/fastcgi.go b/test/e2e/annotations/fastcgi.go index bcf1c3487b..b4684faefc 100644 --- a/test/e2e/annotations/fastcgi.go +++ b/test/e2e/annotations/fastcgi.go @@ -64,7 +64,8 @@ var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "fastcgi_index \"index.php\";") + return strings.Contains(server, "fastcgi_index \"index.php\";") || + strings.Contains(server, "fastcgi_index index.php;") }) }) @@ -94,8 +95,10 @@ var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, "fastcgi_param SCRIPT_FILENAME \"$fastcgi_script_name\";") && - strings.Contains(server, "fastcgi_param REDIRECT_STATUS \"200\";") + return (strings.Contains(server, "fastcgi_param SCRIPT_FILENAME \"$fastcgi_script_name\";") && + strings.Contains(server, "fastcgi_param REDIRECT_STATUS \"200\";")) || + (strings.Contains(server, "fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;") && + strings.Contains(server, "fastcgi_param REDIRECT_STATUS 200;")) }) }) diff --git a/test/e2e/annotations/fromtowwwredirect.go b/test/e2e/annotations/fromtowwwredirect.go index a3fb3b9b5d..2f56c23150 100644 --- a/test/e2e/annotations/fromtowwwredirect.go +++ b/test/e2e/annotations/fromtowwwredirect.go @@ -62,17 +62,20 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() { }) ginkgo.It("should redirect from www HTTPS to HTTPS", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() - ginkgo.By("setting up server for redirect from www") + h := make(map[string]string) + h["ExpectedHost"] = "$http_host" + cfgMap := "add-headers-configmap" + + f.CreateConfigMap(cfgMap, h) + f.UpdateNginxConfigMapData("add-headers", fmt.Sprintf("%s/%s", f.Namespace, cfgMap)) + fromHost := fmt.Sprintf("%s.nip.io", f.GetNginxIP()) toHost := fmt.Sprintf("www.%s", fromHost) annotations := map[string]string{ - "nginx.ingress.kubernetes.io/from-to-www-redirect": "true", - "nginx.ingress.kubernetes.io/configuration-snippet": "more_set_headers \"ExpectedHost: $http_host\";", + "nginx.ingress.kubernetes.io/from-to-www-redirect": "true", } ing := framework.NewSingleIngressWithTLS(fromHost, "/", fromHost, []string{fromHost, toHost}, f.Namespace, framework.EchoService, 80, annotations) diff --git a/test/e2e/annotations/http2pushpreload.go b/test/e2e/annotations/http2pushpreload.go index b15d2df179..2c317eef8d 100644 --- a/test/e2e/annotations/http2pushpreload.go +++ b/test/e2e/annotations/http2pushpreload.go @@ -25,6 +25,10 @@ import ( ) var _ = framework.DescribeAnnotation("http2-push-preload", func() { + if framework.IsCrossplane() { + // Http2 Push preload is removed from crossplane as it is deprecated + return + } f := framework.NewDefaultFramework("http2pushpreload") ginkgo.BeforeEach(func() { diff --git a/test/e2e/annotations/limitconnections.go b/test/e2e/annotations/limitconnections.go index 7d00b6df06..d44cb169c3 100644 --- a/test/e2e/annotations/limitconnections.go +++ b/test/e2e/annotations/limitconnections.go @@ -41,7 +41,7 @@ var _ = framework.DescribeAnnotation("Annotation - limit-connections", func() { ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.SlowEchoService, 80, nil) f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) // limit connections diff --git a/test/e2e/annotations/mirror.go b/test/e2e/annotations/mirror.go index 787cbfa3bc..c6cd028c71 100644 --- a/test/e2e/annotations/mirror.go +++ b/test/e2e/annotations/mirror.go @@ -60,7 +60,8 @@ var _ = framework.DescribeAnnotation("mirror-*", func() { func(server string) bool { return strings.Contains(server, fmt.Sprintf("mirror /_mirror-%v;", ing.UID)) && strings.Contains(server, "mirror_request_body on;") && - strings.Contains(server, `proxy_pass "https://test.env.com/$request_uri";`) + (strings.Contains(server, `proxy_pass "https://test.env.com/$request_uri";`) || + strings.Contains(server, `proxy_pass https://test.env.com/$request_uri;`)) }) }) diff --git a/test/e2e/annotations/modsecurity/modsecurity.go b/test/e2e/annotations/modsecurity/modsecurity.go index 730fc76e78..606a50ede2 100644 --- a/test/e2e/annotations/modsecurity/modsecurity.go +++ b/test/e2e/annotations/modsecurity/modsecurity.go @@ -38,6 +38,9 @@ const ( var _ = framework.DescribeAnnotation("modsecurity owasp", func() { f := framework.NewDefaultFramework("modsecuritylocation") + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { f.NewEchoDeployment() diff --git a/test/e2e/annotations/rewrite.go b/test/e2e/annotations/rewrite.go index 173df29f00..416e0190e6 100644 --- a/test/e2e/annotations/rewrite.go +++ b/test/e2e/annotations/rewrite.go @@ -97,8 +97,8 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `location ~* "^/" {`) && - strings.Contains(server, `location ~* "^/.well-known/acme/challenge" {`) + return (strings.Contains(server, `location ~* "^/" {`) || strings.Contains(server, `location ~* ^/ {`)) && + (strings.Contains(server, `location ~* "^/.well-known/acme/challenge" {`) || strings.Contains(server, `location ~* ^/.well-known/acme/challenge {`)) }) ginkgo.By("making a second request to the non-rewritten location") @@ -132,8 +132,8 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `location ~* "^/foo" {`) && - strings.Contains(server, `location ~* "^/foo.+" {`) + return (strings.Contains(server, `location ~* "^/foo" {`) || strings.Contains(server, `location ~* ^/foo {`)) && + (strings.Contains(server, `location ~* "^/foo.+" {`) || strings.Contains(server, `location ~* ^/foo.+ {`)) }) ginkgo.By("ensuring '/foo' matches '~* ^/foo'") @@ -174,7 +174,8 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `location ~* "^/foo/bar/bar" {`) && + return (strings.Contains(server, `location ~* "^/foo/bar/bar" {`) || + strings.Contains(server, `location ~* ^/foo/bar/bar {`)) && strings.Contains(server, `location ~* "^/foo/bar/[a-z]{3}" {`) }) @@ -202,7 +203,7 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `location ~* "^/foo/bar/(.+)" {`) + return strings.Contains(server, `location ~* "^/foo/bar/(.+)" {`) || strings.Contains(server, `location ~* ^/foo/bar/(.+) {`) }) ginkgo.By("check that '/foo/bar/bar' redirects to custom rewrite") diff --git a/test/e2e/annotations/serversnippet.go b/test/e2e/annotations/serversnippet.go index c94960a3da..0a6c091048 100644 --- a/test/e2e/annotations/serversnippet.go +++ b/test/e2e/annotations/serversnippet.go @@ -27,6 +27,9 @@ import ( var _ = framework.DescribeAnnotation("server-snippet", func() { f := framework.NewDefaultFramework("serversnippet") + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { f.NewEchoDeployment() diff --git a/test/e2e/annotations/snippet.go b/test/e2e/annotations/snippet.go index 9e3160dcc4..178db4202d 100644 --- a/test/e2e/annotations/snippet.go +++ b/test/e2e/annotations/snippet.go @@ -30,6 +30,9 @@ var _ = framework.DescribeAnnotation("configuration-snippet", func() { "configurationsnippet", framework.WithHTTPBunEnabled(), ) + if framework.IsCrossplane() { + return + } ginkgo.It("set snippet more_set_headers in all locations", func() { host := "configurationsnippet.foo.com" diff --git a/test/e2e/annotations/streamsnippet.go b/test/e2e/annotations/streamsnippet.go index f91cdc34e3..1a5f7fd5de 100644 --- a/test/e2e/annotations/streamsnippet.go +++ b/test/e2e/annotations/streamsnippet.go @@ -33,6 +33,9 @@ import ( var _ = framework.DescribeSetting("stream-snippet", func() { f := framework.NewDefaultFramework("stream-snippet") + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { f.NewEchoDeployment() diff --git a/test/e2e/annotations/upstreamhashby.go b/test/e2e/annotations/upstreamhashby.go index 1b81066627..e5e3c5846e 100644 --- a/test/e2e/annotations/upstreamhashby.go +++ b/test/e2e/annotations/upstreamhashby.go @@ -36,7 +36,7 @@ func startIngress(f *framework.Framework, annotations map[string]string) map[str f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) //nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated diff --git a/test/e2e/annotations/upstreamvhost.go b/test/e2e/annotations/upstreamvhost.go index e091e7c9fd..fb763ba1d5 100644 --- a/test/e2e/annotations/upstreamvhost.go +++ b/test/e2e/annotations/upstreamvhost.go @@ -42,7 +42,8 @@ var _ = framework.DescribeAnnotation("upstream-vhost", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, `proxy_set_header Host "upstreamvhost.bar.com";`) + return strings.Contains(server, `proxy_set_header Host "upstreamvhost.bar.com";`) || + strings.Contains(server, `proxy_set_header Host upstreamvhost.bar.com;`) }) }) }) diff --git a/test/e2e/annotations/xforwardedprefix.go b/test/e2e/annotations/xforwardedprefix.go index 35f2eb4262..3ca4497570 100644 --- a/test/e2e/annotations/xforwardedprefix.go +++ b/test/e2e/annotations/xforwardedprefix.go @@ -43,7 +43,8 @@ var _ = framework.DescribeAnnotation("x-forwarded-prefix", func() { f.WaitForNginxServer(host, func(server string) bool { return strings.Contains(server, host) && - strings.Contains(server, "proxy_set_header X-Forwarded-Prefix \"/test/value\";") + (strings.Contains(server, "proxy_set_header X-Forwarded-Prefix \"/test/value\";") || + strings.Contains(server, "proxy_set_header X-Forwarded-Prefix /test/value;")) }) f.HTTPTestClient(). diff --git a/test/e2e/defaultbackend/custom_default_backend.go b/test/e2e/defaultbackend/custom_default_backend.go index 1e30b9269f..37b8c8ab26 100644 --- a/test/e2e/defaultbackend/custom_default_backend.go +++ b/test/e2e/defaultbackend/custom_default_backend.go @@ -47,7 +47,8 @@ var _ = framework.IngressNginxDescribe("[Default Backend] custom service", func( f.WaitForNginxServer("_", func(server string) bool { - return strings.Contains(server, `set $proxy_upstream_name "upstream-default-backend"`) + return strings.Contains(server, `set $proxy_upstream_name "upstream-default-backend"`) || + strings.Contains(server, `set $proxy_upstream_name upstream-default-backend`) }) f.HTTPTestClient(). diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 204da7df05..02cc088164 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -20,6 +20,7 @@ import ( "fmt" "net" "net/http" + "os" "strings" "time" @@ -119,6 +120,11 @@ func NewSimpleFramework(baseName string, opts ...func(*Framework)) *Framework { return f } +func IsCrossplane() bool { + isCrossplane, ok := os.LookupEnv("IS_CROSSPLANE") + return ok && isCrossplane == "true" +} + func (f *Framework) CreateEnvironment() { var err error @@ -315,7 +321,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b if name == "" { cmd = "cat /etc/nginx/nginx.conf" } else { - cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf | awk '/## start server %v/,/## end server %v/'", name, name) + cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf | awk '/## start server %s;/,/## end server %s;/'", name, name) } o, err := f.ExecCommand(f.pod, cmd) diff --git a/test/e2e/ingress/multiple_rules.go b/test/e2e/ingress/multiple_rules.go index 9247dc1d3f..22ca08a96f 100644 --- a/test/e2e/ingress/multiple_rules.go +++ b/test/e2e/ingress/multiple_rules.go @@ -17,11 +17,11 @@ limitations under the License. package ingress import ( + "fmt" "net/http" "strings" "github.com/onsi/ginkgo/v2" - "github.com/stretchr/testify/assert" networking "k8s.io/api/networking/v1" "k8s.io/ingress-nginx/test/e2e/framework" @@ -36,14 +36,19 @@ var _ = framework.IngressNginxDescribe("single ingress - multiple hosts", func() }) ginkgo.It("should set the correct $service_name NGINX variable", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() + customHeader := "Service-Name" + customHeaderValue := "$service_name" - annotations := map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "service-name: $service_name";`, - } + h := make(map[string]string) + h[customHeader] = customHeaderValue - ing := framework.NewSingleIngress("simh", "/", "first.host", f.Namespace, "first-service", 80, annotations) + cfgMap := "custom-headers" + + f.CreateConfigMap(cfgMap, h) + + f.UpdateNginxConfigMapData("add-headers", fmt.Sprintf("%v/%v", f.Namespace, cfgMap)) + + ing := framework.NewSingleIngress("simh", "/", "first.host", f.Namespace, "first-service", 80, nil) ing.Spec.Rules = append(ing.Spec.Rules, networking.IngressRule{ Host: "second.host", @@ -79,26 +84,19 @@ var _ = framework.IngressNginxDescribe("single ingress - multiple hosts", func() return strings.Contains(server, "second.host") }) - body := f.HTTPTestClient(). + f.HTTPTestClient(). GET("/exact"). WithHeader("Host", "first.host"). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.Contains(ginkgo.GinkgoT(), body, "service-name=first-service") - assert.NotContains(ginkgo.GinkgoT(), body, "service-name=second-service") + Headers().ValueEqual("Service-Name", []string{"first-service"}) - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/exact"). WithHeader("Host", "second.host"). Expect(). Status(http.StatusOK). - Body(). - Raw() + Headers().ValueEqual("Service-Name", []string{"second-service"}) - assert.NotContains(ginkgo.GinkgoT(), body, "service-name=first-service") - assert.Contains(ginkgo.GinkgoT(), body, "service-name=second-service") }) }) diff --git a/test/e2e/ingress/pathtype_exact.go b/test/e2e/ingress/pathtype_exact.go index 2660e32a45..060ea9a318 100644 --- a/test/e2e/ingress/pathtype_exact.go +++ b/test/e2e/ingress/pathtype_exact.go @@ -21,7 +21,6 @@ import ( "strings" "github.com/onsi/ginkgo/v2" - "github.com/stretchr/testify/assert" networking "k8s.io/api/networking/v1" "k8s.io/ingress-nginx/test/e2e/framework" @@ -35,24 +34,31 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() { }) ginkgo.It("should choose exact location for /exact", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() - host := "exact.path" + f.UpdateNginxConfigMapData("global-allowed-response-headers", "Pathtype,duplicated") annotations := map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-exact", } + f.CreateConfigMap("custom-headers-exact", map[string]string{ + "Pathtype": "exact", + }) + + host := "exact.path" exactPathType := networking.PathTypeExact ing := framework.NewSingleIngress("exact", "/exact", host, f.Namespace, framework.EchoService, 80, annotations) ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType f.EnsureIngress(ing) annotations = map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-prefix", } + f.CreateConfigMap("custom-headers-prefix", map[string]string{ + "Pathtype": "prefix", + }) + ing = framework.NewSingleIngress("exact-suffix", "/exact", host, f.Namespace, framework.EchoService, 80, annotations) f.EnsureIngress(ing) @@ -63,34 +69,29 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() { strings.Contains(server, "location /exact/") }) - body := f.HTTPTestClient(). + f.HTTPTestClient(). GET("/exact"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() + Headers().ValueEqual("Pathtype", []string{"exact"}) - assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact") - - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/exact/suffix"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix") + Headers().ValueEqual("Pathtype", []string{"prefix"}) annotations = map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": ` - more_set_input_headers "pathType: prefix"; - more_set_input_headers "duplicated: true"; - `, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-duplicated", } + f.CreateConfigMap("custom-headers-duplicated", map[string]string{ + "Pathtype": "prefix", + "duplicated": "true", + }) + ing = framework.NewSingleIngress("duplicated-prefix", "/exact", host, f.Namespace, framework.EchoService, 80, annotations) f.EnsureIngress(ing) @@ -101,16 +102,12 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() { strings.Contains(server, "location /exact/") }) - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/exact/suffix"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() + Headers().ValueEqual("Pathtype", []string{"prefix"}).NotContainsKey("duplicated") - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=exact") - assert.NotContains(ginkgo.GinkgoT(), body, "duplicated=true") }) }) diff --git a/test/e2e/ingress/pathtype_mixed.go b/test/e2e/ingress/pathtype_mixed.go index 3212089c90..0573cc0f58 100644 --- a/test/e2e/ingress/pathtype_mixed.go +++ b/test/e2e/ingress/pathtype_mixed.go @@ -21,7 +21,6 @@ import ( "strings" "github.com/onsi/ginkgo/v2" - "github.com/stretchr/testify/assert" networking "k8s.io/api/networking/v1" "k8s.io/ingress-nginx/test/e2e/framework" @@ -37,21 +36,32 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefi exactPathType := networking.PathTypeExact ginkgo.It("should choose the correct location", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() - host := "mixed.path" + f.UpdateNginxConfigMapData("global-allowed-response-headers", "Pathtype,Pathheader") + annotations := map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";more_set_input_headers "pathheader: /";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-exact", } + + f.CreateConfigMap("custom-headers-exact", map[string]string{ + "Pathtype": "exact", + "Pathheader": "/", + }) + ing := framework.NewSingleIngress("exact-root", "/", host, f.Namespace, framework.EchoService, 80, annotations) ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType f.EnsureIngress(ing) annotations = map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";more_set_input_headers "pathheader: /";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-prefix", } + + f.CreateConfigMap("custom-headers-prefix", map[string]string{ + "Pathtype": "prefix", + "Pathheader": "/", + }) + ing = framework.NewSingleIngress("prefix-root", "/", host, f.Namespace, framework.EchoService, 80, annotations) f.EnsureIngress(ing) @@ -63,41 +73,42 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefi }) ginkgo.By("Checking exact request to /") - body := f.HTTPTestClient(). + f.HTTPTestClient(). GET("/"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact") - assert.Contains(ginkgo.GinkgoT(), body, "pathheader=/") + Headers().ValueEqual("Pathtype", []string{"exact"}).ValueEqual("Pathheader", []string{"/"}) ginkgo.By("Checking prefix request to /bar") - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/bar"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=exact") - assert.Contains(ginkgo.GinkgoT(), body, "pathheader=/") + Headers().ValueEqual("Pathtype", []string{"prefix"}).ValueEqual("Pathheader", []string{"/"}) annotations = map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";more_set_input_headers "pathheader: /foo";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-ex-foo", } + + f.CreateConfigMap("custom-headers-ex-foo", map[string]string{ + "Pathtype": "exact", + "Pathheader": "/foo", + }) ing = framework.NewSingleIngress("exact-foo", "/foo", host, f.Namespace, framework.EchoService, 80, annotations) ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType f.EnsureIngress(ing) annotations = map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";more_set_input_headers "pathheader: /foo";`, + "nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers-pr-foo", } + + f.CreateConfigMap("custom-headers-pr-foo", map[string]string{ + "Pathtype": "prefix", + "Pathheader": "/foo", + }) + ing = framework.NewSingleIngress("prefix-foo", "/foo", host, f.Namespace, framework.EchoService, 80, annotations) f.EnsureIngress(ing) @@ -109,40 +120,28 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefi }) ginkgo.By("Checking exact request to /foo") - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/foo"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact") - assert.Contains(ginkgo.GinkgoT(), body, "pathheader=/foo") + Headers().ValueEqual("Pathtype", []string{"exact"}).ValueEqual("Pathheader", []string{"/foo"}) ginkgo.By("Checking prefix request to /foo/bar") - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/foo/bar"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() - - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.Contains(ginkgo.GinkgoT(), body, "pathheader=/foo") + Headers().ValueEqual("Pathtype", []string{"prefix"}).ValueEqual("Pathheader", []string{"/foo"}) ginkgo.By("Checking prefix request to /foobar") - body = f.HTTPTestClient(). + f.HTTPTestClient(). GET("/foobar"). WithHeader("Host", host). Expect(). Status(http.StatusOK). - Body(). - Raw() + Headers().ValueEqual("Pathtype", []string{"prefix"}).ValueEqual("Pathheader", []string{"/"}) - assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix") - assert.Contains(ginkgo.GinkgoT(), body, "pathheader=/") }) }) diff --git a/test/e2e/ingress/without_host.go b/test/e2e/ingress/without_host.go index 38f89beda1..24192a0b7d 100644 --- a/test/e2e/ingress/without_host.go +++ b/test/e2e/ingress/without_host.go @@ -39,11 +39,17 @@ var _ = framework.IngressNginxDescribe("[Ingress] definition without host", func f.WaitForNginxServer("_", func(server string) bool { - return strings.Contains(server, fmt.Sprintf(`set $namespace "%v";`, f.Namespace)) && + return (strings.Contains(server, fmt.Sprintf(`set $namespace "%v";`, f.Namespace)) && strings.Contains(server, fmt.Sprintf(`set $ingress_name "%v";`, ing.Name)) && strings.Contains(server, fmt.Sprintf(`set $service_name "%v";`, framework.EchoService)) && strings.Contains(server, `set $service_port "80";`) && - strings.Contains(server, `set $location_path "/";`) + strings.Contains(server, `set $location_path "/";`)) || + // Crossplane assertions + (strings.Contains(server, fmt.Sprintf(`set $namespace %s;`, f.Namespace)) && + strings.Contains(server, fmt.Sprintf(`set $ingress_name %s;`, ing.Name)) && + strings.Contains(server, fmt.Sprintf(`set $service_name %s;`, framework.EchoService)) && + strings.Contains(server, `set $service_port 80;`) && + strings.Contains(server, `set $location_path /;`)) }) f.HTTPTestClient(). @@ -81,11 +87,17 @@ var _ = framework.IngressNginxDescribe("[Ingress] definition without host", func f.WaitForNginxServer("only-backend", func(server string) bool { - return strings.Contains(server, fmt.Sprintf(`set $namespace "%v";`, f.Namespace)) && + return (strings.Contains(server, fmt.Sprintf(`set $namespace "%v";`, f.Namespace)) && strings.Contains(server, fmt.Sprintf(`set $ingress_name "%v";`, ing.Name)) && strings.Contains(server, fmt.Sprintf(`set $service_name "%v";`, framework.EchoService)) && strings.Contains(server, `set $service_port "80";`) && - strings.Contains(server, `set $location_path "/";`) + strings.Contains(server, `set $location_path "/";`)) || + // Crossplane assertions + (strings.Contains(server, fmt.Sprintf(`set $namespace %s;`, f.Namespace)) && + strings.Contains(server, fmt.Sprintf(`set $ingress_name %s;`, ing.Name)) && + strings.Contains(server, fmt.Sprintf(`set $service_name %s;`, framework.EchoService)) && + strings.Contains(server, `set $service_port 80;`) && + strings.Contains(server, `set $location_path /;`)) }) f.HTTPTestClient(). diff --git a/test/e2e/lua/dynamic_configuration.go b/test/e2e/lua/dynamic_configuration.go index a5e2196cef..8f1deaeb12 100644 --- a/test/e2e/lua/dynamic_configuration.go +++ b/test/e2e/lua/dynamic_configuration.go @@ -212,7 +212,7 @@ func createIngress(f *framework.Framework, host, deploymentName string) { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) && + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && strings.Contains(server, "proxy_pass http://upstream_balancer;") }) } diff --git a/test/e2e/metrics/metrics.go b/test/e2e/metrics/metrics.go index bec09bb37c..3cdb88057e 100644 --- a/test/e2e/metrics/metrics.go +++ b/test/e2e/metrics/metrics.go @@ -43,7 +43,7 @@ var _ = framework.IngressNginxDescribe("[metrics] exported prometheus metrics", f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) && + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && strings.Contains(server, "proxy_pass http://upstream_balancer;") }) }) diff --git a/test/e2e/run-e2e-suite.sh b/test/e2e/run-e2e-suite.sh index 909368e96b..621313610a 100755 --- a/test/e2e/run-e2e-suite.sh +++ b/test/e2e/run-e2e-suite.sh @@ -78,6 +78,7 @@ kubectl run --rm \ --env="E2E_NODES=${E2E_NODES}" \ --env="FOCUS=${FOCUS}" \ --env="IS_CHROOT=${IS_CHROOT:-false}"\ + --env="IS_CROSSPLANE=${IS_CROSSPLANE:-false}"\ --env="SKIP_OPENTELEMETRY_TESTS=${SKIP_OPENTELEMETRY_TESTS:-false}"\ --env="E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS}" \ --env="NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE}" \ diff --git a/test/e2e/run-kind-e2e.sh b/test/e2e/run-kind-e2e.sh index fed9ff256a..cf0925a076 100755 --- a/test/e2e/run-kind-e2e.sh +++ b/test/e2e/run-kind-e2e.sh @@ -39,6 +39,8 @@ fi KIND_LOG_LEVEL="1" IS_CHROOT="${IS_CHROOT:-false}" +IS_CROSSPLANE="${IS_CROSSPLANE:-false}" + export KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-ingress-nginx-dev} DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Use 1.0.0-dev to make sure we use the latest configuration in the helm template diff --git a/test/e2e/security/request_smuggling.go b/test/e2e/security/request_smuggling.go index 5ede02d4b5..d96ba4b4c0 100644 --- a/test/e2e/security/request_smuggling.go +++ b/test/e2e/security/request_smuggling.go @@ -37,6 +37,9 @@ var _ = framework.IngressNginxDescribe("[Security] request smuggling", func() { }) ginkgo.It("should not return body content from error_page", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support snippets") // TODO: Re-add this test when we enable admin defined snippets + } host := "foo.bar.com" snippet := ` diff --git a/test/e2e/settings/access_log.go b/test/e2e/settings/access_log.go index 65b9dfda4a..33466f29f5 100644 --- a/test/e2e/settings/access_log.go +++ b/test/e2e/settings/access_log.go @@ -31,6 +31,10 @@ var _ = framework.DescribeSetting("access-log", func() { ginkgo.It("use the default configuration", func() { f.WaitForNginxConfiguration( func(cfg string) bool { + if framework.IsCrossplane() { + return strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo") || + strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 upstreaminfo") + } return (strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo") && strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream")) || (strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 upstreaminfo") && @@ -42,6 +46,9 @@ var _ = framework.DescribeSetting("access-log", func() { f.UpdateNginxConfigMapData("access-log-path", "/tmp/nginx/access.log") f.WaitForNginxConfiguration( func(cfg string) bool { + if framework.IsCrossplane() { + return strings.Contains(cfg, "access_log /tmp/nginx/access.log upstreaminfo") + } return strings.Contains(cfg, "access_log /tmp/nginx/access.log upstreaminfo") && strings.Contains(cfg, "access_log /tmp/nginx/access.log log_stream") }) @@ -53,6 +60,9 @@ var _ = framework.DescribeSetting("access-log", func() { f.UpdateNginxConfigMapData("http-access-log-path", "/tmp/nginx/http-access.log") f.WaitForNginxConfiguration( func(cfg string) bool { + if framework.IsCrossplane() { + return strings.Contains(cfg, "access_log /tmp/nginx/http-access.log upstreaminfo") + } return strings.Contains(cfg, "access_log /tmp/nginx/http-access.log upstreaminfo") && (strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream") || strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 log_stream")) @@ -62,6 +72,9 @@ var _ = framework.DescribeSetting("access-log", func() { ginkgo.Context("stream-access-log-path", func() { ginkgo.It("use the specified configuration", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support stream") + } f.UpdateNginxConfigMapData("stream-access-log-path", "/tmp/nginx/stream-access.log") f.WaitForNginxConfiguration( func(cfg string) bool { @@ -74,6 +87,9 @@ var _ = framework.DescribeSetting("access-log", func() { ginkgo.Context("http-access-log-path & stream-access-log-path", func() { ginkgo.It("use the specified configuration", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support stream") + } f.SetNginxConfigMapData(map[string]string{ "http-access-log-path": "/tmp/nginx/http-access.log", "stream-access-log-path": "/tmp/nginx/stream-access.log", diff --git a/test/e2e/settings/badannotationvalues.go b/test/e2e/settings/badannotationvalues.go index aa9906909c..bee12e66a2 100644 --- a/test/e2e/settings/badannotationvalues.go +++ b/test/e2e/settings/badannotationvalues.go @@ -50,7 +50,7 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.WaitForNginxServer(host, @@ -87,7 +87,7 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.WaitForNginxServer(host, @@ -103,6 +103,9 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { }) ginkgo.It("[BAD_ANNOTATIONS] should allow an ingress if there is a default blocklist config in place", func() { + if framework.IsCrossplane() { + ginkgo.Skip("Crossplane does not support snippets") + } disableSnippet := f.AllowSnippetConfiguration() defer disableSnippet() @@ -120,7 +123,7 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(hostValid, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", hostValid)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", hostValid)) }) f.WaitForNginxServer(hostValid, @@ -153,7 +156,7 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) f.WaitForNginxServer(host, diff --git a/test/e2e/settings/configmap_change.go b/test/e2e/settings/configmap_change.go index 3e37b62cd6..3b18780519 100644 --- a/test/e2e/settings/configmap_change.go +++ b/test/e2e/settings/configmap_change.go @@ -17,7 +17,6 @@ limitations under the License. package settings import ( - "regexp" "strings" "github.com/onsi/ginkgo/v2" @@ -43,36 +42,20 @@ var _ = framework.DescribeSetting("Configmap change", func() { f.UpdateNginxConfigMapData("whitelist-source-range", "1.1.1.1") - checksumRegex := regexp.MustCompile(`Configuration checksum:\s+(\d+)`) - checksum := "" - f.WaitForNginxConfiguration( func(cfg string) bool { - // before returning, extract the current checksum - match := checksumRegex.FindStringSubmatch(cfg) - if len(match) > 0 { - checksum = match[1] - } - return strings.Contains(cfg, "allow 1.1.1.1;") }) - assert.NotEmpty(ginkgo.GinkgoT(), checksum) ginkgo.By("changing error-log-level") f.UpdateNginxConfigMapData("error-log-level", "debug") - newChecksum := "" f.WaitForNginxConfiguration( func(cfg string) bool { - match := checksumRegex.FindStringSubmatch(cfg) - if len(match) > 0 { - newChecksum = match[1] - } - - return strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;") + return strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;") || + strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;") }) - assert.NotEqual(ginkgo.GinkgoT(), checksum, newChecksum) logs, err := f.NginxLogs() assert.Nil(ginkgo.GinkgoT(), err, "obtaining nginx logs") diff --git a/test/e2e/settings/custom_header.go b/test/e2e/settings/custom_header.go index 8341f7ef02..b2c8aac8d6 100644 --- a/test/e2e/settings/custom_header.go +++ b/test/e2e/settings/custom_header.go @@ -79,8 +79,10 @@ var _ = framework.DescribeSetting("add-headers", func() { f.UpdateNginxConfigMapData("add-headers", fmt.Sprintf("%v/%v", f.Namespace, cfgMap)) f.WaitForNginxConfiguration(func(server string) bool { - return strings.Contains(server, fmt.Sprintf("more_set_headers \"%s: %s\";", firstCustomHeader, firstCustomHeaderValue)) && - strings.Contains(server, fmt.Sprintf("more_set_headers \"%s: %s\";", secondCustomHeader, secondCustomHeaderValue)) + return (strings.Contains(server, fmt.Sprintf(`more_set_headers "%s: %s";`, firstCustomHeader, firstCustomHeaderValue)) && + strings.Contains(server, fmt.Sprintf(`more_set_headers "%s: %s";`, secondCustomHeader, secondCustomHeaderValue))) || + (strings.Contains(server, fmt.Sprintf("more_set_headers %s: %s;", firstCustomHeader, firstCustomHeaderValue)) && + strings.Contains(server, fmt.Sprintf("more_set_headers %s: %s;", secondCustomHeader, secondCustomHeaderValue))) }) resp := f.HTTPTestClient(). diff --git a/test/e2e/settings/default_ssl_certificate.go b/test/e2e/settings/default_ssl_certificate.go index c48a1e87f7..e8e2195199 100644 --- a/test/e2e/settings/default_ssl_certificate.go +++ b/test/e2e/settings/default_ssl_certificate.go @@ -69,8 +69,10 @@ var _ = framework.IngressNginxDescribe("[SSL] [Flag] default-ssl-certificate", f ginkgo.By("making sure new ingress is deployed") expectedConfig := fmt.Sprintf(`set $proxy_upstream_name "%v-%v-%v";`, f.Namespace, service, port) + expectedConfigCrossPlane := fmt.Sprintf(`set $proxy_upstream_name %v-%v-%v;`, f.Namespace, service, port) + f.WaitForNginxServer("_", func(cfg string) bool { - return strings.Contains(cfg, expectedConfig) + return strings.Contains(cfg, expectedConfig) || strings.Contains(cfg, expectedConfigCrossPlane) }) ginkgo.By("making sure new ingress is responding") @@ -91,8 +93,9 @@ var _ = framework.IngressNginxDescribe("[SSL] [Flag] default-ssl-certificate", f ginkgo.By("making sure new ingress is deployed") expectedConfig := fmt.Sprintf(`set $proxy_upstream_name "%v-%v-%v";`, f.Namespace, service, port) + expectedConfigCrossPlane := fmt.Sprintf(`set $proxy_upstream_name %v-%v-%v;`, f.Namespace, service, port) f.WaitForNginxServer(host, func(cfg string) bool { - return strings.Contains(cfg, expectedConfig) + return strings.Contains(cfg, expectedConfig) || strings.Contains(cfg, expectedConfigCrossPlane) }) ginkgo.By("making sure the configured default ssl certificate is being used") diff --git a/test/e2e/settings/disable_catch_all.go b/test/e2e/settings/disable_catch_all.go index 4e7a16f4de..54fbe9d8bd 100644 --- a/test/e2e/settings/disable_catch_all.go +++ b/test/e2e/settings/disable_catch_all.go @@ -62,7 +62,8 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() { f.WaitForNginxServer("_", func(cfg string) bool { return strings.Contains(cfg, `set $ingress_name ""`) && - strings.Contains(cfg, `set $proxy_upstream_name "upstream-default-backend"`) + (strings.Contains(cfg, `set $proxy_upstream_name "upstream-default-backend"`) || + strings.Contains(cfg, `set $proxy_upstream_name upstream-default-backend`)) }) }) @@ -74,7 +75,8 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() { f.WaitForNginxServer("_", func(cfg string) bool { return strings.Contains(cfg, `set $ingress_name ""`) && - strings.Contains(cfg, `set $proxy_upstream_name "upstream-default-backend"`) + (strings.Contains(cfg, `set $proxy_upstream_name "upstream-default-backend"`) || + strings.Contains(cfg, `set $proxy_upstream_name upstream-default-backend`)) }) }) diff --git a/test/e2e/settings/global_external_auth.go b/test/e2e/settings/global_external_auth.go index f589a63e94..1721c54a57 100644 --- a/test/e2e/settings/global_external_auth.go +++ b/test/e2e/settings/global_external_auth.go @@ -246,6 +246,9 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() { }) ginkgo.It(`should set snippet when global external auth is configured`, func() { + if framework.IsCrossplane() { + ginkgo.Skip("crossplane does not support snippets") + } globalExternalAuthSnippetSetting := "global-auth-snippet" globalExternalAuthSnippet := "proxy_set_header My-Custom-Header 42;" diff --git a/test/e2e/settings/gzip.go b/test/e2e/settings/gzip.go index c7e580e079..b2972e69c3 100644 --- a/test/e2e/settings/gzip.go +++ b/test/e2e/settings/gzip.go @@ -106,7 +106,7 @@ var _ = framework.DescribeSetting("gzip", func() { f.WaitForNginxConfiguration( func(cfg string) bool { return strings.Contains(cfg, "gzip on;") && - strings.Contains(cfg, `gzip_disable "msie6";`) + (strings.Contains(cfg, `gzip_disable "msie6";`) || strings.Contains(cfg, `gzip_disable msie6;`)) }, ) diff --git a/test/e2e/settings/limit_rate.go b/test/e2e/settings/limit_rate.go index 9d79dc3582..16ce982778 100644 --- a/test/e2e/settings/limit_rate.go +++ b/test/e2e/settings/limit_rate.go @@ -41,7 +41,7 @@ var _ = framework.DescribeSetting("Configmap - limit-rate", func() { f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) }) wlKey := "limit-rate" diff --git a/test/e2e/settings/main_snippet.go b/test/e2e/settings/main_snippet.go index ff14bab9d2..50bf96caed 100644 --- a/test/e2e/settings/main_snippet.go +++ b/test/e2e/settings/main_snippet.go @@ -26,6 +26,9 @@ import ( var _ = framework.DescribeSetting("main-snippet", func() { f := framework.NewDefaultFramework("main-snippet") + if framework.IsCrossplane() { + return + } mainSnippet := "main-snippet" ginkgo.It("should add value of main-snippet setting to nginx config", func() { diff --git a/test/e2e/settings/modsecurity/modsecurity_snippet.go b/test/e2e/settings/modsecurity/modsecurity_snippet.go index 2dd92ced26..5e82ccf8e7 100644 --- a/test/e2e/settings/modsecurity/modsecurity_snippet.go +++ b/test/e2e/settings/modsecurity/modsecurity_snippet.go @@ -26,6 +26,9 @@ import ( var _ = framework.DescribeSetting("[Security] modsecurity-snippet", func() { f := framework.NewDefaultFramework("modsecurity-snippet") + if framework.IsCrossplane() { + return + } ginkgo.It("should add value of modsecurity-snippet setting to nginx config", func() { expectedComment := "# modsecurity snippet" diff --git a/test/e2e/settings/no_tls_redirect_locations.go b/test/e2e/settings/no_tls_redirect_locations.go index 18fd09e267..b9ac1bb971 100644 --- a/test/e2e/settings/no_tls_redirect_locations.go +++ b/test/e2e/settings/no_tls_redirect_locations.go @@ -33,7 +33,7 @@ var _ = framework.DescribeSetting("Add no tls redirect locations", func() { f.EnsureIngress(ing) f.WaitForNginxConfiguration(func(server string) bool { - return strings.Contains(server, "set $force_no_ssl_redirect \"false\"") + return strings.Contains(server, "set $force_no_ssl_redirect \"false\"") || strings.Contains(server, "set $force_no_ssl_redirect false") }) wlKey := "no-tls-redirect-locations" @@ -42,7 +42,7 @@ var _ = framework.DescribeSetting("Add no tls redirect locations", func() { f.UpdateNginxConfigMapData(wlKey, wlValue) f.WaitForNginxConfiguration(func(server string) bool { - return strings.Contains(server, "set $force_no_ssl_redirect \"true\"") + return strings.Contains(server, "set $force_no_ssl_redirect \"true\"") || strings.Contains(server, "set $force_no_ssl_redirect true") }) }) }) diff --git a/test/e2e/settings/proxy_host.go b/test/e2e/settings/proxy_host.go index bb5dc9c012..1fcda11a13 100644 --- a/test/e2e/settings/proxy_host.go +++ b/test/e2e/settings/proxy_host.go @@ -34,14 +34,16 @@ var _ = framework.IngressNginxDescribe("Dynamic $proxy_host", func() { }) ginkgo.It("should exist a proxy_host", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() + + h := make(map[string]string) + h["Custom-Header"] = "$proxy_host" + cfgMap := "add-headers-configmap" + + f.CreateConfigMap(cfgMap, h) + f.UpdateNginxConfigMapData("add-headers", fmt.Sprintf("%s/%s", f.Namespace, cfgMap)) upstreamName := fmt.Sprintf("%v-%v-80", f.Namespace, framework.EchoService) - annotations := map[string]string{ - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_headers "Custom-Header: $proxy_host"`, - } - f.EnsureIngress(framework.NewSingleIngress(test, "/", test, f.Namespace, framework.EchoService, 80, annotations)) + f.EnsureIngress(framework.NewSingleIngress(test, "/", test, f.Namespace, framework.EchoService, 80, nil)) f.WaitForNginxConfiguration( func(server string) bool { @@ -58,15 +60,20 @@ var _ = framework.IngressNginxDescribe("Dynamic $proxy_host", func() { }) ginkgo.It("should exist a proxy_host using the upstream-vhost annotation value", func() { - disableSnippet := f.AllowSnippetConfiguration() - defer disableSnippet() + + h := make(map[string]string) + h["Custom-Header"] = "$proxy_host" + cfgMap := "add-headers-configmap" + + f.CreateConfigMap(cfgMap, h) + f.UpdateNginxConfigMapData("add-headers", fmt.Sprintf("%s/%s", f.Namespace, cfgMap)) upstreamName := fmt.Sprintf("%v-%v-80", f.Namespace, framework.EchoService) upstreamVHost := "different.host" annotations := map[string]string{ - "nginx.ingress.kubernetes.io/upstream-vhost": upstreamVHost, - "nginx.ingress.kubernetes.io/configuration-snippet": `more_set_headers "Custom-Header: $proxy_host"`, + "nginx.ingress.kubernetes.io/upstream-vhost": upstreamVHost, } + f.EnsureIngress(framework.NewSingleIngress(test, "/", test, f.Namespace, framework.EchoService, 80, annotations)) f.WaitForNginxConfiguration( diff --git a/test/e2e/settings/proxy_protocol.go b/test/e2e/settings/proxy_protocol.go index cfce68bf8a..4c2e2a1aaf 100644 --- a/test/e2e/settings/proxy_protocol.go +++ b/test/e2e/settings/proxy_protocol.go @@ -162,6 +162,9 @@ var _ = framework.DescribeSetting("use-proxy-protocol", func() { }) ginkgo.It("should enable PROXY Protocol for TCP", func() { + if framework.IsCrossplane() { + return + } cmapData := map[string]string{} cmapData[setting] = "true" cmapData["enable-real-ip"] = "true" diff --git a/test/e2e/settings/server_snippet.go b/test/e2e/settings/server_snippet.go index 1e2084bd84..e162630db7 100644 --- a/test/e2e/settings/server_snippet.go +++ b/test/e2e/settings/server_snippet.go @@ -28,6 +28,9 @@ import ( var _ = framework.DescribeSetting("configmap server-snippet", func() { f := framework.NewDefaultFramework("cm-server-snippet") + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { f.NewEchoDeployment() }) diff --git a/test/e2e/settings/ssl_ciphers.go b/test/e2e/settings/ssl_ciphers.go index 241dfc92b2..f80bf41a27 100644 --- a/test/e2e/settings/ssl_ciphers.go +++ b/test/e2e/settings/ssl_ciphers.go @@ -35,7 +35,7 @@ var _ = framework.DescribeSetting("ssl-ciphers", func() { f.UpdateNginxConfigMapData(wlKey, wlValue) f.WaitForNginxConfiguration(func(cfg string) bool { - return strings.Contains(cfg, fmt.Sprintf("ssl_ciphers '%s';", wlValue)) + return strings.Contains(cfg, fmt.Sprintf("ssl_ciphers '%s';", wlValue)) || strings.Contains(cfg, fmt.Sprintf("ssl_ciphers %s;", wlValue)) }) }) }) diff --git a/test/e2e/settings/ssl_passthrough.go b/test/e2e/settings/ssl_passthrough.go index b10511bde4..111c0c776d 100644 --- a/test/e2e/settings/ssl_passthrough.go +++ b/test/e2e/settings/ssl_passthrough.go @@ -35,6 +35,9 @@ import ( var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() { f := framework.NewDefaultFramework("ssl-passthrough", framework.WithHTTPBunEnabled()) + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error { diff --git a/test/e2e/settings/stream_snippet.go b/test/e2e/settings/stream_snippet.go index e1552afd36..4d1757a086 100644 --- a/test/e2e/settings/stream_snippet.go +++ b/test/e2e/settings/stream_snippet.go @@ -34,6 +34,9 @@ import ( var _ = framework.DescribeSetting("configmap stream-snippet", func() { f := framework.NewDefaultFramework("cm-stream-snippet") + if framework.IsCrossplane() { + return + } ginkgo.BeforeEach(func() { f.NewEchoDeployment() diff --git a/test/e2e/settings/tls.go b/test/e2e/settings/tls.go index 1ebf358c18..2191116642 100644 --- a/test/e2e/settings/tls.go +++ b/test/e2e/settings/tls.go @@ -71,7 +71,7 @@ var _ = framework.DescribeSetting("[SSL] TLS protocols, ciphers and headers", fu f.WaitForNginxConfiguration( func(cfg string) bool { - return strings.Contains(cfg, fmt.Sprintf("ssl_ciphers '%s';", testCiphers)) + return strings.Contains(cfg, fmt.Sprintf("ssl_ciphers '%s';", testCiphers)) || strings.Contains(cfg, fmt.Sprintf("ssl_ciphers %s;", testCiphers)) }) resp := f.HTTPTestClientWithTLSConfig(tlsConfig). diff --git a/test/e2e/tcpudp/tcp.go b/test/e2e/tcpudp/tcp.go index 856184d18b..de45b00351 100644 --- a/test/e2e/tcpudp/tcp.go +++ b/test/e2e/tcpudp/tcp.go @@ -37,6 +37,9 @@ import ( var _ = framework.IngressNginxDescribe("[TCP] tcp-services", func() { f := framework.NewDefaultFramework("tcp") + if framework.IsCrossplane() { + return + } var ip string ginkgo.BeforeEach(func() { From cb7cb7fd3300e5b1799e1b6132aab404787740be Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Sun, 10 Nov 2024 17:13:02 -0700 Subject: [PATCH 10/16] Remove temporary templates --- .../template/crossplane/testdata/README.md | 8 - .../crossplane/testdata/nginx-new-orig.tmpl | 1450 ----------------- .../crossplane/testdata/nginx-new.tmpl | 1268 -------------- 3 files changed, 2726 deletions(-) delete mode 100644 internal/ingress/controller/template/crossplane/testdata/README.md delete mode 100644 internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl delete mode 100644 internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl diff --git a/internal/ingress/controller/template/crossplane/testdata/README.md b/internal/ingress/controller/template/crossplane/testdata/README.md deleted file mode 100644 index 4f44e3c98e..0000000000 --- a/internal/ingress/controller/template/crossplane/testdata/README.md +++ /dev/null @@ -1,8 +0,0 @@ -This directory contains the following files: - -* nginx.tmpl - Should be used to track migrated directives. We will test later to see -if the ending result of it is the same as the one parsed by go-crossplane -* various nginx.conf - Will be used to see if the template parser reacts as -expected, creating files that matches and can be parsed by go-crossplane - -TODO: move files to embed.FS \ No newline at end of file diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl deleted file mode 100644 index b7fa803829..0000000000 --- a/internal/ingress/controller/template/crossplane/testdata/nginx-new-orig.tmpl +++ /dev/null @@ -1,1450 +0,0 @@ -{{ $all := . }} -{{ $servers := .Servers }} -{{ $cfg := .Cfg }} -{{ $IsIPV6Enabled := .IsIPV6Enabled }} -{{ $healthzURI := .HealthzURI }} -{{ $backends := .Backends }} -{{ $proxyHeaders := .ProxySetHeaders }} -{{ $addHeaders := .AddHeaders }} - -# Configuration checksum: {{ $all.Cfg.Checksum }} - -# setup custom paths that do not require root access -pid {{ .PID }}; # OK - -{{ if $cfg.UseGeoIP2 }} #OK -load_module /etc/nginx/modules/ngx_http_geoip2_module.so; -{{ end }} - -{{ if $cfg.EnableBrotli }} #OK -load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; -load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; -{{ end }} - -{{ if (shouldLoadAuthDigestModule $servers) }} -load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; -{{ end }} - -{{ if (shouldLoadModSecurityModule $cfg $servers) }} -load_module /etc/nginx/modules/ngx_http_modsecurity_module.so; -{{ end }} - -{{ if (shouldLoadOpentelemetryModule $cfg $servers) }} -load_module /etc/nginx/modules/otel_ngx_module.so; -{{ end }} - -daemon off; # OK - -worker_processes {{ $cfg.WorkerProcesses }}; # OK -{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} # OK -worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; -{{ end }} - -worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; # OK - -{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} -{{/* avoid waiting too long during a reload */}} -worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; # OK - -# REMOVED -# {{ if not (empty $cfg.MainSnippet) }} -# {{ $cfg.MainSnippet }} -# {{ end }} - -events { - multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; # OK - worker_connections {{ $cfg.MaxWorkerConnections }}; # OK - use epoll; # OK - {{ range $index , $v := $cfg.DebugConnections }} # OK - debug_connection {{ $v }}; # OK - {{ end }} -} - -http { - {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} - opentelemetry_config {{ $cfg.OpentelemetryConfig }}; - {{ end }} - - lua_package_path "/etc/nginx/lua/?.lua;;"; # OK - - {{ buildLuaSharedDictionaries $cfg $servers }} # OK - - lua_shared_dict luaconfig 5m; # OK - - init_by_lua_file /etc/nginx/lua/ngx_conf_init.lua; # OK - - init_worker_by_lua_file /etc/nginx/lua/ngx_conf_init_worker.lua; # OK - - {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} - {{/* we use the value of the real IP for the geo_ip module */}} - {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} - {{ if $cfg.UseProxyProtocol }} - real_ip_header proxy_protocol; - {{ else }} - real_ip_header {{ $cfg.ForwardedForHeader }}; - {{ end }} - - real_ip_recursive on; - {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} - set_real_ip_from {{ $trusted_ip }}; - {{ end }} - {{ end }} - - {{ if $all.Cfg.EnableModsecurity }} - modsecurity on; - - {{ if (not (empty $all.Cfg.ModsecuritySnippet)) }} - modsecurity_rules ' - {{ $all.Cfg.ModsecuritySnippet }} - '; - {{ else }} - modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf; - {{ end }} - - {{ if $all.Cfg.EnableOWASPCoreRules }} - modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf; - {{ end }} - - {{ end }} - - {{ if $cfg.UseGeoIP2 }} - # https://github.com/leev/ngx_http_geoip2_module#example-usage - - {{ range $index, $file := $all.MaxmindEditionFiles }} - {{ if eq $file "GeoLite2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; - $geoip2_country_name source=$remote_addr country names en; - $geoip2_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_continent_code source=$remote_addr continent code; - $geoip2_continent_name source=$remote_addr continent names en; - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; - } - {{ end }} - - {{ if eq $file "GeoIP2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; - $geoip2_country_name source=$remote_addr country names en; - $geoip2_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_continent_code source=$remote_addr continent code; - $geoip2_continent_name source=$remote_addr continent names en; - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; - } - {{ end }} - - {{ if eq $file "GeoLite2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; - $geoip2_city_country_name source=$remote_addr country names en; - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_city source=$remote_addr city names en; - $geoip2_city_geoname_id source=$remote_addr city geoname_id; - $geoip2_postal_code source=$remote_addr postal code; - $geoip2_dma_code source=$remote_addr location metro_code; - $geoip2_latitude source=$remote_addr location latitude; - $geoip2_longitude source=$remote_addr location longitude; - $geoip2_time_zone source=$remote_addr location time_zone; - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; - $geoip2_region_name source=$remote_addr subdivisions 0 names en; - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; - $geoip2_city_continent_code source=$remote_addr continent code; - $geoip2_city_continent_name source=$remote_addr continent names en; - } - {{ end }} - - {{ if eq $file "GeoIP2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; - $geoip2_city_country_name source=$remote_addr country names en; - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; - $geoip2_city source=$remote_addr city names en; - $geoip2_city_geoname_id source=$remote_addr city geoname_id; - $geoip2_postal_code source=$remote_addr postal code; - $geoip2_dma_code source=$remote_addr location metro_code; - $geoip2_latitude source=$remote_addr location latitude; - $geoip2_longitude source=$remote_addr location longitude; - $geoip2_time_zone source=$remote_addr location time_zone; - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; - $geoip2_region_name source=$remote_addr subdivisions 0 names en; - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; - $geoip2_city_continent_code source=$remote_addr continent code; - $geoip2_city_continent_name source=$remote_addr continent names en; - } - {{ end }} - - {{ if eq $file "GeoLite2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; - $geoip2_org source=$remote_addr autonomous_system_organization; - } - {{ end }} - - {{ if eq $file "GeoIP2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; - $geoip2_org source=$remote_addr autonomous_system_organization; - } - {{ end }} - - {{ if eq $file "GeoIP2-ISP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_isp source=$remote_addr isp; - $geoip2_isp_org source=$remote_addr organization; - $geoip2_asn source=$remote_addr default=0 autonomous_system_number; - } - {{ end }} - - {{ if eq $file "GeoIP2-Connection-Type.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Connection-Type.mmdb { - $geoip2_connection_type connection_type; - } - {{ end }} - - {{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; - {{ end }} - $geoip2_is_anon source=$remote_addr is_anonymous; - $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; - $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; - $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; - $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; - $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; - } - {{ end }} - - {{ end }} - - {{ end }} - - aio threads; - - {{ if $cfg.EnableAioWrite }} - aio_write on; - {{ end }} - - tcp_nopush on; - tcp_nodelay on; - - log_subrequest on; - - reset_timedout_connection on; - - keepalive_timeout {{ $cfg.KeepAlive }}s; - keepalive_requests {{ $cfg.KeepAliveRequests }}; - - client_body_temp_path /tmp/nginx/client-body; - fastcgi_temp_path /tmp/nginx/fastcgi-temp; - proxy_temp_path /tmp/nginx/proxy-temp; - - client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; - client_header_timeout {{ $cfg.ClientHeaderTimeout }}s; - large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; - client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; - client_body_timeout {{ $cfg.ClientBodyTimeout }}s; - - {{ if gt $cfg.GRPCBufferSizeKb 0 }} - grpc_buffer_size {{ $cfg.GRPCBufferSizeKb }}k; - {{ end }} - - {{ if and (ne $cfg.HTTP2MaxHeaderSize "") (ne $cfg.HTTP2MaxFieldSize "") }} - http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; - http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; - {{ end }} - - {{ if (gt $cfg.HTTP2MaxRequests 0) }} - http2_max_requests {{ $cfg.HTTP2MaxRequests }}; - {{ end }} - - http2_max_concurrent_streams {{ $cfg.HTTP2MaxConcurrentStreams }}; - - types_hash_max_size 2048; - server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; - server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; - map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; - - proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }}; - proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }}; - - variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; - variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; - - underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; - ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; - - limit_req_status {{ $cfg.LimitReqStatusCode }}; - limit_conn_status {{ $cfg.LimitConnStatusCode }}; - - {{ buildOpentelemetry $cfg $servers }} - - include /etc/nginx/mime.types; - default_type {{ $cfg.DefaultType }}; - - {{ if $cfg.EnableBrotli }} - brotli on; - brotli_comp_level {{ $cfg.BrotliLevel }}; - brotli_min_length {{ $cfg.BrotliMinLength }}; - brotli_types {{ $cfg.BrotliTypes }}; - {{ end }} - - {{ if $cfg.UseGzip }} - gzip on; - gzip_comp_level {{ $cfg.GzipLevel }}; - {{- if $cfg.GzipDisable }} - gzip_disable "{{ $cfg.GzipDisable }}"; - {{- end }} - gzip_http_version 1.1; - gzip_min_length {{ $cfg.GzipMinLength}}; - gzip_types {{ $cfg.GzipTypes }}; - gzip_proxied any; - gzip_vary on; - {{ end }} - - # Custom headers for response - {{ range $k, $v := $addHeaders }} - more_set_headers {{ printf "%s: %s" $k $v | quote }}; - {{ end }} - - server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; - {{ if not $cfg.ShowServerTokens }} - more_clear_headers Server; - {{ end }} - - # disable warnings - uninitialized_variable_warn off; - - # Additional available variables: - # $namespace - # $ingress_name - # $service_name - # $service_port - log_format upstreaminfo {{ if $cfg.LogFormatEscapeNone }}escape=none {{ else if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ $cfg.LogFormatUpstream }}'; - - {{/* map urls that should not appear in access.log */}} - {{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} - map $request_uri $loggable { - {{ range $reqUri := $cfg.SkipAccessLogURLs }} - {{ $reqUri }} 0;{{ end }} - default 1; - } - - {{ if or $cfg.DisableAccessLog $cfg.DisableHTTPAccessLog }} - access_log off; - {{ else }} - {{ if $cfg.EnableSyslog }} - access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable; - {{ else }} - access_log {{ or $cfg.HTTPAccessLogPath $cfg.AccessLogPath }} upstreaminfo {{ $cfg.AccessLogParams }} if=$loggable; - {{ end }} - {{ end }} - - {{ if $cfg.EnableSyslog }} - error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }}; - {{ else }} - error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; - {{ end }} - - {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} - - # See https://www.nginx.com/blog/websocket-nginx - map $http_upgrade $connection_upgrade { - default upgrade; - {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} - # See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - '' ''; - {{ else }} - '' close; - {{ end }} - } - - # Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server. - # If no such header is provided, it can provide a random value. - map $http_x_request_id $req_id { - default $http_x_request_id; - {{ if $cfg.GenerateRequestID }} - "" $request_id; - {{ end }} - } - - {{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} - # We can't use $proxy_add_x_forwarded_for because the realip module - # replaces the remote_addr too soon - map $http_x_forwarded_for $full_x_forwarded_for { - {{ if $all.Cfg.UseProxyProtocol }} - default "$http_x_forwarded_for, $proxy_protocol_addr"; - '' "$proxy_protocol_addr"; - {{ else }} - default "$http_x_forwarded_for, $realip_remote_addr"; - '' "$realip_remote_addr"; - {{ end}} - } - - {{ end }} - - # Create a variable that contains the literal $ character. - # This works because the geo module will not resolve variables. - geo $literal_dollar { - default "$"; - } - - server_name_in_redirect off; - port_in_redirect off; - - ssl_protocols {{ $cfg.SSLProtocols }}; - - ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; - - # turn on session caching to drastically improve performance - {{ if $cfg.SSLSessionCache }} - ssl_session_cache shared:SSL:{{ $cfg.SSLSessionCacheSize }}; - ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; - {{ end }} - - # allow configuring ssl session tickets - ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; - - {{ if not (empty $cfg.SSLSessionTicketKey ) }} - ssl_session_ticket_key /etc/ingress-controller/tickets.key; - {{ end }} - - # slightly reduce the time-to-first-byte - ssl_buffer_size {{ $cfg.SSLBufferSize }}; - - {{ if not (empty $cfg.SSLCiphers) }} - # allow configuring custom ssl ciphers - ssl_ciphers '{{ $cfg.SSLCiphers }}'; - ssl_prefer_server_ciphers on; - {{ end }} - - {{ if not (empty $cfg.SSLDHParam) }} - # allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam - ssl_dhparam {{ $cfg.SSLDHParam }}; - {{ end }} - - ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; - - # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} - ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; - ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; - - {{ if and $cfg.CustomHTTPErrors (not $cfg.DisableProxyInterceptErrors) }} - proxy_intercept_errors on; - {{ end }} - - {{ range $errCode := $cfg.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} - - proxy_ssl_session_reuse on; - - {{ if $cfg.AllowBackendServerHeader }} - proxy_pass_header Server; - {{ end }} - - {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; - {{ end }} - - {{ if not (empty $cfg.HTTPSnippet) }} - # Custom code snippet configured in the configuration configmap - {{ $cfg.HTTPSnippet }} - {{ end }} - - upstream upstream_balancer { - ### Attention!!! - # - # We no longer create "upstream" section for every backend. - # Backends are handled dynamically using Lua. If you would like to debug - # and see what backends ingress-nginx has in its memory you can - # install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin. - # Once you have the plugin you can use "kubectl ingress-nginx backends" command to - # inspect current backends. - # - ### - - server 0.0.0.1; # placeholder - - balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer.lua; - - {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} - keepalive {{ $cfg.UpstreamKeepaliveConnections }}; - keepalive_time {{ $cfg.UpstreamKeepaliveTime }}; - keepalive_timeout {{ $cfg.UpstreamKeepaliveTimeout }}s; - keepalive_requests {{ $cfg.UpstreamKeepaliveRequests }}; - {{ end }} - } - - {{ range $rl := (filterRateLimits $servers ) }} - # Ratelimit {{ $rl.Name }} - geo $remote_addr $allowlist_{{ $rl.ID }} { - default 0; - {{ range $ip := $rl.Allowlist }} - {{ $ip }} 1;{{ end }} - } - - # Ratelimit {{ $rl.Name }} - map $allowlist_{{ $rl.ID }} $limit_{{ $rl.ID }} { - 0 {{ $cfg.LimitConnZoneVariable }}; - 1 ""; - } - {{ end }} - - {{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} - {{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} - {{ range $zone := (buildRateLimitZones $servers) }} - {{ $zone }} - {{ end }} - - # Cache for internal auth checks - proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; - - # Global filters - {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - map $http_user_agent $block_ua { - default 0; - - {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; - {{ end }} - } - {{ end }} - - {{ if gt (len $cfg.BlockReferers) 0 }} - map $http_referer $block_ref { - default 0; - - {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; - {{ end }} - } - {{ end }} - - {{/* Build server redirects (from/to www) */}} - {{ range $redirect := .RedirectServers }} - ## start server {{ $redirect.From }} - server { - server_name {{ $redirect.From }}; - - {{ buildHTTPListener $all $redirect.From }} - {{ buildHTTPSListener $all $redirect.From }} - - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { - return 403; - } - {{ end }} - {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { - return 403; - } - {{ end }} - - set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; - - return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; - } - ## end server {{ $redirect.From }} - {{ end }} - - {{ range $server := $servers }} - {{ range $location := $server.Locations }} - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} - upstream {{ buildAuthUpstreamName $location $server.Hostname }} { - {{- $externalAuth := $location.ExternalAuth }} - server {{ extractHostPort $externalAuth.URL }}; - - keepalive {{ $externalAuth.KeepaliveConnections }}; - keepalive_requests {{ $externalAuth.KeepaliveRequests }}; - keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; - } - ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} - {{ end }} - {{ end }} - {{ end }} - - {{ range $server := $servers }} - ## start server {{ $server.Hostname }} - server { - server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; - - {{ if $cfg.UseHTTP2 }} - http2 on; - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { - return 403; - } - {{ end }} - {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { - return 403; - } - {{ end }} - - {{ template "SERVER" serverConfig $all $server }} - - {{ if not (empty $cfg.ServerSnippet) }} - # Custom code snippet configured in the configuration configmap - {{ $cfg.ServerSnippet }} - {{ end }} - - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics $cfg.EnableModsecurity) }} - } - ## end server {{ $server.Hostname }} - - {{ end }} - - # backend for when default-backend-service is not configured or it does not have endpoints - server { - listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; - {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} - set $proxy_upstream_name "internal"; - - access_log off; - - location / { - return 404; - } - } - - # default server, used for NGINX healthcheck and access to nginx stats - server { - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; - {{ end }} - - listen 127.0.0.1:{{ .StatusPort }}; - set $proxy_upstream_name "internal"; - - keepalive_timeout 0; - gzip off; - - access_log off; - - {{ if $cfg.EnableOpentelemetry }} - opentelemetry off; - {{ end }} - location {{ $healthzURI }} { - return 200; - } - - location /is-dynamic-lb-initialized { - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; - } - - location {{ .StatusPath }} { - stub_status on; - } - - location /configuration { - client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; - client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; - proxy_buffering off; - - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; - } - - location / { - return 404; - } - } -} - -stream { - lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;;"; - - lua_shared_dict tcp_udp_configuration_data 5M; - - {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} - - init_by_lua_file /etc/nginx/lua/ngx_conf_init_stream.lua; - - init_worker_by_lua_file /etc/nginx/lua/nginx/ngx_conf_init_tcp_udp.lua; - - lua_add_variable $proxy_upstream_name; - - log_format log_stream '{{ $cfg.LogFormatStream }}'; - - {{ if or $cfg.DisableAccessLog $cfg.DisableStreamAccessLog }} - access_log off; - {{ else }} - access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }}; - {{ end }} - - - error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; - {{ if $cfg.EnableRealIP }} - {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} - set_real_ip_from {{ $trusted_ip }}; - {{ end }} - {{ end }} - - upstream upstream_balancer { - server 0.0.0.1:1234; # placeholder - balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer_tcp_udp.lua; - } - - server { - listen 127.0.0.1:{{ .StreamPort }}; - - access_log off; - - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_content_tcp_udp.lua; - } - - # TCP services - {{ range $tcpServer := .TCPBackends }} - server { - preread_by_lua_block { - ngx.var.proxy_upstream_name="tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}"; - } - - {{ range $address := $all.Cfg.BindAddressIpv4 }} - listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ else }} - listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ end }} - {{ if $IsIPV6Enabled }} - {{ range $address := $all.Cfg.BindAddressIpv6 }} - listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ else }} - listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; - {{ end }} - {{ end }} - proxy_timeout {{ $cfg.ProxyStreamTimeout }}; - proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; - proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; - - proxy_pass upstream_balancer; - {{ if $tcpServer.Backend.ProxyProtocol.Encode }} - proxy_protocol on; - {{ end }} - } - {{ end }} - - # UDP services - {{ range $udpServer := .UDPBackends }} - server { - preread_by_lua_block { - ngx.var.proxy_upstream_name="udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}"; - } - - {{ range $address := $all.Cfg.BindAddressIpv4 }} - listen {{ $address }}:{{ $udpServer.Port }} udp; - {{ else }} - listen {{ $udpServer.Port }} udp; - {{ end }} - {{ if $IsIPV6Enabled }} - {{ range $address := $all.Cfg.BindAddressIpv6 }} - listen {{ $address }}:{{ $udpServer.Port }} udp; - {{ else }} - listen [::]:{{ $udpServer.Port }} udp; - {{ end }} - {{ end }} - proxy_responses {{ $cfg.ProxyStreamResponses }}; - proxy_timeout {{ $cfg.ProxyStreamTimeout }}; - proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; - proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; - proxy_pass upstream_balancer; - } - {{ end }} - - # Stream Snippets - {{ range $snippet := .StreamSnippets }} - {{ $snippet }} - {{ end }} -} - -{{/* definition of templates to avoid repetitions */}} -{{ define "CUSTOM_ERRORS" }} - {{ $enableMetrics := .EnableMetrics }} - {{ $modsecurityEnabled := .ModsecurityEnabled }} - {{ $upstreamName := .UpstreamName }} - {{ range $errCode := .ErrorCodes }} - location @custom_{{ $upstreamName }}_{{ $errCode }} { - internal; - - # Ensure that modsecurity will not run on custom error pages or they might be blocked - {{ if $modsecurityEnabled }} - modsecurity off; - {{ end }} - - proxy_intercept_errors off; - - proxy_set_header X-Code {{ $errCode }}; - proxy_set_header X-Format $http_accept; - proxy_set_header X-Original-URI $request_uri; - proxy_set_header X-Namespace $namespace; - proxy_set_header X-Ingress-Name $ingress_name; - proxy_set_header X-Service-Name $service_name; - proxy_set_header X-Service-Port $service_port; - proxy_set_header X-Request-ID $req_id; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $best_http_host; - - set $proxy_upstream_name {{ $upstreamName | quote }}; - - rewrite (.*) / break; - - proxy_pass http://upstream_balancer; - {{ if $enableMetrics }} - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; - {{ end }} - } - {{ end }} -{{ end }} - -{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} -{{ define "CORS" }} - {{ $cors := .CorsConfig }} - # Cors Preflight methods needs additional options and different Return Code - {{ if $cors.CorsAllowOrigin }} - {{ buildCorsOriginRegex $cors.CorsAllowOrigin }} - {{ end }} - if ($request_method = 'OPTIONS') { - set $cors ${cors}options; - } - - if ($cors = "true") { - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; - } - - if ($cors = "trueoptions") { - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; - more_set_headers 'Content-Type: text/plain charset=UTF-8'; - more_set_headers 'Content-Length: 0'; - return 204; - } -{{ end }} - -{{/* definition of server-template to avoid repetitions with server-alias */}} -{{ define "SERVER" }} - {{ $all := .First }} - {{ $server := .Second }} - - {{ buildHTTPListener $all $server.Hostname }} - {{ buildHTTPSListener $all $server.Hostname }} - - set $proxy_upstream_name "-"; - - {{ if not ( empty $server.CertificateAuth.MatchCN ) }} - {{ if gt (len $server.CertificateAuth.MatchCN) 0 }} - if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { - return 403 "client certificate unauthorized"; - } - {{ end }} - {{ end }} - - {{ if eq $server.Hostname "_" }} - ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; - {{ end }} - - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; - - {{ if not (empty $server.AuthTLSError) }} - # {{ $server.AuthTLSError }} - return 403; - {{ else }} - - {{ if not (empty $server.CertificateAuth.CAFileName) }} - # PEM sha: {{ $server.CertificateAuth.CASHA }} - ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; - ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; - ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; - - {{ if not (empty $server.CertificateAuth.CRLFileName) }} - # PEM sha: {{ $server.CertificateAuth.CRLSHA }} - ssl_crl {{ $server.CertificateAuth.CRLFileName }}; - {{ end }} - - {{ if not (empty $server.CertificateAuth.ErrorPage)}} - error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; - {{ end }} - {{ end }} - - {{ if not (empty $server.ProxySSL.CAFileName) }} - # PEM sha: {{ $server.ProxySSL.CASHA }} - proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; - proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; - proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; - proxy_ssl_verify {{ $server.ProxySSL.Verify }}; - proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; - {{ if not (empty $server.ProxySSL.ProxySSLName) }} - proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; - proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; - {{ end }} - {{ end }} - - {{ if not (empty $server.ProxySSL.PemFileName) }} - proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; - proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; - {{ end }} - - {{ if not (empty $server.SSLCiphers) }} - ssl_ciphers {{ $server.SSLCiphers }}; - {{ end }} - - {{ if not (empty $server.SSLPreferServerCiphers) }} - ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; - {{ end }} - - {{ if not (empty $server.ServerSnippet) }} - # Custom code snippet configured for host {{ $server.Hostname }} - {{ $server.ServerSnippet }} - {{ end }} - - {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics $all.Cfg.EnableModsecurity) }} - {{ end }} - - {{ buildMirrorLocations $server.Locations }} - - {{ $enforceRegex := enforceRegexModifier $server.Locations }} - {{ range $location := $server.Locations }} - {{ $path := buildLocation $location $enforceRegex }} - {{ $proxySetHeader := proxySetHeader $location }} - {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} - - {{ $externalAuth := $location.ExternalAuth }} - {{ if eq $applyGlobalAuth true }} - {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} - {{ end }} - - {{ if not (empty $location.Rewrite.AppRoot) }} - if ($uri = /) { - return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; - } - {{ end }} - - {{ if $authPath }} - location = {{ $authPath }} { - internal; - - {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} - opentelemetry on; - opentelemetry_propagate; - {{ end }} - - {{ if not $all.Cfg.EnableAuthAccessLog }} - access_log off; - {{ end }} - - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; - {{ end }} - - {{ if $externalAuth.AuthCacheKey }} - set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; - set $cache_key ''; - - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; - - proxy_cache auth_cache; - - {{- range $dur := $externalAuth.AuthCacheDuration }} - proxy_cache_valid {{ $dur }}; - {{- end }} - - proxy_cache_key "$cache_key"; - {{ end }} - - # ngx_auth_request module overrides variables in the parent request, - # therefore we have to explicitly set this variable again so that when the parent request - # resumes it has the correct value set for this variable so that Lua can pick backend correctly - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; - - proxy_pass_request_body off; - proxy_set_header Content-Length ""; - proxy_set_header X-Forwarded-Proto ""; - proxy_set_header X-Request-ID $req_id; - - {{ if $externalAuth.Method }} - proxy_method {{ $externalAuth.Method }}; - proxy_set_header X-Original-URI $request_uri; - proxy_set_header X-Scheme $pass_access_scheme; - {{ end }} - - proxy_set_header Host {{ $externalAuth.Host }}; - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; - proxy_set_header X-Original-Method $request_method; - proxy_set_header X-Sent-From "nginx-ingress-controller"; - proxy_set_header X-Real-IP $remote_addr; - {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - proxy_set_header X-Forwarded-For $full_x_forwarded_for; - {{ else }} - proxy_set_header X-Forwarded-For $remote_addr; - {{ end }} - - {{ if $externalAuth.RequestRedirect }} - proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; - {{ else }} - proxy_set_header X-Auth-Request-Redirect $request_uri; - {{ end }} - - {{ if $externalAuth.AuthCacheKey }} - proxy_buffering "on"; - {{ else }} - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; - {{ end }} - proxy_buffer_size {{ $location.Proxy.BufferSize }}; - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; - - proxy_ssl_server_name on; - proxy_pass_request_headers on; - {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; - {{ end }} - {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; - {{ end }} - - # Pass the extracted client certificate to the auth provider - {{ if not (empty $server.CertificateAuth.CAFileName) }} - {{ if $server.CertificateAuth.PassCertToUpstream }} - proxy_set_header ssl-client-cert $ssl_client_escaped_cert; - {{ end }} - proxy_set_header ssl-client-verify $ssl_client_verify; - proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; - proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; - {{ end }} - - {{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} - {{ $line }} - {{- end }} - - {{ if not (empty $externalAuth.AuthSnippet) }} - {{ $externalAuth.AuthSnippet }} - {{ end }} - - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} - # The target is an upstream with HTTP keepalive, that is why the - # Connection header is cleared and the HTTP version is set to 1.1 as - # the Nginx documentation suggests: - # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - proxy_http_version 1.1; - proxy_set_header Connection ""; - set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; - {{ else }} - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; - set $target {{ $externalAuth.URL }}; - {{ end }} - proxy_pass $target; - } - {{ end }} - - {{ if isLocationAllowed $location }} - {{ if $externalAuth.SigninURL }} - location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { - internal; - - add_header Set-Cookie $auth_cookie; - - {{ if $location.CorsConfig.CorsEnabled }} - {{ template "CORS" $location }} - {{ end }} - - # Ensure that modsecurity will not run on an internal location as this is not accessible from outside - {{ if $all.Cfg.EnableModsecurity }} - modsecurity off; - {{ end }} - - return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; - } - {{ end }} - {{ end }} - - location {{ $path }} { - {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} - set $namespace {{ $ing.Namespace | quote}}; - set $ingress_name {{ $ing.Rule | quote }}; - set $service_name {{ $ing.Service | quote }}; - set $service_port {{ $ing.ServicePort | quote }}; - set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; - - {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} - - {{ if $location.Mirror.Source }} - mirror {{ $location.Mirror.Source }}; - mirror_request_body {{ $location.Mirror.RequestBody }}; - {{ end }} - - {{ locationConfigForLua $location $all }} - - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; - - header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; - - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; - - {{ if not $location.Logs.Access }} - access_log off; - {{ end }} - - {{ if $location.Logs.Rewrite }} - rewrite_log on; - {{ end }} - - {{ if $location.HTTP2PushPreload }} - http2_push_preload on; - {{ end }} - - port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; - - set $balancer_ewma_score -1; - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; - set $proxy_host $proxy_upstream_name; - set $pass_access_scheme $scheme; - - {{ if $all.Cfg.UseProxyProtocol }} - set $pass_server_port $proxy_protocol_server_port; - {{ else }} - set $pass_server_port $server_port; - {{ end }} - - set $best_http_host $http_host; - set $pass_port $pass_server_port; - - set $proxy_alternative_upstream_name ""; - - {{ buildModSecurityForLocation $all.Cfg $location }} - - {{ if isLocationAllowed $location }} - {{ if gt (len $location.Denylist.CIDR) 0 }} - {{ range $ip := $location.Denylist.CIDR }} - deny {{ $ip }};{{ end }} - {{ end }} - {{ if gt (len $location.Allowlist.CIDR) 0 }} - {{ range $ip := $location.Allowlist.CIDR }} - allow {{ $ip }};{{ end }} - deny all; - {{ end }} - - {{ if $location.CorsConfig.CorsEnabled }} - {{ template "CORS" $location }} - {{ end }} - - {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} - {{ if $authPath }} - # this location requires authentication - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - set $auth_cookie ''; - add_header Set-Cookie $auth_cookie; - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} - {{ $line }} - {{- end }} - # `auth_request` module does not support HTTP keepalives in upstream block: - # https://trac.nginx.org/nginx/ticket/1579 - access_by_lua_block { - local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) - if res.status == ngx.HTTP_OK then - ngx.var.auth_cookie = res.header['Set-Cookie'] - {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} - {{ $line }} - {{- end }} - return - end - if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - } - {{ else }} - auth_request {{ $authPath }}; - auth_request_set $auth_cookie $upstream_http_set_cookie; - {{ if $externalAuth.AlwaysSetCookie }} - add_header Set-Cookie $auth_cookie always; - {{ else }} - add_header Set-Cookie $auth_cookie; - {{ end }} - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} - {{ $line }} - {{- end }} - {{ end }} - {{ end }} - - {{ if $externalAuth.SigninURL }} - set_escape_uri $escaped_request_uri $request_uri; - error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; - {{ end }} - - {{ if $location.BasicDigestAuth.Secured }} - {{ if eq $location.BasicDigestAuth.Type "basic" }} - auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; - auth_basic_user_file {{ $location.BasicDigestAuth.File }}; - {{ else }} - auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; - auth_digest_user_file {{ $location.BasicDigestAuth.File }}; - {{ end }} - {{ $proxySetHeader }} Authorization ""; - {{ end }} - {{ end }} - - {{/* if the location contains a rate limit annotation, create one */}} - {{ $limits := buildRateLimit $location }} - {{ range $limit := $limits }} - {{ $limit }}{{ end }} - - {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; - {{ end }} - {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; - {{ end }} - - {{/* By default use vhost as Host to upstream, but allow overrides */}} - {{ if not (empty $location.UpstreamVhost) }} - {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; - {{ else }} - {{ $proxySetHeader }} Host $best_http_host; - {{ end }} - - # Pass the extracted client certificate to the backend - {{ if not (empty $server.CertificateAuth.CAFileName) }} - {{ if $server.CertificateAuth.PassCertToUpstream }} - {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; - {{ end }} - {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; - {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; - {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; - {{ end }} - - # Allow websocket connections - {{ $proxySetHeader }} Upgrade $http_upgrade; - {{ if $location.Connection.Enabled}} - {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; - {{ else }} - {{ $proxySetHeader }} Connection $connection_upgrade; - {{ end }} - - {{ $proxySetHeader }} X-Request-ID $req_id; - {{ $proxySetHeader }} X-Real-IP $remote_addr; - {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; - {{ else }} - {{ $proxySetHeader }} X-Forwarded-For $remote_addr; - {{ end }} - {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; - {{ $proxySetHeader }} X-Forwarded-Port $pass_port; - {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; - {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; - {{ if $all.Cfg.ProxyAddOriginalURIHeader }} - {{ $proxySetHeader }} X-Original-URI $request_uri; - {{ end }} - {{ $proxySetHeader }} X-Scheme $pass_access_scheme; - - # Pass the original X-Forwarded-For - {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; - - # mitigate HTTPoxy Vulnerability - # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - {{ $proxySetHeader }} Proxy ""; - - # Custom headers to proxied server - {{ range $k, $v := $all.ProxySetHeaders }} - {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; - {{ end }} - - proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; - proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; - proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; - - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; - proxy_buffer_size {{ $location.Proxy.BufferSize }}; - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; - {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} - proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; - {{ end }} - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; - - proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; - proxy_cookie_path {{ $location.Proxy.CookiePath }}; - - # In case of errors try the next upstream server before returning an error - proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; - proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; - proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; - - {{ if or (eq $location.BackendProtocol "GRPC") (eq $location.BackendProtocol "GRPCS") }} - # Grpc settings - grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; - grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; - grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; - {{ end }} - - {{/* Add any additional configuration defined */}} - {{ $location.ConfigurationSnippet }} - - {{ if not (empty $all.Cfg.LocationSnippet) }} - # Custom code snippet configured in the configuration configmap - {{ $all.Cfg.LocationSnippet }} - {{ end }} - - {{ if $location.CustomHeaders }} - # Custom Response Headers - {{ range $k, $v := $location.CustomHeaders.Headers }} - more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; - {{ end }} - {{ end }} - - {{/* if we are sending the request to a custom default backend, we add the required headers */}} - {{ if (hasPrefix $location.Backend "custom-default-backend-") }} - proxy_set_header X-Code 503; - proxy_set_header X-Format $http_accept; - proxy_set_header X-Namespace $namespace; - proxy_set_header X-Ingress-Name $ingress_name; - proxy_set_header X-Service-Name $service_name; - proxy_set_header X-Service-Port $service_port; - proxy_set_header X-Request-ID $req_id; - {{ end }} - - {{ if $location.Satisfy }} - satisfy {{ $location.Satisfy }}; - {{ end }} - - {{/* if a location-specific error override is set, add the proxy_intercept here */}} - {{ if and $location.CustomHTTPErrors (not $location.DisableProxyInterceptErrors) }} - # Custom error pages per ingress - proxy_intercept_errors on; - {{ end }} - - {{ range $errCode := $location.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} - - {{ if (eq $location.BackendProtocol "FCGI") }} - include /etc/nginx/fastcgi_params; - {{ end }} - {{- if $location.FastCGI.Index -}} - fastcgi_index {{ $location.FastCGI.Index | quote }}; - {{- end -}} - {{ range $k, $v := $location.FastCGI.Params }} - fastcgi_param {{ $k }} {{ $v | quote }}; - {{ end }} - - {{ if not (empty $location.Redirect.URL) }} - return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; - {{ end }} - - {{ buildProxyPass $server.Hostname $all.Backends $location }} - {{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; - {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; - {{ end }} - {{ else }} - # Location denied. Reason: {{ $location.Denied | quote }} - return 503; - {{ end }} - {{ if not (empty $location.ProxySSL.CAFileName) }} - # PEM sha: {{ $location.ProxySSL.CASHA }} - proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; - proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; - proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; - proxy_ssl_verify {{ $location.ProxySSL.Verify }}; - proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; - {{ end }} - - {{ if not (empty $location.ProxySSL.ProxySSLName) }} - proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; - {{ end }} - {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} - proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; - {{ end }} - - {{ if not (empty $location.ProxySSL.PemFileName) }} - proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; - proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; - {{ end }} - } - {{ end }} - {{ end }} - - {{ if eq $server.Hostname "_" }} - # health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} - location {{ $all.HealthzURI }} { - - {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; - {{ end }} - - access_log off; - return 200; - } - - # this is required to avoid error if nginx is being monitored - # with an external software (like sysdig) - location /nginx_status { - - {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; - {{ end }} - - {{ range $v := $all.NginxStatusIpv4Whitelist }} - allow {{ $v }}; - {{ end }} - {{ if $all.IsIPV6Enabled -}} - {{ range $v := $all.NginxStatusIpv6Whitelist }} - allow {{ $v }}; - {{ end }} - {{ end -}} - deny all; - - access_log off; - stub_status on; - } - - {{ end }} - -{{ end }} diff --git a/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl b/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl deleted file mode 100644 index 547fd12dac..0000000000 --- a/internal/ingress/controller/template/crossplane/testdata/nginx-new.tmpl +++ /dev/null @@ -1,1268 +0,0 @@ -{{ $all := . }} -{{ $servers := .Servers }} -{{ $cfg := .Cfg }} -{{ $IsIPV6Enabled := .IsIPV6Enabled }} -{{ $healthzURI := .HealthzURI }} -{{ $backends := .Backends }} -{{ $proxyHeaders := .ProxySetHeaders }} -{{ $addHeaders := .AddHeaders }} - -# Configuration checksum: {{ $all.Cfg.Checksum }} - -# setup custom paths that do not require root access -pid {{ .PID }}; # OK - -{{ if $cfg.UseGeoIP2 }} -load_module /etc/nginx/modules/ngx_http_geoip2_module.so; # OK -{{ end }} - -{{ if $cfg.EnableBrotli }} -load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; # OK -load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; # OK -{{ end }} - -{{ if (shouldLoadAuthDigestModule $servers) }} -load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; # OK -{{ end }} - -{{ if (shouldLoadOpentelemetryModule $cfg $servers) }} -load_module /etc/nginx/modules/otel_ngx_module.so; # OK -{{ end }} - -daemon off; # OK - -worker_processes {{ $cfg.WorkerProcesses }}; # OK -{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} -worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; # OK -{{ end }} - -worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; # OK - -{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} -{{/* avoid waiting too long during a reload */}} -worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; # OK - -events { - multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; # OK - worker_connections {{ $cfg.MaxWorkerConnections }}; # OK - use epoll; # OK - {{ range $index , $v := $cfg.DebugConnections }} - debug_connection {{ $v }}; # OK - {{ end }} -} - -http { - {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} - opentelemetry_config {{ $cfg.OpentelemetryConfig }}; # OK - {{ end }} - - lua_package_path "/etc/nginx/lua/?.lua;;"; # OK - - {{ buildLuaSharedDictionaries $cfg $servers }} # OK - - lua_shared_dict luaconfig 5m; # OK - - init_by_lua_file /etc/nginx/lua/ngx_conf_init.lua; # OK - - init_worker_by_lua_file /etc/nginx/lua/ngx_conf_init_worker.lua; # OK - - {{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} - {{/* we use the value of the real IP for the geo_ip module */}} - {{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIP }} - {{ if $cfg.UseProxyProtocol }} - real_ip_header proxy_protocol; # OK - {{ else }} - real_ip_header {{ $cfg.ForwardedForHeader }}; # OK - {{ end }} - - real_ip_recursive on; # OK - {{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} - set_real_ip_from {{ $trusted_ip }}; # OK - {{ end }} - {{ end }} - - {{ if $cfg.UseGeoIP2 }} - # https://github.com/leev/ngx_http_geoip2_module#example-usage - - {{ range $index, $file := $all.MaxmindEditionFiles }} - {{ if eq $file "GeoLite2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-Country.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; # OK - $geoip2_country_name source=$remote_addr country names en; # OK - $geoip2_country_geoname_id source=$remote_addr country geoname_id; # OK - $geoip2_continent_code source=$remote_addr continent code; # OK - $geoip2_continent_name source=$remote_addr continent names en; # OK - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; # OK - } - {{ end }} - - {{ if eq $file "GeoIP2-Country.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Country.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_country_code source=$remote_addr country iso_code; # OK - $geoip2_country_name source=$remote_addr country names en; # OK - $geoip2_country_geoname_id source=$remote_addr country geoname_id; # OK - $geoip2_continent_code source=$remote_addr continent code; # OK - $geoip2_continent_name source=$remote_addr continent names en; # OK - $geoip2_continent_geoname_id source=$remote_addr continent geoname_id; # OK - } - {{ end }} - - {{ if eq $file "GeoLite2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-City.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; # OK - $geoip2_city_country_name source=$remote_addr country names en; # OK - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; # OK - $geoip2_city source=$remote_addr city names en; # OK - $geoip2_city_geoname_id source=$remote_addr city geoname_id; # OK - $geoip2_postal_code source=$remote_addr postal code; # OK - $geoip2_dma_code source=$remote_addr location metro_code; # OK - $geoip2_latitude source=$remote_addr location latitude; # OK - $geoip2_longitude source=$remote_addr location longitude; # OK - $geoip2_time_zone source=$remote_addr location time_zone; # OK - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; # OK - $geoip2_region_name source=$remote_addr subdivisions 0 names en; # OK - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; # OK - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; # OK - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; # OK - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; # OK - $geoip2_city_continent_code source=$remote_addr continent code; # OK - $geoip2_city_continent_name source=$remote_addr continent names en; # OK - } - {{ end }} - - {{ if eq $file "GeoIP2-City.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-City.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_city_country_code source=$remote_addr country iso_code; # OK - $geoip2_city_country_name source=$remote_addr country names en; # OK - $geoip2_city_country_geoname_id source=$remote_addr country geoname_id; # OK - $geoip2_city source=$remote_addr city names en; # OK - $geoip2_city_geoname_id source=$remote_addr city geoname_id; # OK - $geoip2_postal_code source=$remote_addr postal code; # OK - $geoip2_dma_code source=$remote_addr location metro_code; # OK - $geoip2_latitude source=$remote_addr location latitude; # OK - $geoip2_longitude source=$remote_addr location longitude; # OK - $geoip2_time_zone source=$remote_addr location time_zone; # OK - $geoip2_region_code source=$remote_addr subdivisions 0 iso_code; # OK - $geoip2_region_name source=$remote_addr subdivisions 0 names en; # OK - $geoip2_region_geoname_id source=$remote_addr subdivisions 0 geoname_id; # OK - $geoip2_subregion_code source=$remote_addr subdivisions 1 iso_code; # OK - $geoip2_subregion_name source=$remote_addr subdivisions 1 names en; # OK - $geoip2_subregion_geoname_id source=$remote_addr subdivisions 1 geoname_id; # OK - $geoip2_city_continent_code source=$remote_addr continent code; # OK - $geoip2_city_continent_name source=$remote_addr continent names en; # OK - } - {{ end }} - - {{ if eq $file "GeoLite2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoLite2-ASN.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; # OK - $geoip2_org source=$remote_addr autonomous_system_organization; # OK - } - {{ end }} - - {{ if eq $file "GeoIP2-ASN.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ASN.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_asn source=$remote_addr autonomous_system_number; # OK - $geoip2_org source=$remote_addr autonomous_system_organization; # OK - } - {{ end }} - - {{ if eq $file "GeoIP2-ISP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-ISP.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_isp source=$remote_addr isp; # OK - $geoip2_isp_org source=$remote_addr organization; # OK - $geoip2_asn source=$remote_addr default=0 autonomous_system_number; # OK - } - {{ end }} - - {{ if eq $file "GeoIP2-Connection-Type.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Connection-Type.mmdb { - $geoip2_connection_type connection_type; - } - {{ end }} - - {{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} - geoip2 /etc/ingress-controller/geoip/GeoIP2-Anonymous-IP.mmdb { # OK - {{ if (gt $cfg.GeoIP2AutoReloadMinutes 0) }} - auto_reload {{ $cfg.GeoIP2AutoReloadMinutes }}m; # OK - {{ end }} - $geoip2_is_anon source=$remote_addr is_anonymous; # OK - $geoip2_is_anonymous source=$remote_addr default=0 is_anonymous; # OK - $geoip2_is_anonymous_vpn source=$remote_addr default=0 is_anonymous_vpn; # OK - $geoip2_is_hosting_provider source=$remote_addr default=0 is_hosting_provider; # OK - $geoip2_is_public_proxy source=$remote_addr default=0 is_public_proxy; # OK - $geoip2_is_tor_exit_node source=$remote_addr default=0 is_tor_exit_node; # OK - } - {{ end }} - - {{ end }} - - {{ end }} - - aio threads; # OK - - {{ if $cfg.EnableAioWrite }} - aio_write on; # OK - {{ end }} - - tcp_nopush on; # OK - tcp_nodelay on; # OK - - log_subrequest on; # OK - - reset_timedout_connection on; # OK - - keepalive_timeout {{ $cfg.KeepAlive }}s; # OK - keepalive_requests {{ $cfg.KeepAliveRequests }}; # OK - - client_body_temp_path /tmp/nginx/client-body; # OK - fastcgi_temp_path /tmp/nginx/fastcgi-temp; # OK - proxy_temp_path /tmp/nginx/proxy-temp; # OK - - client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; # OK - client_header_timeout {{ $cfg.ClientHeaderTimeout }}s; # OK - large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; # OK - client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; # OK - client_body_timeout {{ $cfg.ClientBodyTimeout }}s; # OK - - {{ if gt $cfg.GRPCBufferSizeKb 0 }} - grpc_buffer_size {{ $cfg.GRPCBufferSizeKb }}k; # OK - {{ end }} - - {{ if and (ne $cfg.HTTP2MaxHeaderSize "") (ne $cfg.HTTP2MaxFieldSize "") }} # OK - http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; # OK - http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; # OK - {{ end }} - - {{ if (gt $cfg.HTTP2MaxRequests 0) }} # OK - http2_max_requests {{ $cfg.HTTP2MaxRequests }}; # OK - {{ end }} - - http2_max_concurrent_streams {{ $cfg.HTTP2MaxConcurrentStreams }}; # OK - - types_hash_max_size 2048; # OK - server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; # OK - server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; # OK - map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; # OK - - proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }}; # OK - proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }}; # OK - - variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; # OK - variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; # OK - - underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; # OK - ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; # OK - - limit_req_status {{ $cfg.LimitReqStatusCode }}; # OK - limit_conn_status {{ $cfg.LimitConnStatusCode }}; # OK - - {{ buildOpentelemetry $cfg $servers }} - - include /etc/nginx/mime.types; # OK - default_type {{ $cfg.DefaultType }}; # OK - - {{ if $cfg.EnableBrotli }} - brotli on; # OK - brotli_comp_level {{ $cfg.BrotliLevel }}; # OK - brotli_min_length {{ $cfg.BrotliMinLength }}; # OK - brotli_types {{ $cfg.BrotliTypes }}; # OK - {{ end }} - - {{ if $cfg.UseGzip }} - gzip on; # OK - gzip_comp_level {{ $cfg.GzipLevel }}; # OK - {{- if $cfg.GzipDisable }} - gzip_disable "{{ $cfg.GzipDisable }}"; # OK - {{- end }} - gzip_http_version 1.1; # OK - gzip_min_length {{ $cfg.GzipMinLength}}; # OK - gzip_types {{ $cfg.GzipTypes }}; # OK - gzip_proxied any; # OK - gzip_vary on; # OK - {{ end }} - - # Custom headers for response - {{ range $k, $v := $addHeaders }} - more_set_headers {{ printf "%s: %s" $k $v | quote }}; # OK - {{ end }} - - server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; # OK - {{ if not $cfg.ShowServerTokens }} - more_clear_headers Server; # OK - {{ end }} - - # disable warnings - uninitialized_variable_warn off; # OK - - # Additional available variables: - # $namespace - # $ingress_name - # $service_name - # $service_port - log_format upstreaminfo {{ if $cfg.LogFormatEscapeNone }}escape=none {{ else if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ $cfg.LogFormatUpstream }}'; # OK - - {{/* map urls that should not appear in access.log */}} - {{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} - map $request_uri $loggable { # OK - {{ range $reqUri := $cfg.SkipAccessLogURLs }} - {{ $reqUri }} 0;{{ end }} # OK - default 1; # OK - } - - {{ if or $cfg.DisableAccessLog $cfg.DisableHTTPAccessLog }} - access_log off; # OK - {{ else }} - {{ if $cfg.EnableSyslog }} - access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable; # OK - {{ else }} - access_log {{ or $cfg.HTTPAccessLogPath $cfg.AccessLogPath }} upstreaminfo {{ $cfg.AccessLogParams }} if=$loggable; # OK - {{ end }} - {{ end }} - - {{ if $cfg.EnableSyslog }} - error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }}; # OK - {{ else }} - error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; # OK - {{ end }} - - {{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} # OK - - # See https://www.nginx.com/blog/websocket-nginx - map $http_upgrade $connection_upgrade { # OK - default upgrade; # OK - {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} - # See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - '' ''; # OK - {{ else }} - '' close; # OK - {{ end }} - } - - # Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server. - # If no such header is provided, it can provide a random value. - map $http_x_request_id $req_id { # OK - default $http_x_request_id; # OK - {{ if $cfg.GenerateRequestID }} - "" $request_id; # OK - {{ end }} - } - - {{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} - # We can't use $proxy_add_x_forwarded_for because the realip module - # replaces the remote_addr too soon - map $http_x_forwarded_for $full_x_forwarded_for { # OK - {{ if $all.Cfg.UseProxyProtocol }} - default "$http_x_forwarded_for, $proxy_protocol_addr"; # OK - '' "$proxy_protocol_addr"; # OK - {{ else }} - default "$http_x_forwarded_for, $realip_remote_addr"; # OK - '' "$realip_remote_addr"; # OK - {{ end}} - } - - {{ end }} - - # Create a variable that contains the literal $ character. - # This works because the geo module will not resolve variables. - geo $literal_dollar { # OK - default "$"; # OK - } - - server_name_in_redirect off; # OK - port_in_redirect off; # OK - - ssl_protocols {{ $cfg.SSLProtocols }}; # OK - - ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; # OK - - # turn on session caching to drastically improve performance - {{ if $cfg.SSLSessionCache }} - ssl_session_cache shared:SSL:{{ $cfg.SSLSessionCacheSize }}; # OK - ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; # OK - {{ end }} - - # allow configuring ssl session tickets - ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; # OK - - {{ if not (empty $cfg.SSLSessionTicketKey ) }} - ssl_session_ticket_key /etc/ingress-controller/tickets.key; # OK - {{ end }} - - # slightly reduce the time-to-first-byte - ssl_buffer_size {{ $cfg.SSLBufferSize }}; # OK - - {{ if not (empty $cfg.SSLCiphers) }} - # allow configuring custom ssl ciphers - ssl_ciphers '{{ $cfg.SSLCiphers }}'; # OK - ssl_prefer_server_ciphers on; # OK - {{ end }} - - {{ if not (empty $cfg.SSLDHParam) }} - # allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam - ssl_dhparam {{ $cfg.SSLDHParam }}; # OK - {{ end }} - - ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; # OK - - # PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} - ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; # OK - ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; # OK - - {{ if and $cfg.CustomHTTPErrors (not $cfg.DisableProxyInterceptErrors) }} - proxy_intercept_errors on; # OK - {{ end }} - - {{ range $errCode := $cfg.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} # OK - - proxy_ssl_session_reuse on; # OK - - {{ if $cfg.AllowBackendServerHeader }} - proxy_pass_header Server; # OK - {{ end }} - - {{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; # OK - {{ end }} - - upstream upstream_balancer { - ### Attention!!! - # - # We no longer create "upstream" section for every backend. - # Backends are handled dynamically using Lua. If you would like to debug - # and see what backends ingress-nginx has in its memory you can - # install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin. - # Once you have the plugin you can use "kubectl ingress-nginx backends" command to - # inspect current backends. - # - ### - - server 0.0.0.1; # OK - - balancer_by_lua_file /etc/nginx/lua/nginx/ngx_conf_balancer.lua; # OK - - {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} - keepalive {{ $cfg.UpstreamKeepaliveConnections }}; # OK - keepalive_time {{ $cfg.UpstreamKeepaliveTime }}; # OK - keepalive_timeout {{ $cfg.UpstreamKeepaliveTimeout }}s; # OK - keepalive_requests {{ $cfg.UpstreamKeepaliveRequests }}; # OK - {{ end }} - } - - {{ range $rl := (filterRateLimits $servers ) }} - # Ratelimit {{ $rl.Name }} - geo $remote_addr $allowlist_{{ $rl.ID }} { - default 0; - {{ range $ip := $rl.Allowlist }} - {{ $ip }} 1;{{ end }} - } - - # Ratelimit {{ $rl.Name }} - map $allowlist_{{ $rl.ID }} $limit_{{ $rl.ID }} { - 0 {{ $cfg.LimitConnZoneVariable }}; - 1 ""; - } - {{ end }} - - {{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} - {{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} - {{ range $zone := (buildRateLimitZones $servers) }} - {{ $zone }} - {{ end }} - - # Cache for internal auth checks - proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; # OK - - # Global filters - {{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; # OK - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - map $http_user_agent $block_ua { # OK - default 0; # OK - - {{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; # OK - {{ end }} - } - {{ end }} - - {{ if gt (len $cfg.BlockReferers) 0 }} - map $http_referer $block_ref { # OK - default 0; # OK - - {{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; # OK - {{ end }} - } - {{ end }} - - {{/* Build server redirects (from/to www) */}} - {{ range $redirect := .RedirectServers }} - ## start server {{ $redirect.From }} - server { #OK - server_name {{ $redirect.From }}; # OK - - {{ buildHTTPListener $all $redirect.From }} # OK - {{ buildHTTPSListener $all $redirect.From }} # OK - - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; # OK - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { # OK - return 403; # OK - } - {{ end }} - {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { # OK - return 403; #OK - } - {{ end }} - - set_by_lua_file $redirect_to /etc/nginx/lua/nginx/ngx_srv_redirect.lua {{ $redirect.To }}; # OK - - return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; # OK - } - ## end server {{ $redirect.From }} - {{ end }} - - {{ range $server := $servers }} - {{ range $location := $server.Locations }} - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} - upstream {{ buildAuthUpstreamName $location $server.Hostname }} { - {{- $externalAuth := $location.ExternalAuth }} - server {{ extractHostPort $externalAuth.URL }}; - - keepalive {{ $externalAuth.KeepaliveConnections }}; - keepalive_requests {{ $externalAuth.KeepaliveRequests }}; - keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; - } - ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} - {{ end }} - {{ end }} - {{ end }} - - {{ range $server := $servers }} - ## start server {{ $server.Hostname }} - server { - server_name {{ buildServerName $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; OK - - {{ if $cfg.UseHTTP2 }} - http2 on; OK - {{ end }} - - {{ if gt (len $cfg.BlockUserAgents) 0 }} - if ($block_ua) { OK - return 403; OK - } - {{ end }} - {{ if gt (len $cfg.BlockReferers) 0 }} - if ($block_ref) { OK - return 403; OK - } - {{ end }} - - {{ template "SERVER" serverConfig $all $server }} - - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics) }} # OK - } - ## end server {{ $server.Hostname }} - - {{ end }} - - # backend for when default-backend-service is not configured or it does not have endpoints - server { # OK - listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; # OK - {{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} # OK - set $proxy_upstream_name "internal"; # OK - - access_log off; # OK - - location / { # OK - return 404; # OK - } - } - - # default server, used for NGINX healthcheck and access to nginx stats - server { # OK - - listen 127.0.0.1:{{ .StatusPort }}; # OK - set $proxy_upstream_name "internal"; # OK - - keepalive_timeout 0; # OK - gzip off; # OK - - access_log off; # OK - - {{ if $cfg.EnableOpentelemetry }} - opentelemetry off; # OK - {{ end }} - location {{ $healthzURI }} { # OK - return 200; # OK - } - - location /is-dynamic-lb-initialized { # OK - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_is_dynamic_lb_initialized.lua; # OK - } - - location {{ .StatusPath }} { # OK - stub_status on; # OK - } - - location /configuration { # OK - client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}; # OK - client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}; # OK - proxy_buffering off; # OK - - content_by_lua_file /etc/nginx/lua/nginx/ngx_conf_configuration.lua; # OK - } - - location / { # OK - return 404; # OK - } - } -} - -{{/* definition of templates to avoid repetitions */}} -{{ define "CUSTOM_ERRORS" }} - {{ $enableMetrics := .EnableMetrics }} - {{ $upstreamName := .UpstreamName }} - {{ range $errCode := .ErrorCodes }} - location @custom_{{ $upstreamName }}_{{ $errCode }} { # OK - internal; # OK - proxy_intercept_errors off; # OK - - proxy_set_header X-Code {{ $errCode }}; # OK - proxy_set_header X-Format $http_accept; # OK - proxy_set_header X-Original-URI $request_uri; # OK - proxy_set_header X-Namespace $namespace; # OK - proxy_set_header X-Ingress-Name $ingress_name; # OK - proxy_set_header X-Service-Name $service_name;# OK - proxy_set_header X-Service-Port $service_port; # OK - proxy_set_header X-Request-ID $req_id;# OK - proxy_set_header X-Forwarded-For $remote_addr; # OK - proxy_set_header Host $best_http_host; # OK - - set $proxy_upstream_name {{ $upstreamName | quote }}; # OK - - rewrite (.*) / break; # OK - - proxy_pass http://upstream_balancer; # OK - {{ if $enableMetrics }} - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log.lua; # OK - {{ end }} - } - {{ end }} -{{ end }} - -{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} -{{ define "CORS" }} - {{ $cors := .CorsConfig }} - # Cors Preflight methods needs additional options and different Return Code - {{ if $cors.CorsAllowOrigin }} - {{ buildCorsOriginRegex $cors.CorsAllowOrigin }} - {{ end }} - if ($request_method = 'OPTIONS') { # OK - set $cors ${cors}options; # OK - } - - if ($cors = "true") { # OK - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; # OK - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} # OK - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; # OK - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; # OK - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} # OK - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; # OK - } - - if ($cors = "trueoptions") { # OK - more_set_headers 'Access-Control-Allow-Origin: $http_origin'; # OK - {{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} # OK - more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; # OK - more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; # OK - {{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} # OK - more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; # OK - more_set_headers 'Content-Type: text/plain charset=UTF-8'; # OK - more_set_headers 'Content-Length: 0'; # OK - return 204; # OK - } -{{ end }} - -{{/* definition of server-template to avoid repetitions with server-alias */}} -{{ define "SERVER" }} - {{ $all := .First }} - {{ $server := .Second }} - - {{ buildHTTPListener $all $server.Hostname }} # OK - {{ buildHTTPSListener $all $server.Hostname }} # OK - - set $proxy_upstream_name "-"; # OK - - {{ if not ( empty $server.CertificateAuth.MatchCN ) }} - {{ if gt (len $server.CertificateAuth.MatchCN) 0 }} - if ( $ssl_client_s_dn !~ {{ $server.CertificateAuth.MatchCN }} ) { # OK - return 403 "client certificate unauthorized"; # OK - } - {{ end }} - {{ end }} - - {{ if eq $server.Hostname "_" }} - ssl_reject_handshake {{ if $all.Cfg.SSLRejectHandshake }}on{{ else }}off{{ end }}; # OK - {{ end }} - - ssl_certificate_by_lua_file /etc/nginx/lua/nginx/ngx_conf_certificate.lua; # OK - - {{ if not (empty $server.AuthTLSError) }} - # {{ $server.AuthTLSError }} # NOT, WHERE THIS IF ENDS?? Couldn't reproduce this config on my ingress - return 403; - {{ else }} - - {{ if not (empty $server.CertificateAuth.CAFileName) }} - # PEM sha: {{ $server.CertificateAuth.CASHA }} - ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; # OK - ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; # OK - ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; # OK - - {{ if not (empty $server.CertificateAuth.CRLFileName) }} - # PEM sha: {{ $server.CertificateAuth.CRLSHA }} - ssl_crl {{ $server.CertificateAuth.CRLFileName }}; # OK - {{ end }} - - {{ if not (empty $server.CertificateAuth.ErrorPage)}} - error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; # OK - {{ end }} - {{ end }} - - {{ if not (empty $server.ProxySSL.CAFileName) }} - # PEM sha: {{ $server.ProxySSL.CASHA }} - proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; # OK - proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; # OK - proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; # OK - proxy_ssl_verify {{ $server.ProxySSL.Verify }}; # OK - proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; # OK - {{ if not (empty $server.ProxySSL.ProxySSLName) }} - proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; # OK - proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; # OK - {{ end }} - {{ end }} - - {{ if not (empty $server.ProxySSL.PemFileName) }} - proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; # OK - proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; # OK - {{ end }} - - {{ if not (empty $server.SSLCiphers) }} - ssl_ciphers {{ $server.SSLCiphers }}; # OK - {{ end }} - - {{ if not (empty $server.SSLPreferServerCiphers) }} - ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; # OK - {{ end }} - - {{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} # OK - {{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics) }} # OK - {{ end }} - - {{ buildMirrorLocations $server.Locations }} # OK - - {{ $enforceRegex := enforceRegexModifier $server.Locations }} # OK - {{ range $location := $server.Locations }} - {{ $path := buildLocation $location $enforceRegex }} # OK - {{ $proxySetHeader := proxySetHeader $location }} # OK - {{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} # OK - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} # OK - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} # OK - - {{ $externalAuth := $location.ExternalAuth }} # OK - {{ if eq $applyGlobalAuth true }} - {{ $externalAuth = $all.Cfg.GlobalExternalAuth }} # OK - {{ end }} - - {{ if not (empty $location.Rewrite.AppRoot) }} - if ($uri = /) { # OK - return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; # OK - } - {{ end }} - - {{ if $authPath }} - location = {{ $authPath }} { - internal; # OK - - {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} - opentelemetry on; # OK - opentelemetry_propagate; # OK - {{ end }} - - {{ if not $all.Cfg.EnableAuthAccessLog }} - access_log off; # OK - {{ end }} - - {{ if $externalAuth.AuthCacheKey }} - set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; # OK - set $cache_key ''; # OK - - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_conf_rewrite_auth.lua; # OK - - proxy_cache auth_cache; # OK - - {{- range $dur := $externalAuth.AuthCacheDuration }} - proxy_cache_valid {{ $dur }}; # OK - {{- end }} - - proxy_cache_key "$cache_key"; # OK - {{ end }} - - # ngx_auth_request module overrides variables in the parent request, - # therefore we have to explicitly set this variable again so that when the parent request - # resumes it has the correct value set for this variable so that Lua can pick backend correctly - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; # OK - - proxy_pass_request_body off; # OK - proxy_set_header Content-Length ""; # OK - proxy_set_header X-Forwarded-Proto ""; # OK - proxy_set_header X-Request-ID $req_id; # OK - - {{ if $externalAuth.Method }} - proxy_method {{ $externalAuth.Method }}; - proxy_set_header X-Original-URI $request_uri; # OK - proxy_set_header X-Scheme $pass_access_scheme; # OK - {{ end }} - - proxy_set_header Host {{ $externalAuth.Host }}; # OK - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; # OK - proxy_set_header X-Original-Method $request_method; # OK - proxy_set_header X-Sent-From "nginx-ingress-controller"; # OK - proxy_set_header X-Real-IP $remote_addr; # OK - {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - proxy_set_header X-Forwarded-For $full_x_forwarded_for; # OK - {{ else }} - proxy_set_header X-Forwarded-For $remote_addr; # OK - {{ end }} - - {{ if $externalAuth.RequestRedirect }} - proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; # OK - {{ else }} - proxy_set_header X-Auth-Request-Redirect $request_uri; # OK - {{ end }} - - {{ if $externalAuth.AuthCacheKey }} - proxy_buffering "on"; # OK - {{ else }} - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; # OK - {{ end }} - proxy_buffer_size {{ $location.Proxy.BufferSize }}; # OK - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; # OK - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; # OK - - proxy_ssl_server_name on; # OK - proxy_pass_request_headers on; # OK - {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; # OK - {{ end }} - {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; # OK - {{ end }} - - # Pass the extracted client certificate to the auth provider - {{ if not (empty $server.CertificateAuth.CAFileName) }} - {{ if $server.CertificateAuth.PassCertToUpstream }} - proxy_set_header ssl-client-cert $ssl_client_escaped_cert; # OK - {{ end }} - proxy_set_header ssl-client-verify $ssl_client_verify; # OK - proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; # OK - proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; # OK - {{ end }} - - {{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} - {{ $line }} # OK - {{- end }} - - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - {{ $authUpstreamName := buildAuthUpstreamName $location $server.Hostname }} - # The target is an upstream with HTTP keepalive, that is why the - # Connection header is cleared and the HTTP version is set to 1.1 as - # the Nginx documentation suggests: - # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive - proxy_http_version 1.1; # OK - proxy_set_header Connection ""; # OK - set $target {{ changeHostPort $externalAuth.URL $authUpstreamName }}; # OK - {{ else }} - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; # OK - set $target {{ $externalAuth.URL }}; # OK - {{ end }} - proxy_pass $target; # OK - } - {{ end }} - - {{ if isLocationAllowed $location }} - {{ if $externalAuth.SigninURL }} - location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { - internal; # OK - - add_header Set-Cookie $auth_cookie; # OK - - {{ if $location.CorsConfig.CorsEnabled }} - {{ template "CORS" $location }} # OK - {{ end }} - - return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; # OK - } - {{ end }} - {{ end }} - - location {{ $path }} { - {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} - set $namespace {{ $ing.Namespace | quote}}; # OK - set $ingress_name {{ $ing.Rule | quote }}; # OK - set $service_name {{ $ing.Service | quote }}; # OK - set $service_port {{ $ing.ServicePort | quote }}; # OK - set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; # OK - - {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} # OK - - {{ if $location.Mirror.Source }} - mirror {{ $location.Mirror.Source }}; # OK - mirror_request_body {{ $location.Mirror.RequestBody }}; # OK - {{ end }} - - {{ locationConfigForLua $location $all }} # OK - - rewrite_by_lua_file /etc/nginx/lua/nginx/ngx_rewrite.lua; # OK - - header_filter_by_lua_file /etc/nginx/lua/nginx/ngx_conf_srv_hdr_filter.lua; # OK - - log_by_lua_file /etc/nginx/lua/nginx/ngx_conf_log_block.lua; # OK - - {{ if not $location.Logs.Access }} - access_log off; # OK - {{ end }} - - {{ if $location.Logs.Rewrite }} - rewrite_log on; # OK - {{ end }} - - {{ if $location.HTTP2PushPreload }} - http2_push_preload on; # OK - {{ end }} - - port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; # OK - - set $balancer_ewma_score -1; # OK - set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; # OK - set $proxy_host $proxy_upstream_name; # OK - set $pass_access_scheme $scheme; # OK - - {{ if $all.Cfg.UseProxyProtocol }} - set $pass_server_port $proxy_protocol_server_port; # OK - {{ else }} - set $pass_server_port $server_port; # OK - {{ end }} - - set $best_http_host $http_host; # OK - set $pass_port $pass_server_port; # OK - - set $proxy_alternative_upstream_name ""; # OK - - {{ if isLocationAllowed $location }} # 1 - {{ if gt (len $location.Denylist.CIDR) 0 }} # 2 - {{ range $ip := $location.Denylist.CIDR }} # 3 - deny {{ $ip }};{{ end }} # 2 # OK - {{ end }} # 1 - {{ if gt (len $location.Allowlist.CIDR) 0 }} # 2 - {{ range $ip := $location.Allowlist.CIDR }} # 3 - allow {{ $ip }};{{ end }} # 2 # OK - deny all; # OK - {{ end }} # 1 - - {{ if $location.CorsConfig.CorsEnabled }} # 2 - {{ template "CORS" $location }} # OK - {{ end }} # 1 - - {{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} # 2 - {{ if $authPath }} # 3 - # this location requires authentication - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} # 4 - set $auth_cookie ''; - add_header Set-Cookie $auth_cookie; - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders true }} # 5 - {{ $line }} - {{- end }} # 4 - # `auth_request` module does not support HTTP keepalives in upstream block: - # https://trac.nginx.org/nginx/ticket/1579 - access_by_lua_block { - local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) - if res.status == ngx.HTTP_OK then - ngx.var.auth_cookie = res.header['Set-Cookie'] - {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} - {{ $line }} - {{- end }} - return - end - if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - } - {{ else }} - auth_request {{ $authPath }}; - auth_request_set $auth_cookie $upstream_http_set_cookie; - {{ if $externalAuth.AlwaysSetCookie }} # 5 - add_header Set-Cookie $auth_cookie always; - {{ else }} - add_header Set-Cookie $auth_cookie; - {{ end }} # 4 - {{- range $line := buildAuthResponseHeaders $proxySetHeader $externalAuth.ResponseHeaders false }} # 5 - {{ $line }} - {{- end }} # 4 - {{ end }} # 3 - {{ end }} # 2 - - {{ if $externalAuth.SigninURL }} # 3 - set_escape_uri $escaped_request_uri $request_uri; - error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; - {{ end }} # 2 - - {{ if $location.BasicDigestAuth.Secured }} # 3 - {{ if eq $location.BasicDigestAuth.Type "basic" }} # 4 - auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; - auth_basic_user_file {{ $location.BasicDigestAuth.File }}; - {{ else }} - auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; - auth_digest_user_file {{ $location.BasicDigestAuth.File }}; - {{ end }} # 3 - {{ $proxySetHeader }} Authorization ""; - {{ end }} # 2 - {{ end }} # 1 - - {{/* if the location contains a rate limit annotation, create one */}} - {{ $limits := buildRateLimit $location }} - {{ range $limit := $limits }} # 2 # OK - {{ $limit }}{{ end }} # 1 - - {{ if isValidByteSize $location.Proxy.BodySize true }} - client_max_body_size {{ $location.Proxy.BodySize }}; # OK - {{ end }} - {{ if isValidByteSize $location.ClientBodyBufferSize false }} - client_body_buffer_size {{ $location.ClientBodyBufferSize }}; # OK - {{ end }} # 1 - - {{/* By default use vhost as Host to upstream, but allow overrides */}} - {{ if not (empty $location.UpstreamVhost) }} - {{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; # OK - {{ else }} - {{ $proxySetHeader }} Host $best_http_host; # OK - {{ end }} # 1 - - # Pass the extracted client certificate to the backend - {{ if not (empty $server.CertificateAuth.CAFileName) }} # 2 - {{ if $server.CertificateAuth.PassCertToUpstream }} # 3 - {{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; # OK - {{ end }} # 2 - {{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; # OK - {{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; # OK - {{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; # OK - {{ end }} # 1 - - # Allow websocket connections - {{ $proxySetHeader }} Upgrade $http_upgrade; # OK - {{ if $location.Connection.Enabled}} - {{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; # OK - {{ else }} - {{ $proxySetHeader }} Connection $connection_upgrade; # OK - {{ end }} - - {{ $proxySetHeader }} X-Request-ID $req_id; # OK - {{ $proxySetHeader }} X-Real-IP $remote_addr; # OK - {{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} - {{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; # OK - {{ else }} - {{ $proxySetHeader }} X-Forwarded-For $remote_addr; # OK - {{ end }} # 1 - {{ $proxySetHeader }} X-Forwarded-Host $best_http_host; # OK - {{ $proxySetHeader }} X-Forwarded-Port $pass_port; # OK - {{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; # OK - {{ $proxySetHeader }} X-Forwarded-Scheme $pass_access_scheme; # OK - {{ if $all.Cfg.ProxyAddOriginalURIHeader }} - {{ $proxySetHeader }} X-Original-URI $request_uri; # OK - {{ end }} # 1 - {{ $proxySetHeader }} X-Scheme $pass_access_scheme; # OK - - # Pass the original X-Forwarded-For - {{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; # OK - - # mitigate HTTPoxy Vulnerability - # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - {{ $proxySetHeader }} Proxy ""; # OK - - # Custom headers to proxied server - {{ range $k, $v := $all.ProxySetHeaders }} - {{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; # OK - {{ end }} # 1 - - proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; OK - proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; # OK - proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; # OK - - proxy_buffering {{ $location.Proxy.ProxyBuffering }}; # OK - proxy_buffer_size {{ $location.Proxy.BufferSize }}; # OK - proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; # OK - {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} - proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; # OK - {{ end }} - proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; # OK - proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; # OK - - proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; # OK - proxy_cookie_path {{ $location.Proxy.CookiePath }}; # OK - - # In case of errors try the next upstream server before returning an error - proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; # OK - proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; # OK - proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; # OK - - {{ if or (eq $location.BackendProtocol "GRPC") (eq $location.BackendProtocol "GRPCS") }} - # Grpc settings - grpc_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; # OK - grpc_send_timeout {{ $location.Proxy.SendTimeout }}s; # OK - grpc_read_timeout {{ $location.Proxy.ReadTimeout }}s; # OK - {{ end }} # 1 - - - {{ if $location.CustomHeaders }} # 2 - # Custom Response Headers - {{ range $k, $v := $location.CustomHeaders.Headers }} # 3 - more_set_headers {{ printf "%s: %s" $k $v | escapeLiteralDollar | quote }}; # OK - {{ end }} # 2 - {{ end }} # 1 - - {{/* if we are sending the request to a custom default backend, we add the required headers */}} - {{ if (hasPrefix $location.Backend "custom-default-backend-") }} - proxy_set_header X-Code 503; # OK - proxy_set_header X-Format $http_accept; # OK - proxy_set_header X-Namespace $namespace; # OK - proxy_set_header X-Ingress-Name $ingress_name; # OK - proxy_set_header X-Service-Name $service_name; # OK - proxy_set_header X-Service-Port $service_port; # OK - proxy_set_header X-Request-ID $req_id; # OK - {{ end }} # 1 - - {{ if $location.Satisfy }} - satisfy {{ $location.Satisfy }}; # OK - {{ end }} # 1 - - {{/* if a location-specific error override is set, add the proxy_intercept here */}} - {{ if and $location.CustomHTTPErrors (not $location.DisableProxyInterceptErrors) }} - # Custom error pages per ingress - proxy_intercept_errors on; # OK - {{ end }} # 1 - - {{ range $errCode := $location.CustomHTTPErrors }} - error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} # OK - - {{ if (eq $location.BackendProtocol "FCGI") }} - include /etc/nginx/fastcgi_params; OK - {{ end }} # 1 - {{- if $location.FastCGI.Index -}} - fastcgi_index {{ $location.FastCGI.Index | quote }}; # OK - {{- end -}} # 1 - {{ range $k, $v := $location.FastCGI.Params }} - fastcgi_param {{ $k }} {{ $v | quote }}; # OK - {{ end }} # 1 - - {{ if not (empty $location.Redirect.URL) }} - return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; # OK - {{ end }} # 1 - - {{ buildProxyPass $server.Hostname $all.Backends $location }} # OK - {{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; # OK - {{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} - proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; # OK - {{ end }} # 1 - {{ else }} - # Location denied. Reason: {{ $location.Denied | quote }} # OK - return 503; # OK - {{ end }} # 0 - {{ if not (empty $location.ProxySSL.CAFileName) }} # 1 - # PEM sha: {{ $location.ProxySSL.CASHA }} # OK - proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; # OK - proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; # OK - proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; # OK - proxy_ssl_verify {{ $location.ProxySSL.Verify }}; # OK - proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; # OK - {{ end }} # 0 - - {{ if not (empty $location.ProxySSL.ProxySSLName) }} # 1 - proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; # OK - {{ end }} # 0 - {{ if not (empty $location.ProxySSL.ProxySSLServerName) }} # 1 - proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; # OK - {{ end }} # 0 - - {{ if not (empty $location.ProxySSL.PemFileName) }} # 1 - proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; # OK - proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; # OK - {{ end }} # 0 - } - {{ end }} # End range - {{ end }} # Maybe that missing if... - - {{ if eq $server.Hostname "_" }} - # health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} - location {{ $all.HealthzURI }} { # OK - - {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; # OK - {{ end }} - - access_log off; # OK - return 200; # OK - } - - # this is required to avoid error if nginx is being monitored - # with an external software (like sysdig) - location /nginx_status { - - {{ if $all.Cfg.EnableOpentelemetry }} - opentelemetry off; # OK - {{ end }} - - {{ range $v := $all.NginxStatusIpv4Whitelist }} - allow {{ $v }}; # OK - {{ end }} - {{ if $all.IsIPV6Enabled -}} - {{ range $v := $all.NginxStatusIpv6Whitelist }} - allow {{ $v }}; # OK - {{ end }} - {{ end -}} - deny all; # OK - - access_log off; # OK - stub_status on; # OK - } - - {{ end }} - -{{ end }} From 8132b3ee107986a9a028b91037a527f15cdae8d1 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 12 Nov 2024 17:17:59 -0700 Subject: [PATCH 11/16] Add crossplane flag and e2e test --- .github/workflows/ci.yaml | 15 ++ .github/workflows/zz-tmpl-k8s-e2e.yaml | 1 + .golangci.yml | 1 + charts/ingress-nginx/templates/_params.tpl | 3 + charts/ingress-nginx/values.yaml | 1 + go.work.sum | 120 ++++++++++++++++ internal/ingress/controller/controller.go | 134 +++++++----------- internal/ingress/controller/nginx.go | 53 ++++--- .../template/crossplane/crossplane.go | 89 +++++------- .../crossplane_internal_utils_test.go | 19 +-- .../template/crossplane/crossplane_test.go | 19 ++- .../template/crossplane/location.go | 2 +- .../ingress/controller/template/template.go | 9 ++ pkg/flags/flags.go | 19 ++- test/e2e/framework/exec.go | 7 +- test/e2e/wait-for-nginx.sh | 10 +- 16 files changed, 322 insertions(+), 180 deletions(-) create mode 100644 go.work.sum diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c925264a86..7dd66a61e9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -320,3 +320,18 @@ jobs: with: k8s-version: ${{ matrix.k8s }} variation: "CHROOT" + + kubernetes-crossplane: + name: Kubernetes Crossplane + needs: + - changes + - build + if: | + (needs.changes.outputs.go == 'true') || (needs.changes.outputs.baseimage == 'true') || ${{ github.event.workflow_dispatch.run_e2e == 'true' }} + strategy: + matrix: + k8s: [v1.30.4, v1.31.0] + uses: ./.github/workflows/zz-tmpl-k8s-e2e.yaml + with: + k8s-version: ${{ matrix.k8s }} + variation: "CROSSPLANE" \ No newline at end of file diff --git a/.github/workflows/zz-tmpl-k8s-e2e.yaml b/.github/workflows/zz-tmpl-k8s-e2e.yaml index 996b673f94..935538a8e1 100644 --- a/.github/workflows/zz-tmpl-k8s-e2e.yaml +++ b/.github/workflows/zz-tmpl-k8s-e2e.yaml @@ -44,6 +44,7 @@ jobs: SKIP_INGRESS_IMAGE_CREATION: true SKIP_E2E_IMAGE_CREATION: true IS_CHROOT: ${{ inputs.variation == 'CHROOT' }} + IS_CROSSPLANE: ${{ inputs.variation == 'CROSSPLANE' }} run: | kind get kubeconfig > $HOME/.kube/kind-config-kind make kind-e2e-test diff --git a/.golangci.yml b/.golangci.yml index afbe3b8251..2d73e14e77 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,6 +25,7 @@ linters: - ginkgolinter - gocheckcompilerdirectives - goconst + - gocritic - gocyclo - godox - gofmt diff --git a/charts/ingress-nginx/templates/_params.tpl b/charts/ingress-nginx/templates/_params.tpl index 0051dc9c09..c4530ead64 100644 --- a/charts/ingress-nginx/templates/_params.tpl +++ b/charts/ingress-nginx/templates/_params.tpl @@ -60,6 +60,9 @@ {{- if .Values.controller.enableTopologyAwareRouting }} - --enable-topology-aware-routing=true {{- end }} +{{- if .Values.controller.templateEngine }} +- --configuration-template-engine={{ .Values.controller.templateEngine }} +{{- end }} {{- if .Values.controller.disableLeaderElection }} - --disable-leader-election=true {{- end }} diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 116adf7ca5..7b68e46feb 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -21,6 +21,7 @@ commonLabels: {} controller: name: controller + templateEngine: "go-template" enableAnnotationValidations: true image: ## Keep false as default for now! diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000000..257e3fa78e --- /dev/null +++ b/go.work.sum @@ -0,0 +1,120 @@ +cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/getsentry/sentry-go v0.21.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ncabatoff/fakescraper v0.0.0-20201102132415-4b37ba603d65/go.mod h1:Tx6UMSMyIsjLG/VU/F6xA1+0XI+/f9o1dGJnf1l+bPg= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= +github.com/uwu-tools/magex v0.10.0/go.mod h1:TrSEhrL1xHfJVy6n05AUwFdcQndgwrbgL5ybPNKWmVY= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= +go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= +go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= +go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= +go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +k8s.io/kms v0.31.2/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index aa8f4c4b92..63ea76dcff 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -61,89 +61,59 @@ const ( // Configuration contains all the settings required by an Ingress controller type Configuration struct { - APIServerHost string - RootCAFile string - - KubeConfigFile string - - Client clientset.Interface - - ResyncPeriod time.Duration - - ConfigMapName string - DefaultService string - - Namespace string - - WatchNamespaceSelector labels.Selector - - // +optional - TCPConfigMapName string - // +optional - UDPConfigMapName string - - DefaultSSLCertificate string - - // +optional - PublishService string - PublishStatusAddress string - - UpdateStatus bool - UseNodeInternalIP bool - ElectionID string - ElectionTTL time.Duration - UpdateStatusOnShutdown bool - - HealthCheckHost string - ListenPorts *ngx_config.ListenPorts - - DisableServiceExternalName bool - - EnableSSLPassthrough bool - - DisableLeaderElection bool - - EnableProfiling bool - - EnableMetrics bool - MetricsPerHost bool - MetricsPerUndefinedHost bool - MetricsBuckets *collectors.HistogramBuckets - MetricsBucketFactor float64 - MetricsMaxBuckets uint32 - ReportStatusClasses bool - ExcludeSocketMetrics []string - - FakeCertificate *ingress.SSLCert - - SyncRateLimit float32 - - DisableCatchAll bool - - IngressClassConfiguration *ingressclass.Configuration - - ValidationWebhook string - ValidationWebhookCertPath string - ValidationWebhookKeyPath string - DisableFullValidationTest bool - - GlobalExternalAuth *ngx_config.GlobalExternalAuth - MaxmindEditionFiles *[]string - - MonitorMaxBatchSize int - - PostShutdownGracePeriod int - ShutdownGracePeriod int - - InternalLoggerAddress string - IsChroot bool - DeepInspector bool - + APIServerHost string + RootCAFile string + KubeConfigFile string + Client clientset.Interface + ResyncPeriod time.Duration + ConfigMapName string + DefaultService string + Namespace string + WatchNamespaceSelector labels.Selector + TCPConfigMapName string + UDPConfigMapName string + DefaultSSLCertificate string + PublishService string + PublishStatusAddress string + UpdateStatus bool + UseNodeInternalIP bool + ElectionID string + ElectionTTL time.Duration + UpdateStatusOnShutdown bool + HealthCheckHost string + ListenPorts *ngx_config.ListenPorts + DisableServiceExternalName bool + EnableSSLPassthrough bool + DisableLeaderElection bool + EnableProfiling bool + EnableMetrics bool + MetricsPerHost bool + MetricsPerUndefinedHost bool + MetricsBuckets *collectors.HistogramBuckets + MetricsBucketFactor float64 + MetricsMaxBuckets uint32 + ReportStatusClasses bool + ExcludeSocketMetrics []string + FakeCertificate *ingress.SSLCert + SyncRateLimit float32 + DisableCatchAll bool + IngressClassConfiguration *ingressclass.Configuration + ValidationWebhook string + ValidationWebhookCertPath string + ValidationWebhookKeyPath string + DisableFullValidationTest bool + GlobalExternalAuth *ngx_config.GlobalExternalAuth + MaxmindEditionFiles *[]string + MonitorMaxBatchSize int + PostShutdownGracePeriod int + ShutdownGracePeriod int + InternalLoggerAddress string + IsChroot bool + DeepInspector bool DynamicConfigurationRetries int - - DisableSyncEvents bool - - EnableTopologyAwareRouting bool + DisableSyncEvents bool + EnableTopologyAwareRouting bool + ConfigurationTemplateEngine string } func getIngressPodZone(svc *apiv1.Service) string { diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index 6f138d7540..dba8934594 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -159,7 +159,10 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro } onTemplateChange := func() { - template, err := crossplane.NewTemplate() + if config.ConfigurationTemplateEngine != "go-template" { + return + } + template, err := ngx_template.NewTemplate(nginx.TemplatePath) if err != nil { // this error is different from the rest because it must be clear why nginx is not working klog.ErrorS(err, "Error loading new template") @@ -171,18 +174,28 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro n.syncQueue.EnqueueTask(task.GetDummyObject("template-change")) } - ngxTpl, err := crossplane.NewTemplate() - if err != nil { - klog.Fatalf("Invalid NGINX configuration template: %v", err) + var ngxTpl ngx_template.Writer + switch config.ConfigurationTemplateEngine { + case "go-template": + ngxTpl, err = ngx_template.NewTemplate(nginx.TemplatePath) + if err != nil { + klog.Fatalf("Invalid NGINX configuration template: %v", err) + } + _, err = file.NewFileWatcher(nginx.TemplatePath, onTemplateChange) + if err != nil { + klog.Fatalf("Error creating file watcher for %v: %v", nginx.TemplatePath, err) + } + case "crossplane": + ngxTpl, err = crossplane.NewTemplate() + if err != nil { + klog.Fatalf("Invalid NGINX configuration template: %v", err) + } + default: + klog.Fatal("Invalid template engine, please use 'go-template' or 'crossplane'") } n.t = ngxTpl - _, err = file.NewFileWatcher(nginx.TemplatePath, onTemplateChange) - if err != nil { - klog.Fatalf("Error creating file watcher for %v: %v", nginx.TemplatePath, err) - } - filesToWatch := []string{} if err := os.Mkdir("/etc/ingress-controller/geoip/", 0o755); err != nil && !os.IsExist(err) { @@ -653,6 +666,11 @@ func (n *NGINXController) testTemplate(cfg []byte) error { if err != nil { return err } + + if err := n.t.Validate(tmpfile.Name()); err != nil { + return fmt.Errorf("error during template validation: %w", err) + } + out, err := n.command.Test(tmpfile.Name()) if err != nil { // this error is different from the rest because it must be clear why nginx is not working @@ -701,7 +719,7 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error { err = n.testTemplate(content) if err != nil { - return fmt.Errorf("err %s content %s", err, string(content)) + return err } if klog.V(2).Enabled() { @@ -869,14 +887,15 @@ func (n *NGINXController) configureDynamically(pcfg *ingress.Configuration) erro } } - // TODO: (ricardo) - Disable in case this is crossplane, we don't support stream on this mode - /*streamConfigurationChanged := !reflect.DeepEqual(n.runningConfig.TCPEndpoints, pcfg.TCPEndpoints) || !reflect.DeepEqual(n.runningConfig.UDPEndpoints, pcfg.UDPEndpoints) - if streamConfigurationChanged { - err := updateStreamConfiguration(pcfg.TCPEndpoints, pcfg.UDPEndpoints) - if err != nil { - return err + if n.cfg.ConfigurationTemplateEngine == "go-template" { + streamConfigurationChanged := !reflect.DeepEqual(n.runningConfig.TCPEndpoints, pcfg.TCPEndpoints) || !reflect.DeepEqual(n.runningConfig.UDPEndpoints, pcfg.UDPEndpoints) + if streamConfigurationChanged { + err := updateStreamConfiguration(pcfg.TCPEndpoints, pcfg.UDPEndpoints) + if err != nil { + return err + } } - }*/ + } serversChanged := !reflect.DeepEqual(n.runningConfig.Servers, pcfg.Servers) if serversChanged { diff --git a/internal/ingress/controller/template/crossplane/crossplane.go b/internal/ingress/controller/template/crossplane/crossplane.go index 13796fdb8d..aab90a7526 100644 --- a/internal/ingress/controller/template/crossplane/crossplane.go +++ b/internal/ingress/controller/template/crossplane/crossplane.go @@ -18,7 +18,6 @@ package crossplane import ( "bytes" - "os" ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" @@ -31,55 +30,27 @@ Unsupported directives: - opentelemetry - modsecurity - any stream directive (TCP/UDP forwarding) -- geoip2 */ // On this case we will try to use the go ngx_crossplane to write the template instead of the template renderer type Template struct { - options *ngx_crossplane.BuildOptions - config *ngx_crossplane.Config - tplConfig *config.TemplateConfig - mimeFile string + options *ngx_crossplane.BuildOptions + parseOptions *ngx_crossplane.ParseOptions + config *ngx_crossplane.Config + tplConfig *config.TemplateConfig + mimeFile string } func NewTemplate() (*Template, error) { lua := ngx_crossplane.Lua{} - return &Template{ - mimeFile: "/etc/nginx/mime.types", - options: &ngx_crossplane.BuildOptions{ - Builders: []ngx_crossplane.RegisterBuilder{ - lua.RegisterBuilder(), - }, + buildOptions := &ngx_crossplane.BuildOptions{ + Builders: []ngx_crossplane.RegisterBuilder{ + lua.RegisterBuilder(), }, - }, nil -} - -func (c *Template) SetMimeFile(file string) { - c.mimeFile = file -} - -func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) { - c.tplConfig = conf - - // build root directives - c.buildConfig() - - // build events directive - c.buildEvents() - - // build http directive - c.buildHTTP() - - var buf bytes.Buffer - - err := ngx_crossplane.Build(&buf, *c.config, &ngx_crossplane.BuildOptions{}) - if err != nil { - return nil, err } - lua := ngx_crossplane.Lua{} - options := ngx_crossplane.ParseOptions{ + parseOptions := &ngx_crossplane.ParseOptions{ ParseComments: true, ErrorOnUnknownDirectives: true, StopParsingOnError: true, @@ -99,24 +70,40 @@ func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) { IgnoreDirectives: []string{"set_escape_uri"}, } - tmpFile, err := os.CreateTemp("", "") - if err != nil { - return nil, err - } - defer func() { - _ = os.Remove(tmpFile.Name()) - _ = tmpFile.Close() - }() + return &Template{ + mimeFile: "/etc/nginx/mime.types", + options: buildOptions, + parseOptions: parseOptions, + }, nil +} - _, err = tmpFile.Write(buf.Bytes()) - if err != nil { - return nil, err - } +func (c *Template) SetMimeFile(file string) { + c.mimeFile = file +} - _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) +func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) { + c.tplConfig = conf + + // build root directives + c.buildConfig() + + // build events directive + c.buildEvents() + + // build http directive + c.buildHTTP() + + var buf bytes.Buffer + + err := ngx_crossplane.Build(&buf, *c.config, &ngx_crossplane.BuildOptions{}) if err != nil { return nil, err } return buf.Bytes(), err } + +func (c *Template) Validate(filename string) error { + _, err := ngx_crossplane.Parse(filename, c.parseOptions) + return err +} diff --git a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go index b5c2b69627..6d8d813368 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_internal_utils_test.go @@ -22,7 +22,6 @@ import ( ngx_crossplane "github.com/nginxinc/nginx-go-crossplane" "github.com/stretchr/testify/require" - "k8s.io/ingress-nginx/internal/ingress/controller/config" ) // THIS FILE SHOULD BE USED JUST FOR INTERNAL TESTS - Private functions @@ -53,22 +52,6 @@ func Test_Internal_boolToStr(t *testing.T) { require.Equal(t, boolToStr(false), "off") } -func Test_Internal_buildLuaDictionaries(t *testing.T) { - t.Skip("Maps are not sorted, need to fix this") - cfg := &config.Configuration{ - LuaSharedDicts: map[string]int{ - "somedict": 1024, - "otherdict": 1025, - }, - } - directives := buildLuaSharedDictionaries(cfg) - require.Len(t, directives, 2) - require.Equal(t, "lua_shared_dict", directives[0].Directive) - require.Equal(t, []string{"somedict", "1M"}, directives[0].Args) - require.Equal(t, "lua_shared_dict", directives[1].Directive) - require.Equal(t, []string{"otherdict", "1025K"}, directives[1].Args) -} - func Test_Internal_buildCorsOriginRegex(t *testing.T) { tests := []struct { name string @@ -87,7 +70,7 @@ func Test_Internal_buildCorsOriginRegex(t *testing.T) { name: "multiple hosts should be changed properly", corsOrigins: []string{"*.xpto.com", " lalala.com"}, want: ngx_crossplane.Directives{ - buildBlockDirective("if", []string{"$http_origin", "~*", "([A-Za-z0-9\\-]+\\.xpto\\.com)", "|", "(lalala\\.com)"}, + buildBlockDirective("if", []string{"$http_origin", "~*", "(([A-Za-z0-9\\-]+\\.xpto\\.com)|(lalala\\.com))$"}, ngx_crossplane.Directives{buildDirective("set", "$cors", "true")}, ), }, diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 3d3fa745dd..02c59035ef 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -169,12 +169,27 @@ func TestCrossplaneTemplate(t *testing.T) { Target: "http://www.mymirror.com", RequestBody: "off", }, + Proxy: proxy.Config{ + ProxyBuffering: "on", + RequestBuffering: "on", + NextUpstream: "10.10.10.10", + }, }, { DefaultBackendUpstreamName: "something", - CustomHTTPErrors: []int{403, 404, 403, 409}, // Duplicated on purpose! + Proxy: proxy.Config{ + ProxyBuffering: "on", + RequestBuffering: "on", + NextUpstream: "10.10.10.10", + }, + CustomHTTPErrors: []int{403, 404, 403, 409}, // Duplicated on purpose! }, { + Proxy: proxy.Config{ + ProxyBuffering: "on", + RequestBuffering: "on", + NextUpstream: "10.10.10.10", + }, DefaultBackendUpstreamName: "otherthing", CustomHTTPErrors: []int{403, 404, 403, 409}, // Duplicated on purpose! }, @@ -255,7 +270,6 @@ func TestCrossplaneTemplate(t *testing.T) { _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) require.NoError(t, err) - require.Equal(t, "bla", string(content)) }) t.Run("it should set the right logging configs", func(t *testing.T) { @@ -352,6 +366,5 @@ func TestCrossplaneTemplate(t *testing.T) { _, err = ngx_crossplane.Parse(tmpFile.Name(), &options) require.NoError(t, err) - // require.Equal(t, " ", string(content)) }) } diff --git a/internal/ingress/controller/template/crossplane/location.go b/internal/ingress/controller/template/crossplane/location.go index af2ee433ba..e2a06f85e3 100644 --- a/internal/ingress/controller/template/crossplane/location.go +++ b/internal/ingress/controller/template/crossplane/location.go @@ -296,7 +296,7 @@ func (c *Template) buildAllowedLocation(server *ingress.Server, location *ingres if location.CorsConfig.CorsEnabled { dir = append(dir, buildCorsDirectives(location.CorsConfig)...) } - // TODO: Implement the build Auth Location + if !isLocationInLocationList(location, c.tplConfig.Cfg.NoAuthLocations) { dir = append(dir, buildAuthLocationConfig(location, locationConfig)...) } diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index ed052e4ecf..e420b9bcfb 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -71,6 +71,10 @@ type Writer interface { // NOTE: Implementors must ensure that the content of the returned slice is not modified by the implementation // after the return of this function. Write(conf *config.TemplateConfig) ([]byte, error) + // Validate is a function that can be called, containing the file name to be tested + // This function should be used just by specific cases like crossplane, otherwise it can return + // null error + Validate(filename string) error } // Template ingress template @@ -229,6 +233,11 @@ type LuaListenPorts struct { SSLProxyPort string `json:"ssl_proxy"` } +// Validate is no-op at go-template +func (t *Template) Validate(filename string) error { + return nil +} + // Write populates a buffer using a template with NGINX configuration // and the servers and upstreams created by Ingress rules func (t *Template) Write(conf *config.TemplateConfig) ([]byte, error) { diff --git a/pkg/flags/flags.go b/pkg/flags/flags.go index ce24160fdc..ff8fa3d737 100644 --- a/pkg/flags/flags.go +++ b/pkg/flags/flags.go @@ -233,6 +233,8 @@ Takes the form ":port". If not provided, no admission controller is starte disableSyncEvents = flags.Bool("disable-sync-events", false, "Disables the creation of 'Sync' event resources") enableTopologyAwareRouting = flags.Bool("enable-topology-aware-routing", false, "Enable topology aware routing feature, needs service object annotation service.kubernetes.io/topology-mode sets to auto.") + + configurationTemplateEngine = flags.String("configuration-template-engine", "go-template", "Defines what configuration template engine should be used. Can be 'go-template' or 'crossplane'. ") ) flags.StringVar(&nginx.MaxmindMirror, "maxmind-mirror", "", `Maxmind mirror url (example: http://geoip.local/databases.`) @@ -303,6 +305,10 @@ https://blog.maxmind.com/2019/12/significant-changes-to-accessing-and-using-geol return false, nil, fmt.Errorf("flags --publish-service and --publish-status-address are mutually exclusive") } + if *enableSSLPassthrough && *configurationTemplateEngine != "go-template" { + return false, nil, fmt.Errorf("SSL Passthrough can only be enabled with 'go-template' configuration engine") + } + nginx.HealthPath = *defHealthzURL if *defHealthCheckTimeout > 0 { @@ -390,12 +396,13 @@ https://blog.maxmind.com/2019/12/significant-changes-to-accessing-and-using-geol WatchWithoutClass: *watchWithoutClass, IngressClassByName: *ingressClassByName, }, - DisableCatchAll: *disableCatchAll, - ValidationWebhook: *validationWebhook, - ValidationWebhookCertPath: *validationWebhookCert, - ValidationWebhookKeyPath: *validationWebhookKey, - InternalLoggerAddress: *internalLoggerAddress, - DisableSyncEvents: *disableSyncEvents, + DisableCatchAll: *disableCatchAll, + ValidationWebhook: *validationWebhook, + ValidationWebhookCertPath: *validationWebhookCert, + ValidationWebhookKeyPath: *validationWebhookKey, + InternalLoggerAddress: *internalLoggerAddress, + DisableSyncEvents: *disableSyncEvents, + ConfigurationTemplateEngine: *configurationTemplateEngine, } if *apiserverHost != "" { diff --git a/test/e2e/framework/exec.go b/test/e2e/framework/exec.go index 8d528c37ae..ea38b8bef8 100644 --- a/test/e2e/framework/exec.go +++ b/test/e2e/framework/exec.go @@ -117,7 +117,12 @@ func (f *Framework) newIngressController(namespace, namespaceOverlay string) err isChroot = "false" } - cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay, isChroot) + isCrossplane, ok := os.LookupEnv("IS_CROSSPLANE") + if !ok { + isCrossplane = "false" + } + + cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay, isChroot, isCrossplane) out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("unexpected error waiting for ingress controller deployment: %v.\nLogs:\n%v", err, string(out)) diff --git a/test/e2e/wait-for-nginx.sh b/test/e2e/wait-for-nginx.sh index 73023aba15..8eb4368d0c 100755 --- a/test/e2e/wait-for-nginx.sh +++ b/test/e2e/wait-for-nginx.sh @@ -24,6 +24,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" export NAMESPACE=$1 export NAMESPACE_OVERLAY=$2 export IS_CHROOT=$3 +export IS_CROSSPLANE=$4 + +TPL_ENGINE="go-template" +if [ "$IS_CROSSPLANE" == "true" ]; then + TPL_ENGINE="crossplane" +fi echo "deploying NGINX Ingress controller in namespace $NAMESPACE" @@ -52,12 +58,14 @@ if [[ ! -z "$NAMESPACE_OVERLAY" && -d "$DIR/namespace-overlays/$NAMESPACE_OVERLA echo "Namespace overlay $NAMESPACE_OVERLAY is being used for namespace $NAMESPACE" helm install nginx-ingress ${DIR}/charts/ingress-nginx \ --namespace=$NAMESPACE \ - --values "$DIR/namespace-overlays/$NAMESPACE_OVERLAY/values.yaml" + --values "$DIR/namespace-overlays/$NAMESPACE_OVERLAY/values.yaml" \ + --set controller.templateEngine=${TPL_ENGINE} else cat << EOF | helm install nginx-ingress ${DIR}/charts/ingress-nginx --namespace=$NAMESPACE --values - # TODO: remove the need to use fullnameOverride fullnameOverride: nginx-ingress controller: + templateEngine: ${TPL_ENGINE} image: repository: ingress-controller/controller chroot: ${IS_CHROOT} From 78432192077a8ad2da365658b1b89952d41a0932 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 12 Nov 2024 17:25:24 -0700 Subject: [PATCH 12/16] Add setmisc 3rd party module --- .../template/crossplane/crossplane.go | 4 +- .../crossplane/extramodules/opentelemetry.go | 7 --- .../crossplane/extramodules/setmisc.go | 61 +++++++++++++++++++ 3 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 internal/ingress/controller/template/crossplane/extramodules/setmisc.go diff --git a/internal/ingress/controller/template/crossplane/crossplane.go b/internal/ingress/controller/template/crossplane/crossplane.go index aab90a7526..200e6ec52d 100644 --- a/internal/ingress/controller/template/crossplane/crossplane.go +++ b/internal/ingress/controller/template/crossplane/crossplane.go @@ -60,14 +60,12 @@ func NewTemplate() (*Template, error) { ngx_crossplane.MatchHeadersMoreLatest, extramodules.BrotliMatchFn, extramodules.OpentelemetryMatchFn, + extramodules.SetMiscMatchFn, ngx_crossplane.MatchGeoip2Latest, }, LexOptions: ngx_crossplane.LexOptions{ Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, }, - // Modules that needs to be ported: - // // https://github.com/openresty/set-misc-nginx-module?tab=readme-ov-file#set_escape_uri - IgnoreDirectives: []string{"set_escape_uri"}, } return &Template{ diff --git a/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go b/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go index f3a9cde9a3..a0039d6fde 100644 --- a/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go +++ b/internal/ingress/controller/template/crossplane/extramodules/opentelemetry.go @@ -14,13 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -/** - * Copyright (c) F5, Inc. - * - * This source code is licensed under the Apache License, Version 2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - // Code generated by generator; DO NOT EDIT. // All the definitions are extracted from the source code // Each bit mask describes these behaviors: diff --git a/internal/ingress/controller/template/crossplane/extramodules/setmisc.go b/internal/ingress/controller/template/crossplane/extramodules/setmisc.go new file mode 100644 index 0000000000..ab39ec5e84 --- /dev/null +++ b/internal/ingress/controller/template/crossplane/extramodules/setmisc.go @@ -0,0 +1,61 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by generator; DO NOT EDIT. +// All the definitions are extracted from the source code +// Each bit mask describes these behaviors: +// - how many arguments the directive can take +// - whether or not it is a block directive +// - whether this is a flag (takes one argument that's either "on" or "off") +// - which contexts it's allowed to be in + +package extramodules + +var setMiscDirectives = map[string][]uint{ + "set_base32_alphabet": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1, + }, + "set_base32_padding": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag, + }, + "set_decode_base32": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake12, + }, + "set_encode_base32": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake12, + }, + "set_formatted_gmt_time": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2, + }, + "set_formatted_local_time": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2, + }, + "set_hashed_upstream": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake3, + }, + "set_local_today": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1, + }, + "set_misc_base32_padding": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag, + }, +} + + +func SetMiscMatchFn(directive string) ([]uint, bool) { + m, ok := setMiscDirectives[directive] + return m, ok +} From 7d3cad25d35a0ae5c51857b33d8ba3820586c7e8 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 12 Nov 2024 17:35:52 -0700 Subject: [PATCH 13/16] Fix helm docs and fakeTemplate --- charts/ingress-nginx/README.md | 1 + charts/ingress-nginx/values.yaml | 1 + internal/ingress/controller/controller_test.go | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index c0b00e56d1..788a044417 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -489,6 +489,7 @@ metadata: | controller.sysctls | object | `{}` | sysctls for controller pods # Ref: https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ | | controller.tcp.annotations | object | `{}` | Annotations to be added to the tcp config configmap | | controller.tcp.configMapNamespace | string | `""` | Allows customization of the tcp-services-configmap; defaults to $(POD_NAMESPACE) | +| controller.templateEngine | string | `"go-template"` | Defines which template engine should be used when creating NGINX configuration. Can be 'go-template' or 'crossplane' | | controller.terminationGracePeriodSeconds | int | `300` | `terminationGracePeriodSeconds` to avoid killing pods before we are ready # wait up to five minutes for the drain of connections # | | controller.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | | controller.topologySpreadConstraints | list | `[]` | Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. # Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ # | diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 7b68e46feb..afe280fc3e 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -21,6 +21,7 @@ commonLabels: {} controller: name: controller + # -- Defines which template engine should be used when creating NGINX configuration. Can be 'go-template' or 'crossplane' templateEngine: "go-template" enableAnnotationValidations: true image: diff --git a/internal/ingress/controller/controller_test.go b/internal/ingress/controller/controller_test.go index 9d3fea4708..a830a57294 100644 --- a/internal/ingress/controller/controller_test.go +++ b/internal/ingress/controller/controller_test.go @@ -157,6 +157,10 @@ func (ntc testNginxTestCommand) Test(cfg string) ([]byte, error) { type fakeTemplate struct{} +func (fakeTemplate) Validate(filename string) error { + return nil +} + func (fakeTemplate) Write(conf *ngx_config.TemplateConfig) ([]byte, error) { r := []byte{} for _, s := range conf.Servers { From f3e7f3a2b7527513e0e4eb692fd964387e494c4a Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Tue, 12 Nov 2024 22:54:27 -0700 Subject: [PATCH 14/16] Fix lint, extra module, test assertions --- .../ingress/annotations/annotations_test.go | 1 - .../ingress/annotations/parser/validators.go | 2 - internal/ingress/controller/nginx.go | 7 +- .../template/crossplane/authlocation.go | 74 +++++++------------ .../controller/template/crossplane/cors.go | 4 +- .../template/crossplane/crossplane_test.go | 2 +- .../crossplane/extramodules/analyze.go | 2 - .../crossplane/extramodules/setmisc.go | 44 ++--------- .../controller/template/crossplane/http.go | 59 ++++++--------- .../template/crossplane/location.go | 6 +- .../controller/template/crossplane/server.go | 44 ++++++----- .../controller/template/crossplane/utils.go | 4 +- test/e2e/annotations/affinity.go | 36 ++++++--- test/e2e/annotations/affinitymode.go | 6 +- test/e2e/annotations/auth.go | 1 - test/e2e/annotations/grpc.go | 1 - test/e2e/annotations/limitconnections.go | 3 +- test/e2e/annotations/upstreamhashby.go | 3 +- test/e2e/framework/framework.go | 2 +- test/e2e/framework/httpexpect/response.go | 1 - test/e2e/settings/disable_sync_events.go | 1 - test/e2e/settings/enable_real_ip.go | 1 - 22 files changed, 123 insertions(+), 181 deletions(-) diff --git a/internal/ingress/annotations/annotations_test.go b/internal/ingress/annotations/annotations_test.go index 5df3cdc0ee..0c041cc2ca 100644 --- a/internal/ingress/annotations/annotations_test.go +++ b/internal/ingress/annotations/annotations_test.go @@ -133,7 +133,6 @@ func TestSSLPassthrough(t *testing.T) { ec := NewAnnotationExtractor(mockCfg{}) ing := buildIngress() - //nolint:goconst //already a constant fooAnns := []struct { annotations map[string]string er bool diff --git a/internal/ingress/annotations/parser/validators.go b/internal/ingress/annotations/parser/validators.go index 31524508f5..0be4d4fe33 100644 --- a/internal/ingress/annotations/parser/validators.go +++ b/internal/ingress/annotations/parser/validators.go @@ -49,8 +49,6 @@ var ( // IsValidRegex checks if the tested string can be used as a regex, but without any weird character. // It includes regex characters for paths that may contain regexes -// -//nolint:goconst //already a constant var IsValidRegex = regexp.MustCompile("^[/" + alphaNumericChars + regexEnabledChars + "]*$") // SizeRegex validates sizes understood by NGINX, like 1000, 100k, 1000M diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index dba8934594..9559790ed4 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -71,6 +71,7 @@ import ( const ( tempNginxPattern = "nginx-cfg" emptyUID = "-1" + goTemplateEngine = "go-template" ) // NewNGINXController creates a new NGINX Ingress controller. @@ -159,7 +160,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro } onTemplateChange := func() { - if config.ConfigurationTemplateEngine != "go-template" { + if config.ConfigurationTemplateEngine != goTemplateEngine { return } template, err := ngx_template.NewTemplate(nginx.TemplatePath) @@ -176,7 +177,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro var ngxTpl ngx_template.Writer switch config.ConfigurationTemplateEngine { - case "go-template": + case goTemplateEngine: ngxTpl, err = ngx_template.NewTemplate(nginx.TemplatePath) if err != nil { klog.Fatalf("Invalid NGINX configuration template: %v", err) @@ -887,7 +888,7 @@ func (n *NGINXController) configureDynamically(pcfg *ingress.Configuration) erro } } - if n.cfg.ConfigurationTemplateEngine == "go-template" { + if n.cfg.ConfigurationTemplateEngine == goTemplateEngine { streamConfigurationChanged := !reflect.DeepEqual(n.runningConfig.TCPEndpoints, pcfg.TCPEndpoints) || !reflect.DeepEqual(n.runningConfig.UDPEndpoints, pcfg.UDPEndpoints) if streamConfigurationChanged { err := updateStreamConfiguration(pcfg.TCPEndpoints, pcfg.UDPEndpoints) diff --git a/internal/ingress/controller/template/crossplane/authlocation.go b/internal/ingress/controller/template/crossplane/authlocation.go index 64c15eeb65..ef0dd8e179 100644 --- a/internal/ingress/controller/template/crossplane/authlocation.go +++ b/internal/ingress/controller/template/crossplane/authlocation.go @@ -124,39 +124,23 @@ func (c *Template) buildAuthLocation(server *ingress.Server, */ locationDirectives = append(locationDirectives, buildDirective("set", "$proxy_upstream_name", location.Backend), + buildDirective("proxy_pass_request_body", "off"), + buildDirective("proxy_ssl_server_name", "on"), + buildDirective("proxy_pass_request_headers", "on"), + buildDirective("proxy_set_header", "Content-Length", ""), + buildDirective("proxy_set_header", "X-Forwarded-Proto", ""), + buildDirective("proxy_set_header", "X-Request-ID", "$req_id"), + buildDirective("proxy_set_header", "Host", locationConfig.externalAuth.Host), + buildDirective("proxy_set_header", "X-Original-URL", "$scheme://$http_host$request_uri"), + buildDirective("proxy_set_header", "X-Original-Method", "$request_method"), + buildDirective("proxy_set_header", "X-Sent-From", "nginx-ingress-controller"), + buildDirective("proxy_set_header", "X-Real-IP", "$remote_addr"), ) - locationDirectives = append(locationDirectives, - buildDirective("proxy_pass_request_body", "off")) - - locationDirectives = append(locationDirectives, - buildDirective("proxy_ssl_server_name", "on")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_pass_request_headers", "on")) - - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "Content-Length", "")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Forwarded-Proto", "")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Request-ID", "$req_id")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "Host", locationConfig.externalAuth.Host)) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Original-URL", "$scheme://$http_host$request_uri")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Original-Method", "$request_method")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Sent-From", "nginx-ingress-controller")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Real-IP", "$remote_addr")) - if locationConfig.externalAuth.Method != "" { locationDirectives = append(locationDirectives, - buildDirective("proxy_method", locationConfig.externalAuth.Method)) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Original-URI", "$request_uri")) - locationDirectives = append(locationDirectives, + buildDirective("proxy_method", locationConfig.externalAuth.Method), + buildDirective("proxy_set_header", "X-Original-URI", "$request_uri"), buildDirective("proxy_set_header", "X-Scheme", "$pass_access_scheme")) } @@ -178,8 +162,7 @@ func (c *Template) buildAuthLocation(server *ingress.Server, if locationConfig.externalAuth.Method != "" { locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "X-Original-URI", "$request_uri")) - locationDirectives = append(locationDirectives, + buildDirective("proxy_set_header", "X-Original-URI", "$request_uri"), buildDirective("proxy_set_header", "X-Scheme", "$pass_access_scheme")) } @@ -192,11 +175,10 @@ func (c *Template) buildAuthLocation(server *ingress.Server, } locationDirectives = append(locationDirectives, - buildDirective("proxy_buffer_size", location.Proxy.BufferSize)) - locationDirectives = append(locationDirectives, - buildDirective("proxy_buffers", location.Proxy.BuffersNumber, location.Proxy.BufferSize)) - locationDirectives = append(locationDirectives, - buildDirective("proxy_request_buffering", location.Proxy.RequestBuffering)) + buildDirective("proxy_buffer_size", location.Proxy.BufferSize), + buildDirective("proxy_buffers", location.Proxy.BuffersNumber, location.Proxy.BufferSize), + buildDirective("proxy_request_buffering", location.Proxy.RequestBuffering), + ) if isValidByteSize(location.Proxy.BodySize, true) { locationDirectives = append(locationDirectives, @@ -210,13 +192,10 @@ func (c *Template) buildAuthLocation(server *ingress.Server, if server.CertificateAuth.CAFileName != "" { locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "ssl-client-verify", "$ssl_client_verify")) - - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "ssl-client-subject-dn", "$ssl_client_s_dn")) - - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "ssl-client-issuer-dn", "$ssl_client_i_dn")) + buildDirective("proxy_set_header", "ssl-client-verify", "$ssl_client_verify"), + buildDirective("proxy_set_header", "ssl-client-subject-dn", "$ssl_client_s_dn"), + buildDirective("proxy_set_header", "ssl-client-issuer-dn", "$ssl_client_i_dn"), + ) if server.CertificateAuth.PassCertToUpstream { locationDirectives = append(locationDirectives, @@ -231,16 +210,13 @@ func (c *Template) buildAuthLocation(server *ingress.Server, if locationConfig.applyAuthUpstream && locationConfig.applyGlobalAuth { locationDirectives = append(locationDirectives, - buildDirective("proxy_http_version", "1.1")) - locationDirectives = append(locationDirectives, - buildDirective("proxy_set_header", "Connection", "")) - locationDirectives = append(locationDirectives, + buildDirective("proxy_http_version", "1.1"), + buildDirective("proxy_set_header", "Connection", ""), buildDirective("set", "$target", changeHostPort(locationConfig.externalAuth.URL, buildAuthUpstreamName(location, server.Hostname)))) } else { locationDirectives = append(locationDirectives, - buildDirective("proxy_http_version", location.Proxy.ProxyHTTPVersion)) - locationDirectives = append(locationDirectives, + buildDirective("proxy_http_version", location.Proxy.ProxyHTTPVersion), buildDirective("set", "$target", locationConfig.externalAuth.URL)) } locationDirectives = append(locationDirectives, diff --git a/internal/ingress/controller/template/crossplane/cors.go b/internal/ingress/controller/template/crossplane/cors.go index 932c2489bf..932f25dbbc 100644 --- a/internal/ingress/controller/template/crossplane/cors.go +++ b/internal/ingress/controller/template/crossplane/cors.go @@ -35,12 +35,10 @@ func buildCorsDirectives(locationcors cors.Config) ngx_crossplane.Directives { buildDirective("set", "$cors", "${cors}options"), }, ), - ) - - directives = append(directives, commonCorsDirective(locationcors, false), commonCorsDirective(locationcors, true), ) + return directives } diff --git a/internal/ingress/controller/template/crossplane/crossplane_test.go b/internal/ingress/controller/template/crossplane/crossplane_test.go index 02c59035ef..c52077c757 100644 --- a/internal/ingress/controller/template/crossplane/crossplane_test.go +++ b/internal/ingress/controller/template/crossplane/crossplane_test.go @@ -87,12 +87,12 @@ func TestCrossplaneTemplate(t *testing.T) { ngx_crossplane.MatchHeadersMoreLatest, extramodules.BrotliMatchFn, extramodules.OpentelemetryMatchFn, + extramodules.SetMiscMatchFn, ngx_crossplane.MatchGeoip2Latest, }, LexOptions: ngx_crossplane.LexOptions{ Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()}, }, - IgnoreDirectives: []string{"set_escape_uri"}, } mimeFile, err := os.CreateTemp("", "") diff --git a/internal/ingress/controller/template/crossplane/extramodules/analyze.go b/internal/ingress/controller/template/crossplane/extramodules/analyze.go index 72efe24749..22d227d30d 100644 --- a/internal/ingress/controller/template/crossplane/extramodules/analyze.go +++ b/internal/ingress/controller/template/crossplane/extramodules/analyze.go @@ -22,8 +22,6 @@ limitations under the License. */ // This file is an extraction from https://github.com/nginxinc/nginx-go-crossplane/blob/main/analyze.go -// -//nolint:unused package extramodules // bit masks for different directive argument styles. diff --git a/internal/ingress/controller/template/crossplane/extramodules/setmisc.go b/internal/ingress/controller/template/crossplane/extramodules/setmisc.go index ab39ec5e84..fed384d469 100644 --- a/internal/ingress/controller/template/crossplane/extramodules/setmisc.go +++ b/internal/ingress/controller/template/crossplane/extramodules/setmisc.go @@ -14,48 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Code generated by generator; DO NOT EDIT. -// All the definitions are extracted from the source code -// Each bit mask describes these behaviors: -// - how many arguments the directive can take -// - whether or not it is a block directive -// - whether this is a flag (takes one argument that's either "on" or "off") -// - which contexts it's allowed to be in +// As opposite to the other files, this wasn't auto generated but hand crafted. +// Please do not change it package extramodules var setMiscDirectives = map[string][]uint{ - "set_base32_alphabet": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1, - }, - "set_base32_padding": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag, - }, - "set_decode_base32": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake12, - }, - "set_encode_base32": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake12, - }, - "set_formatted_gmt_time": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2, - }, - "set_formatted_local_time": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake2, - }, - "set_hashed_upstream": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake3, - }, - "set_local_today": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake1, - }, - "set_misc_base32_padding": { - ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfFlag, - }, + "set_escape_uri": { + ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPSifConf | ngxHTTPLocConf | ngxHTTPLifConf | ngxConfTake12, + }, } - func SetMiscMatchFn(directive string) ([]uint, bool) { - m, ok := setMiscDirectives[directive] - return m, ok + m, ok := setMiscDirectives[directive] + return m, ok } diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index 5da0b248a2..381ef67a43 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -113,8 +113,10 @@ func (c *Template) buildHTTP() { // HTTP2 Configuration if cfg.HTTP2MaxHeaderSize != "" && cfg.HTTP2MaxFieldSize != "" { - httpBlock = append(httpBlock, buildDirective("http2_max_field_size", cfg.HTTP2MaxFieldSize)) - httpBlock = append(httpBlock, buildDirective("http2_max_header_size", cfg.HTTP2MaxHeaderSize)) + httpBlock = append(httpBlock, + buildDirective("http2_max_field_size", cfg.HTTP2MaxFieldSize), + buildDirective("http2_max_header_size", cfg.HTTP2MaxHeaderSize), + ) } if cfg.HTTP2MaxRequests > 0 { @@ -122,13 +124,15 @@ func (c *Template) buildHTTP() { } if cfg.UseGzip { - httpBlock = append(httpBlock, buildDirective("gzip", "on")) - httpBlock = append(httpBlock, buildDirective("gzip_comp_level", cfg.GzipLevel)) - httpBlock = append(httpBlock, buildDirective("gzip_http_version", "1.1")) - httpBlock = append(httpBlock, buildDirective("gzip_min_length", cfg.GzipMinLength)) - httpBlock = append(httpBlock, buildDirective("gzip_types", strings.Split(cfg.GzipTypes, " "))) - httpBlock = append(httpBlock, buildDirective("gzip_proxied", "any")) - httpBlock = append(httpBlock, buildDirective("gzip_vary", "on")) + httpBlock = append(httpBlock, + buildDirective("gzip", "on"), + buildDirective("gzip_comp_level", cfg.GzipLevel), + buildDirective("gzip_http_version", "1.1"), + buildDirective("gzip_min_length", cfg.GzipMinLength), + buildDirective("gzip_types", strings.Split(cfg.GzipTypes, " ")), + buildDirective("gzip_proxied", "any"), + buildDirective("gzip_vary", "on"), + ) if cfg.GzipDisable != "" { httpBlock = append(httpBlock, buildDirective("gzip_disable", strings.Split(cfg.GzipDisable, " "))) @@ -346,29 +350,9 @@ func (c *Template) buildHTTP() { } } - /* - {{ range $server := $servers }} - {{ range $location := $server.Locations }} - {{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} - {{ $applyAuthUpstream := shouldApplyAuthUpstream $location $all.Cfg }} - {{ if and (eq $applyAuthUpstream true) (eq $applyGlobalAuth false) }} - ## start auth upstream {{ $server.Hostname }}{{ $location.Path }} - upstream {{ buildAuthUpstreamName $location $server.Hostname }} { - {{- $externalAuth := $location.ExternalAuth }} - server {{ extractHostPort $externalAuth.URL }}; - - keepalive {{ $externalAuth.KeepaliveConnections }}; - keepalive_requests {{ $externalAuth.KeepaliveRequests }}; - keepalive_timeout {{ $externalAuth.KeepaliveTimeout }}s; - } - ## end auth upstream {{ $server.Hostname }}{{ $location.Path }} - {{ end }} - {{ end }} - {{ end }} - */ for _, server := range c.tplConfig.Servers { for _, location := range server.Locations { - if shouldApplyAuthUpstream(location, cfg) && !shouldApplyGlobalAuth(location, cfg.GlobalExternalAuth.URL) { + if shouldApplyAuthUpstream(location, &cfg) && !shouldApplyGlobalAuth(location, cfg.GlobalExternalAuth.URL) { authUpstreamBlock := buildBlockDirective("upstream", []string{buildAuthUpstreamName(location, server.Hostname)}, ngx_crossplane.Directives{ buildDirective("server", extractHostPort(location.ExternalAuth.URL)), @@ -387,14 +371,17 @@ func (c *Template) buildHTTP() { } for _, server := range c.tplConfig.Servers { - httpBlock = append(httpBlock, buildStartServer(server.Hostname)) - serverBlock := c.buildServerDirective(server) - httpBlock = append(httpBlock, serverBlock) - httpBlock = append(httpBlock, buildEndServer(server.Hostname)) + httpBlock = append(httpBlock, + buildStartServer(server.Hostname), + c.buildServerDirective(server), + buildEndServer(server.Hostname), + ) } - httpBlock = append(httpBlock, c.buildDefaultBackend()) - httpBlock = append(httpBlock, c.buildHealthAndStatsServer()) + httpBlock = append(httpBlock, + c.buildDefaultBackend(), + c.buildHealthAndStatsServer(), + ) c.config.Parsed = append(c.config.Parsed, &ngx_crossplane.Directive{ Directive: "http", diff --git a/internal/ingress/controller/template/crossplane/location.go b/internal/ingress/controller/template/crossplane/location.go index e2a06f85e3..ddb28a7b19 100644 --- a/internal/ingress/controller/template/crossplane/location.go +++ b/internal/ingress/controller/template/crossplane/location.go @@ -173,7 +173,7 @@ func (c *Template) buildServerLocations(server *ingress.Server, locations []*ing proxySetHeader: getProxySetHeader(location), authPath: buildAuthLocation(location, cfg.GlobalExternalAuth.URL), applyGlobalAuth: shouldApplyGlobalAuth(location, cfg.GlobalExternalAuth.URL), - applyAuthUpstream: shouldApplyAuthUpstream(location, cfg), + applyAuthUpstream: shouldApplyAuthUpstream(location, &cfg), externalAuth: &externalAuth{}, } @@ -236,7 +236,7 @@ func (c *Template) buildLocation(server *ingress.Server, buildDirective("set", "$location_path", strings.ReplaceAll(ing.Path, `$`, `${literal_dollar}`)), } - locationDirectives = append(locationDirectives, locationConfigForLua(location, *c.tplConfig)...) + locationDirectives = append(locationDirectives, locationConfigForLua(location, c.tplConfig)...) locationDirectives = append(locationDirectives, buildCertificateDirectives(location)...) if cfg.Cfg.UseProxyProtocol { @@ -648,7 +648,7 @@ func buildRateLimit(loc *ingress.Location) ngx_crossplane.Directives { } // locationConfigForLua formats some location specific configuration into Lua table represented as string -func locationConfigForLua(location *ingress.Location, all config.TemplateConfig) ngx_crossplane.Directives { +func locationConfigForLua(location *ingress.Location, all *config.TemplateConfig) ngx_crossplane.Directives { /* Lua expects the following vars force_ssl_redirect = string_to_bool(ngx.var.force_ssl_redirect), ssl_redirect = string_to_bool(ngx.var.ssl_redirect), diff --git a/internal/ingress/controller/template/crossplane/server.go b/internal/ingress/controller/template/crossplane/server.go index 541e156f0f..c81003b0c3 100644 --- a/internal/ingress/controller/template/crossplane/server.go +++ b/internal/ingress/controller/template/crossplane/server.go @@ -56,7 +56,6 @@ func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane. if server.AuthTLSError != "" { serverBlock = append(serverBlock, buildDirective("return", 403)) } else { - serverBlock = append(serverBlock, c.buildCertificateDirectives(server)...) serverBlock = append(serverBlock, buildCustomErrorLocationsPerServer(server, c.tplConfig.EnableMetrics)...) serverBlock = append(serverBlock, buildMirrorLocationDirective(server.Locations)...) @@ -119,9 +118,10 @@ func (c *Template) buildCertificateDirectives(server *ingress.Server) ngx_crossp if server.CertificateAuth.CAFileName != "" { certAuth := server.CertificateAuth - certDirectives = append(certDirectives, buildDirective("ssl_client_certificate", certAuth.CAFileName)) - certDirectives = append(certDirectives, buildDirective("ssl_verify_client", certAuth.VerifyClient)) - certDirectives = append(certDirectives, buildDirective("ssl_verify_depth", certAuth.ValidationDepth)) + certDirectives = append(certDirectives, + buildDirective("ssl_client_certificate", certAuth.CAFileName), + buildDirective("ssl_verify_client", certAuth.VerifyClient), + buildDirective("ssl_verify_depth", certAuth.ValidationDepth)) if certAuth.CRLFileName != "" { certDirectives = append(certDirectives, buildDirective("ssl_crl", certAuth.CRLFileName)) } @@ -132,19 +132,22 @@ func (c *Template) buildCertificateDirectives(server *ingress.Server) ngx_crossp prxSSL := server.ProxySSL if prxSSL.CAFileName != "" { - certDirectives = append(certDirectives, buildDirective("proxy_ssl_trusted_certificate", prxSSL.CAFileName)) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_ciphers", prxSSL.Ciphers)) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_protocols", strings.Split(prxSSL.Protocols, " "))) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_verify", prxSSL.Verify)) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_verify_depth", prxSSL.VerifyDepth)) + certDirectives = append(certDirectives, buildDirective("proxy_ssl_trusted_certificate", prxSSL.CAFileName), + buildDirective("proxy_ssl_ciphers", prxSSL.Ciphers), + buildDirective("proxy_ssl_protocols", strings.Split(prxSSL.Protocols, " ")), + buildDirective("proxy_ssl_verify", prxSSL.Verify), + buildDirective("proxy_ssl_verify_depth", prxSSL.VerifyDepth), + ) if prxSSL.ProxySSLName != "" { - certDirectives = append(certDirectives, buildDirective("proxy_ssl_name", prxSSL.ProxySSLName)) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_server_name", prxSSL.ProxySSLServerName)) + certDirectives = append(certDirectives, + buildDirective("proxy_ssl_name", prxSSL.ProxySSLName), + buildDirective("proxy_ssl_server_name", prxSSL.ProxySSLServerName)) } } if prxSSL.PemFileName != "" { - certDirectives = append(certDirectives, buildDirective("proxy_ssl_certificate", prxSSL.PemFileName)) - certDirectives = append(certDirectives, buildDirective("proxy_ssl_certificate_key", prxSSL.PemFileName)) + certDirectives = append(certDirectives, + buildDirective("proxy_ssl_certificate", prxSSL.PemFileName), + buildDirective("proxy_ssl_certificate_key", prxSSL.PemFileName)) } if server.SSLCiphers != "" { certDirectives = append(certDirectives, buildDirective("ssl_ciphers", server.SSLCiphers)) @@ -191,11 +194,12 @@ func (c *Template) buildDefaultBackend() *ngx_crossplane.Directive { fmt.Sprintf("backlog=%d", c.tplConfig.BacklogSize), )) } - serverBlock = append(serverBlock, buildDirective("set", "$proxy_upstream_name", "internal")) - serverBlock = append(serverBlock, buildDirective("access_log", "off")) - serverBlock = append(serverBlock, buildBlockDirective("location", []string{"/"}, ngx_crossplane.Directives{ - buildDirective("return", "404"), - })) + serverBlock = append(serverBlock, + buildDirective("set", "$proxy_upstream_name", "internal"), + buildDirective("access_log", "off"), + buildBlockDirective("location", []string{"/"}, ngx_crossplane.Directives{ + buildDirective("return", "404"), + })) return &ngx_crossplane.Directive{ Directive: "server", @@ -228,8 +232,8 @@ func (c *Template) buildHealthAndStatsServer() *ngx_crossplane.Directive { buildBlockDirective( "location", []string{"/configuration"}, ngx_crossplane.Directives{ - buildDirective("client_max_body_size", luaConfigurationRequestBodySize(c.tplConfig.Cfg)), - buildDirective("client_body_buffer_size", luaConfigurationRequestBodySize(c.tplConfig.Cfg)), + buildDirective("client_max_body_size", luaConfigurationRequestBodySize(&c.tplConfig.Cfg)), + buildDirective("client_body_buffer_size", luaConfigurationRequestBodySize(&c.tplConfig.Cfg)), buildDirective("proxy_buffering", "off"), buildDirective("content_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_configuration.lua"), }), diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index ea0ade3c9b..74b09e6f07 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -289,7 +289,7 @@ func httpListener(addresses []string, co []string, tc *config.TemplateConfig, ss return listeners } -func luaConfigurationRequestBodySize(cfg config.Configuration) string { +func luaConfigurationRequestBodySize(cfg *config.Configuration) string { size := cfg.LuaSharedDicts["configuration_data"] if size < cfg.LuaSharedDicts["certificate_data"] { size = cfg.LuaSharedDicts["certificate_data"] @@ -347,7 +347,7 @@ func shouldApplyGlobalAuth(location *ingress.Location, globalExternalAuthURL str // shouldApplyAuthUpstream returns true only in case when ExternalAuth.URL and // ExternalAuth.KeepaliveConnections are all set -func shouldApplyAuthUpstream(location *ingress.Location, cfg config.Configuration) bool { +func shouldApplyAuthUpstream(location *ingress.Location, cfg *config.Configuration) bool { if location.ExternalAuth.URL == "" || location.ExternalAuth.KeepaliveConnections == 0 { return false } diff --git a/test/e2e/annotations/affinity.go b/test/e2e/annotations/affinity.go index d2adc86a5f..629277ddf1 100644 --- a/test/e2e/annotations/affinity.go +++ b/test/e2e/annotations/affinity.go @@ -58,7 +58,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -80,7 +81,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -115,7 +117,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -181,7 +184,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -212,7 +216,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) local, err := time.LoadLocation("GMT") @@ -243,7 +248,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -265,7 +271,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -289,7 +296,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -312,7 +320,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -431,7 +440,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -454,7 +464,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.HTTPTestClient(). @@ -476,7 +487,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + return (strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host))) && strings.Contains(server, "listen 443") }) diff --git a/test/e2e/annotations/affinitymode.go b/test/e2e/annotations/affinitymode.go index a49a767219..7b5f47c565 100644 --- a/test/e2e/annotations/affinitymode.go +++ b/test/e2e/annotations/affinitymode.go @@ -56,7 +56,8 @@ var _ = framework.DescribeAnnotation("affinitymode", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) // Check configuration @@ -89,7 +90,8 @@ var _ = framework.DescribeAnnotation("affinitymode", func() { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) // Check configuration diff --git a/test/e2e/annotations/auth.go b/test/e2e/annotations/auth.go index fd1734f354..5ecff23b43 100644 --- a/test/e2e/annotations/auth.go +++ b/test/e2e/annotations/auth.go @@ -419,7 +419,6 @@ http { f.EnsureIngress(ing2) f.WaitForNginxServer(host, func(server string) bool { - //nolint:goconst //server_name is a constant return strings.Contains(server, "server_name "+host) }) }) diff --git a/test/e2e/annotations/grpc.go b/test/e2e/annotations/grpc.go index 2a9c5a9835..049cf931d2 100644 --- a/test/e2e/annotations/grpc.go +++ b/test/e2e/annotations/grpc.go @@ -106,7 +106,6 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() { return strings.Contains(server, "grpc_pass grpc://upstream_balancer;") }) - //nolint:goconst //string interpolation conn, err := grpc.NewClient(f.GetNginxIP()+":443", grpc.WithTransportCredentials( credentials.NewTLS(&tls.Config{ diff --git a/test/e2e/annotations/limitconnections.go b/test/e2e/annotations/limitconnections.go index d44cb169c3..e660a233a8 100644 --- a/test/e2e/annotations/limitconnections.go +++ b/test/e2e/annotations/limitconnections.go @@ -41,7 +41,8 @@ var _ = framework.DescribeAnnotation("Annotation - limit-connections", func() { ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.SlowEchoService, 80, nil) f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) // limit connections diff --git a/test/e2e/annotations/upstreamhashby.go b/test/e2e/annotations/upstreamhashby.go index e5e3c5846e..43670c7174 100644 --- a/test/e2e/annotations/upstreamhashby.go +++ b/test/e2e/annotations/upstreamhashby.go @@ -36,7 +36,8 @@ func startIngress(f *framework.Framework, annotations map[string]string) map[str f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) //nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 02cc088164..b3eec60e76 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -321,7 +321,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b if name == "" { cmd = "cat /etc/nginx/nginx.conf" } else { - cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf | awk '/## start server %s;/,/## end server %s;/'", name, name) + cmd = fmt.Sprintf("cat /etc/nginx/nginx.conf | awk '/## start server %s/,/## end server %s/'", name, name) } o, err := f.ExecCommand(f.pod, cmd) diff --git a/test/e2e/framework/httpexpect/response.go b/test/e2e/framework/httpexpect/response.go index e324e94ffa..1c7624752c 100644 --- a/test/e2e/framework/httpexpect/response.go +++ b/test/e2e/framework/httpexpect/response.go @@ -234,7 +234,6 @@ func (r *HTTPResponse) checkContentType(expectedType string, expectedCharset ... } if mediaType != expectedType { - //nolint:goconst //string interpolation r.chain.fail("\nexpected \"Content-Type\" header with %q media type,"+ "\nbut got %q", expectedType, mediaType) return false diff --git a/test/e2e/settings/disable_sync_events.go b/test/e2e/settings/disable_sync_events.go index 0d55c96e48..033fd9194a 100644 --- a/test/e2e/settings/disable_sync_events.go +++ b/test/e2e/settings/disable_sync_events.go @@ -44,7 +44,6 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-sync-events", func() { return strings.Contains(server, fmt.Sprintf("server_name %v", host)) }) - //nolint:goconst //string interpolation events, err := f.KubeClientSet.CoreV1().Events(ing.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: "reason=Sync,involvedObject.name=" + host}) assert.Nil(ginkgo.GinkgoT(), err, "listing events") diff --git a/test/e2e/settings/enable_real_ip.go b/test/e2e/settings/enable_real_ip.go index bf16e1ea04..778011b9fa 100644 --- a/test/e2e/settings/enable_real_ip.go +++ b/test/e2e/settings/enable_real_ip.go @@ -47,7 +47,6 @@ var _ = framework.DescribeSetting("enable-real-ip", func() { f.WaitForNginxServer(host, func(server string) bool { - //nolint:goconst //already a const return strings.Contains(server, "server_name "+host) && !strings.Contains(server, "proxy_set_header X-Forwarded-Proto $full_x_forwarded_proto;") }) From 8eac53ca30178adbcac8c8098788cd1e00dbf0c2 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Wed, 13 Nov 2024 06:39:58 -0700 Subject: [PATCH 15/16] Fix test assertion --- test/e2e/lua/dynamic_configuration.go | 3 ++- test/e2e/metrics/metrics.go | 3 ++- test/e2e/settings/badannotationvalues.go | 12 ++++++++---- test/e2e/settings/limit_rate.go | 3 ++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/test/e2e/lua/dynamic_configuration.go b/test/e2e/lua/dynamic_configuration.go index 8f1deaeb12..a63a7a37d9 100644 --- a/test/e2e/lua/dynamic_configuration.go +++ b/test/e2e/lua/dynamic_configuration.go @@ -212,7 +212,8 @@ func createIngress(f *framework.Framework, host, deploymentName string) { f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + return (strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host))) && strings.Contains(server, "proxy_pass http://upstream_balancer;") }) } diff --git a/test/e2e/metrics/metrics.go b/test/e2e/metrics/metrics.go index 3cdb88057e..2100eefd2a 100644 --- a/test/e2e/metrics/metrics.go +++ b/test/e2e/metrics/metrics.go @@ -43,7 +43,8 @@ var _ = framework.IngressNginxDescribe("[metrics] exported prometheus metrics", f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + return (strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host))) && strings.Contains(server, "proxy_pass http://upstream_balancer;") }) }) diff --git a/test/e2e/settings/badannotationvalues.go b/test/e2e/settings/badannotationvalues.go index bee12e66a2..4459a8da8b 100644 --- a/test/e2e/settings/badannotationvalues.go +++ b/test/e2e/settings/badannotationvalues.go @@ -50,7 +50,8 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.WaitForNginxServer(host, @@ -87,7 +88,8 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.WaitForNginxServer(host, @@ -123,7 +125,8 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(hostValid, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", hostValid)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", hostValid)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", hostValid)) }) f.WaitForNginxServer(hostValid, @@ -156,7 +159,8 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() { f.WaitForNginxServer(host, func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return !strings.Contains(server, fmt.Sprintf("server_name %s;", host)) && + !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) f.WaitForNginxServer(host, diff --git a/test/e2e/settings/limit_rate.go b/test/e2e/settings/limit_rate.go index 16ce982778..41c54da852 100644 --- a/test/e2e/settings/limit_rate.go +++ b/test/e2e/settings/limit_rate.go @@ -41,7 +41,8 @@ var _ = framework.DescribeSetting("Configmap - limit-rate", func() { f.EnsureIngress(ing) f.WaitForNginxServer(host, func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) + return strings.Contains(server, fmt.Sprintf("server_name %s;", host)) || + strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) }) wlKey := "limit-rate" From 065ec63e8b3de2ad6eeef9c74c568092f98ef2d7 Mon Sep 17 00:00:00 2001 From: Ricardo Katz Date: Wed, 13 Nov 2024 09:55:45 -0700 Subject: [PATCH 16/16] Fix golang-lint findings --- .golangci.yml | 1 - go.work.sum | 9 +++++ .../ingress/controller/controller_test.go | 2 +- .../template/crossplane/authlocation.go | 3 +- .../controller/template/crossplane/cors.go | 5 ++- .../crossplane/extramodules/analyze.go | 2 ++ .../controller/template/crossplane/http.go | 30 ++++++++-------- .../template/crossplane/location.go | 35 ++++--------------- .../controller/template/crossplane/server.go | 6 ++-- .../controller/template/crossplane/utils.go | 27 +++++++------- .../ingress/controller/template/template.go | 2 +- test/e2e/annotations/canary.go | 1 - test/e2e/annotations/cors.go | 1 - test/e2e/settings/proxy_host.go | 2 -- 14 files changed, 55 insertions(+), 71 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2d73e14e77..feaf26b285 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,6 @@ linters: - errname - ginkgolinter - gocheckcompilerdirectives - - goconst - gocritic - gocyclo - godox diff --git a/go.work.sum b/go.work.sum index 257e3fa78e..67a15a2d82 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,4 +1,5 @@ cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= @@ -20,6 +21,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= @@ -109,11 +111,18 @@ go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8 go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= k8s.io/kms v0.31.2/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= diff --git a/internal/ingress/controller/controller_test.go b/internal/ingress/controller/controller_test.go index a830a57294..022f23e8eb 100644 --- a/internal/ingress/controller/controller_test.go +++ b/internal/ingress/controller/controller_test.go @@ -157,7 +157,7 @@ func (ntc testNginxTestCommand) Test(cfg string) ([]byte, error) { type fakeTemplate struct{} -func (fakeTemplate) Validate(filename string) error { +func (fakeTemplate) Validate(_ string) error { return nil } diff --git a/internal/ingress/controller/template/crossplane/authlocation.go b/internal/ingress/controller/template/crossplane/authlocation.go index ef0dd8e179..113f288785 100644 --- a/internal/ingress/controller/template/crossplane/authlocation.go +++ b/internal/ingress/controller/template/crossplane/authlocation.go @@ -86,7 +86,8 @@ func buildExternalAuth(cfg any) *externalAuth { } func (c *Template) buildAuthLocation(server *ingress.Server, - location *ingress.Location, locationConfig locationCfg) *ngx_crossplane.Directive { + location *ingress.Location, locationConfig locationCfg, +) *ngx_crossplane.Directive { locationDirectives := ngx_crossplane.Directives{ buildDirective("internal"), } diff --git a/internal/ingress/controller/template/crossplane/cors.go b/internal/ingress/controller/template/crossplane/cors.go index 932f25dbbc..252fa17029 100644 --- a/internal/ingress/controller/template/crossplane/cors.go +++ b/internal/ingress/controller/template/crossplane/cors.go @@ -23,11 +23,10 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/cors" ) -func buildCorsDirectives(locationcors cors.Config) ngx_crossplane.Directives { +func buildCorsDirectives(locationcors *cors.Config) ngx_crossplane.Directives { directives := make(ngx_crossplane.Directives, 0) if len(locationcors.CorsAllowOrigin) > 0 { directives = append(directives, buildCorsOriginRegex(locationcors.CorsAllowOrigin)...) - } directives = append(directives, buildBlockDirective("if", @@ -43,7 +42,7 @@ func buildCorsDirectives(locationcors cors.Config) ngx_crossplane.Directives { } // commonCorsDirective builds the common cors directives for a location -func commonCorsDirective(cfg cors.Config, options bool) *ngx_crossplane.Directive { +func commonCorsDirective(cfg *cors.Config, options bool) *ngx_crossplane.Directive { corsDir := "true" if options { corsDir = "trueoptions" diff --git a/internal/ingress/controller/template/crossplane/extramodules/analyze.go b/internal/ingress/controller/template/crossplane/extramodules/analyze.go index 22d227d30d..0b6d2f335a 100644 --- a/internal/ingress/controller/template/crossplane/extramodules/analyze.go +++ b/internal/ingress/controller/template/crossplane/extramodules/analyze.go @@ -70,6 +70,8 @@ const ( // helpful directive location alias describing "any" context // doesn't include ngxHTTPSifConf, ngxHTTPLifConf, ngxHTTPLmtConf, or ngxMgmtMainConf. +// +//nolint:unused // This file is generated const ngxAnyConf = ngxMainConf | ngxEventConf | ngxMailMainConf | ngxMailSrvConf | ngxStreamMainConf | ngxStreamSrvConf | ngxStreamUpsConf | ngxHTTPMainConf | ngxHTTPSrvConf | ngxHTTPLocConf | ngxHTTPUpsConf | diff --git a/internal/ingress/controller/template/crossplane/http.go b/internal/ingress/controller/template/crossplane/http.go index 381ef67a43..02ff72c9aa 100644 --- a/internal/ingress/controller/template/crossplane/http.go +++ b/internal/ingress/controller/template/crossplane/http.go @@ -85,7 +85,7 @@ func (c *Template) initHTTPDirectives() ngx_crossplane.Directives { return httpBlock } -//nolint:gocyclo +//nolint:gocyclo // Function is what it is func (c *Template) buildHTTP() { cfg := c.tplConfig.Cfg httpBlock := c.initHTTPDirectives() @@ -140,10 +140,10 @@ func (c *Template) buildHTTP() { } if cfg.EnableBrotli { - httpBlock = append(httpBlock, buildDirective("brotli", "on")) - httpBlock = append(httpBlock, buildDirective("brotli_comp_level", cfg.BrotliLevel)) - httpBlock = append(httpBlock, buildDirective("brotli_min_length", cfg.BrotliMinLength)) - httpBlock = append(httpBlock, buildDirective("brotli_types", cfg.BrotliTypes)) + httpBlock = append(httpBlock, buildDirective("brotli", "on"), + buildDirective("brotli_comp_level", cfg.BrotliLevel), + buildDirective("brotli_min_length", cfg.BrotliMinLength), + buildDirective("brotli_types", cfg.BrotliTypes)) } if (c.tplConfig.Cfg.EnableOpentelemetry || shouldLoadOpentelemetryModule(c.tplConfig.Servers)) && @@ -293,16 +293,17 @@ func (c *Template) buildHTTP() { httpBlock = append(httpBlock, buildBlockDirective("upstream", []string{"upstream_balancer"}, blockUpstreamDirectives)) // Adding Rate limit - for _, rl := range filterRateLimits(c.tplConfig.Servers) { - id := fmt.Sprintf("$allowlist_%s", rl.ID) - httpBlock = append(httpBlock, buildDirective("#", "Ratelimit", rl.Name)) + rl := filterRateLimits(c.tplConfig.Servers) + for i := range rl { + id := fmt.Sprintf("$allowlist_%s", rl[i].ID) + httpBlock = append(httpBlock, buildDirective("#", "Ratelimit", rl[i].Name)) rlDirectives := ngx_crossplane.Directives{ buildDirective("default", 0), } - for _, ip := range rl.Allowlist { + for _, ip := range rl[i].Allowlist { rlDirectives = append(rlDirectives, buildDirective(ip, "1")) } - mapRateLimitDirective := buildMapDirective(id, fmt.Sprintf("$limit_%s", rl.ID), ngx_crossplane.Directives{ + mapRateLimitDirective := buildMapDirective(id, fmt.Sprintf("$limit_%s", rl[i].ID), ngx_crossplane.Directives{ buildDirective("0", cfg.LimitConnZoneVariable), buildDirective("1", ""), }) @@ -343,10 +344,11 @@ func (c *Template) buildHTTP() { if redirectServers, ok := c.tplConfig.RedirectServers.([]*utilingress.Redirect); ok { for _, server := range redirectServers { - httpBlock = append(httpBlock, buildStartServer(server.From)) - serverBlock := c.buildRedirectServer(server) - httpBlock = append(httpBlock, serverBlock) - httpBlock = append(httpBlock, buildEndServer(server.From)) + httpBlock = append(httpBlock, + buildStartServer(server.From), + c.buildRedirectServer(server), + buildEndServer(server.From), + ) } } diff --git a/internal/ingress/controller/template/crossplane/location.go b/internal/ingress/controller/template/crossplane/location.go index ddb28a7b19..bc7c5685ed 100644 --- a/internal/ingress/controller/template/crossplane/location.go +++ b/internal/ingress/controller/template/crossplane/location.go @@ -107,7 +107,6 @@ func buildCustomErrorLocationsPerServer(server *ingress.Server, enableMetrics bo errorLocationsDirectives = append(errorLocationsDirectives, buildCustomErrorLocation(errorLocations[i].UpstreamName, errorLocations[i].Codes, enableMetrics)...) } return errorLocationsDirectives - } func buildCustomErrorLocation(upstreamName string, errorCodes []int, enableMetrics bool) ngx_crossplane.Directives { @@ -199,7 +198,7 @@ func (c *Template) buildServerLocations(server *ingress.Server, locations []*ing buildDirective("add_header", "Set-Cookie", "$auth_cookie"), } if location.CorsConfig.CorsEnabled { - directives = append(directives, buildCorsDirectives(location.CorsConfig)...) + directives = append(directives, buildCorsDirectives(&location.CorsConfig)...) } directives = append(directives, buildDirective("return", @@ -208,17 +207,15 @@ func (c *Template) buildServerLocations(server *ingress.Server, locations []*ing serverLocations = append(serverLocations, buildBlockDirective("location", []string{buildAuthSignURLLocation(location.Path, locationConfig.externalAuth.SigninURL)}, directives)) - } serverLocations = append(serverLocations, c.buildLocation(server, location, locationConfig)) - } - return serverLocations } func (c *Template) buildLocation(server *ingress.Server, - location *ingress.Location, locationConfig locationCfg) *ngx_crossplane.Directive { + location *ingress.Location, locationConfig locationCfg, +) *ngx_crossplane.Directive { ing := getIngressInformation(location.Ingress, server.Hostname, location.IngressPath) cfg := c.tplConfig locationDirectives := ngx_crossplane.Directives{ @@ -294,7 +291,7 @@ func (c *Template) buildAllowedLocation(server *ingress.Server, location *ingres } if location.CorsConfig.CorsEnabled { - dir = append(dir, buildCorsDirectives(location.CorsConfig)...) + dir = append(dir, buildCorsDirectives(&location.CorsConfig)...) } if !isLocationInLocationList(location, c.tplConfig.Cfg.NoAuthLocations) { @@ -686,8 +683,8 @@ func buildAuthLocationConfig(location *ingress.Location, locationConfig location directives := make(ngx_crossplane.Directives, 0) if locationConfig.authPath != "" { if locationConfig.applyAuthUpstream && !locationConfig.applyGlobalAuth { - directives = append(directives, buildDirective("set", "$auth_cookie", "")) - directives = append(directives, buildDirective("add_header", "Set-Cookie", "$auth_cookie")) + directives = append(directives, buildDirective("set", "$auth_cookie", ""), + buildDirective("add_header", "Set-Cookie", "$auth_cookie")) directives = append(directives, buildAuthResponseHeaders(locationConfig.proxySetHeader, locationConfig.externalAuth.ResponseHeaders, true)...) if len(locationConfig.externalAuth.ResponseHeaders) > 0 { directives = append(directives, buildDirective("set", "$auth_response_headers", strings.Join(locationConfig.externalAuth.ResponseHeaders, ","))) @@ -733,24 +730,4 @@ func buildAuthLocationConfig(location *ingress.Location, locationConfig location } return directives - /* - Missing this Lua script - # `auth_request` module does not support HTTP keepalives in upstream block: - # https://trac.nginx.org/nginx/ticket/1579 - access_by_lua_block { - local res = ngx.location.capture('{{ $authPath }}', { method = ngx.HTTP_GET, body = '', share_all_vars = {{ $externalAuth.KeepaliveShareVars }} }) - if res.status == ngx.HTTP_OK then - ngx.var.auth_cookie = res.header['Set-Cookie'] - {{- range $line := buildAuthUpstreamLuaHeaders $externalAuth.ResponseHeaders }} # IF 4 - {{ $line }} - {{- end }} # END IF 4 - return - end - if res.status == ngx.HTTP_UNAUTHORIZED or res.status == ngx.HTTP_FORBIDDEN then - ngx.exit(res.status) - end - ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) - } - - */ } diff --git a/internal/ingress/controller/template/crossplane/server.go b/internal/ingress/controller/template/crossplane/server.go index c81003b0c3..a78a5a351a 100644 --- a/internal/ingress/controller/template/crossplane/server.go +++ b/internal/ingress/controller/template/crossplane/server.go @@ -37,7 +37,7 @@ func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane. buildDirective("ssl_certificate_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_certificate.lua"), } - serverBlock = append(serverBlock, buildListener(*c.tplConfig, server.Hostname)...) + serverBlock = append(serverBlock, buildListener(c.tplConfig, server.Hostname)...) serverBlock = append(serverBlock, c.buildBlockers()...) if server.Hostname == "_" { @@ -62,7 +62,6 @@ func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane. // The other locations should come here! serverBlock = append(serverBlock, c.buildServerLocations(server, server.Locations)...) - } // "/healthz" location @@ -101,7 +100,6 @@ func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane. // End of "nginx_status" location serverBlock = append(serverBlock, buildBlockDirective("location", []string{"/nginx_status"}, statusLocationDirs)) - } // DO NOT MOVE! THIS IS THE END DIRECTIVE OF SERVERS @@ -167,7 +165,7 @@ func (c *Template) buildRedirectServer(server *utilingress.Redirect) *ngx_crossp buildDirective("ssl_certificate_by_lua_file", "/etc/nginx/lua/nginx/ngx_conf_certificate.lua"), buildDirective("set_by_lua_file", "$redirect_to", "/etc/nginx/lua/nginx/ngx_srv_redirect.lua", server.To), } - serverBlock = append(serverBlock, buildListener(*c.tplConfig, server.From)...) + serverBlock = append(serverBlock, buildListener(c.tplConfig, server.From)...) serverBlock = append(serverBlock, c.buildBlockers()...) serverBlock = append(serverBlock, buildDirective("return", c.tplConfig.Cfg.HTTPRedirectCode, "$redirect_to")) diff --git a/internal/ingress/controller/template/crossplane/utils.go b/internal/ingress/controller/template/crossplane/utils.go index 74b09e6f07..eef9b87ca2 100644 --- a/internal/ingress/controller/template/crossplane/utils.go +++ b/internal/ingress/controller/template/crossplane/utils.go @@ -17,7 +17,7 @@ limitations under the License. package crossplane import ( - "crypto/sha1" + "crypto/sha1" //nolint:gosec // We cannot move away from sha1 "encoding/base64" "encoding/hex" "fmt" @@ -59,10 +59,12 @@ var ( defaultGlobalAuthRedirectParam = "rd" ) -type seconds int -type minutes int +type ( + seconds int + minutes int +) -func buildDirectiveWithComment(directive string, comment string, args ...any) *ngx_crossplane.Directive { +func buildDirectiveWithComment(directive, comment string, args ...any) *ngx_crossplane.Directive { dir := buildDirective(directive, args...) dir.Comment = ptr.To(comment) return dir @@ -213,25 +215,25 @@ func buildServerName(hostname string) string { return `~^(?[\w-]+)\.` + strings.Join(parts, "\\.") + `$` } -func buildListener(tc config.TemplateConfig, hostname string) ngx_crossplane.Directives { +func buildListener(tc *config.TemplateConfig, hostname string) ngx_crossplane.Directives { listenDirectives := make(ngx_crossplane.Directives, 0) - co := commonListenOptions(&tc, hostname) + co := commonListenOptions(tc, hostname) addrV4 := []string{""} if len(tc.Cfg.BindAddressIpv4) > 0 { addrV4 = tc.Cfg.BindAddressIpv4 } - listenDirectives = append(listenDirectives, httpListener(addrV4, co, &tc, false)...) - listenDirectives = append(listenDirectives, httpListener(addrV4, co, &tc, true)...) + listenDirectives = append(listenDirectives, httpListener(addrV4, co, tc, false)...) + listenDirectives = append(listenDirectives, httpListener(addrV4, co, tc, true)...) if tc.IsIPV6Enabled { addrV6 := []string{"[::]"} if len(tc.Cfg.BindAddressIpv6) > 0 { addrV6 = tc.Cfg.BindAddressIpv6 } - listenDirectives = append(listenDirectives, httpListener(addrV6, co, &tc, false)...) - listenDirectives = append(listenDirectives, httpListener(addrV6, co, &tc, true)...) + listenDirectives = append(listenDirectives, httpListener(addrV6, co, tc, false)...) + listenDirectives = append(listenDirectives, httpListener(addrV6, co, tc, true)...) } return listenDirectives @@ -258,7 +260,7 @@ func commonListenOptions(template *config.TemplateConfig, hostname string) []str return out } -func httpListener(addresses []string, co []string, tc *config.TemplateConfig, ssl bool) ngx_crossplane.Directives { +func httpListener(addresses, co []string, tc *config.TemplateConfig, ssl bool) ngx_crossplane.Directives { listeners := make(ngx_crossplane.Directives, 0) port := tc.ListenPorts.HTTP isTLSProxy := tc.IsSSLPassthroughEnabled @@ -400,7 +402,7 @@ func changeHostPort(newURL, value string) string { } func buildAuthSignURLLocation(location, authSignURL string) string { - hasher := sha1.New() // #nosec + hasher := sha1.New() //nolint:gosec // We cannot move away from sha1 hasher.Write([]byte(location)) hasher.Write([]byte(authSignURL)) return "@" + hex.EncodeToString(hasher.Sum(nil)) @@ -558,7 +560,6 @@ func buildProxyPass(backends []*ingress.Backend, location *ingress.Location) ngx } func buildGeoIPDirectives(reloadTime int, files []string) ngx_crossplane.Directives { - directives := make(ngx_crossplane.Directives, 0) buildGeoIPBlock := func(file string, directives ngx_crossplane.Directives) *ngx_crossplane.Directive { if reloadTime > 0 && file != "GeoIP2-Connection-Type.mmdb" { diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index e420b9bcfb..b976ec142a 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -234,7 +234,7 @@ type LuaListenPorts struct { } // Validate is no-op at go-template -func (t *Template) Validate(filename string) error { +func (t *Template) Validate(_ string) error { return nil } diff --git a/test/e2e/annotations/canary.go b/test/e2e/annotations/canary.go index 443a3a486e..3632ed6967 100644 --- a/test/e2e/annotations/canary.go +++ b/test/e2e/annotations/canary.go @@ -1106,7 +1106,6 @@ var _ = framework.DescribeAnnotation("canary-*", func() { !strings.Contains(server, `set $proxy_upstream_name "pstream-default-backend;`) && !strings.Contains(server, canaryUpstreamNameCrossplane) && strings.Contains(server, upstreamNameCrossplane)) - }) }) diff --git a/test/e2e/annotations/cors.go b/test/e2e/annotations/cors.go index 1db7d53741..57206b2e67 100644 --- a/test/e2e/annotations/cors.go +++ b/test/e2e/annotations/cors.go @@ -86,7 +86,6 @@ var _ = framework.DescribeAnnotation("cors-*", func() { func(server string) bool { return strings.Contains(server, "more_set_headers 'Access-Control-Allow-Methods: POST, GET';") || strings.Contains(server, `more_set_headers "Access-Control-Allow-Methods: POST, GET";`) - }) }) diff --git a/test/e2e/settings/proxy_host.go b/test/e2e/settings/proxy_host.go index 1fcda11a13..afb37c372c 100644 --- a/test/e2e/settings/proxy_host.go +++ b/test/e2e/settings/proxy_host.go @@ -34,7 +34,6 @@ var _ = framework.IngressNginxDescribe("Dynamic $proxy_host", func() { }) ginkgo.It("should exist a proxy_host", func() { - h := make(map[string]string) h["Custom-Header"] = "$proxy_host" cfgMap := "add-headers-configmap" @@ -60,7 +59,6 @@ var _ = framework.IngressNginxDescribe("Dynamic $proxy_host", func() { }) ginkgo.It("should exist a proxy_host using the upstream-vhost annotation value", func() { - h := make(map[string]string) h["Custom-Header"] = "$proxy_host" cfgMap := "add-headers-configmap"