From dde05a91fdf4ae2c6523fbb12e79f931acf2f223 Mon Sep 17 00:00:00 2001 From: sh2 Date: Thu, 25 Apr 2024 14:56:39 +0800 Subject: [PATCH 01/29] refactor: remove explicit test case definition for xds translator test (#3230) * remove explicit test case definition for xds translator test Signed-off-by: shawnh2 * fix lint and gen-check Signed-off-by: shawnh2 * check secret from translator context Signed-off-by: shawnh2 --------- Signed-off-by: shawnh2 --- .../in/xds-ir/mixed-tls-jwt-authn.yaml | 11 +- .../listener-proxy-protocol.secrets.yaml | 12 + .../xds-ir/mixed-tls-jwt-authn.clusters.yaml | 36 +- .../xds-ir/mixed-tls-jwt-authn.endpoints.yaml | 3 +- .../xds-ir/mixed-tls-jwt-authn.listeners.yaml | 23 +- .../xds-ir/mixed-tls-jwt-authn.routes.yaml | 6 +- ...e-port-with-different-filters.secrets.yaml | 8 + .../suppress-envoy-headers.secrets.yaml | 12 + .../tcp-route-tls-terminate.secrets.yaml | 6 + ...ls-with-ciphers-versions-alpn.secrets.yaml | 12 + internal/xds/translator/translator_test.go | 590 ++++-------------- 11 files changed, 198 insertions(+), 521 deletions(-) create mode 100644 internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml diff --git a/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml b/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml index 36984ea69f6..e77e1262245 100644 --- a/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/mixed-tls-jwt-authn.yaml @@ -8,11 +8,12 @@ http: mergeSlashes: true escapedSlashesAction: UnescapeAndRedirect tls: - - name: first-listener - # byte slice representation of "cert-data" - serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] - # byte slice representation of "key-data" - privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + certificates: + - name: first-listener + # byte slice representation of "cert-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] routes: - name: "first-route" hostname: "*" diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml index 7a0c933174e..d53a7a1b2ce 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.clusters.yaml @@ -1,4 +1,7 @@ -- commonLbConfig: +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: localityWeightedLbConfig: {} connectTimeout: 10s dnsLookupFamily: V4_ONLY @@ -12,34 +15,3 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS -- commonLbConfig: - localityWeightedLbConfig: {} - connectTimeout: 10s - dnsLookupFamily: V4_ONLY - dnsRefreshRate: 30s - lbPolicy: LEAST_REQUEST - loadAssignment: - clusterName: localhost_443 - endpoints: - - lbEndpoints: - - endpoint: - address: - socketAddress: - address: localhost - portValue: 443 - loadBalancingWeight: 1 - loadBalancingWeight: 1 - locality: {} - name: localhost_443 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 - respectDnsTtl: true - transportSocket: - name: envoy.transport_sockets.tls - typedConfig: - '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext - commonTlsContext: - validationContext: - trustedCa: - filename: /etc/ssl/certs/ca-certificates.crt - type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml index 0d68b430c20..3b3f2d09076 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.endpoints.yaml @@ -8,4 +8,5 @@ portValue: 50000 loadBalancingWeight: 1 loadBalancingWeight: 1 - locality: {} + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml index 85bb8b4ac73..5fa3f9246df 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -14,26 +15,6 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: - - name: envoy.filters.http.jwt_authn - typedConfig: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication - providers: - first-route/example: - audiences: - - foo.com - issuer: https://www.example.com - payloadInMetadata: https://www.example.com - remoteJwks: - asyncFetch: {} - cacheDuration: 300s - httpUri: - cluster: localhost_443 - timeout: 5s - uri: https://localhost/jwt/public-key/jwks.json - retryPolicy: {} - requirementMap: - first-route: - providerName: first-route/example - name: envoy.filters.http.router typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router @@ -48,8 +29,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml index c73bec09093..75d30a0592a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.routes.yaml @@ -10,7 +10,5 @@ name: first-route route: cluster: first-route-dest - typedPerFilterConfig: - envoy.filters.http.jwt_authn: - '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig - requirementName: first-route + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml new file mode 100644 index 00000000000..81afea10735 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port-with-different-filters.secrets.yaml @@ -0,0 +1,8 @@ +- genericSecret: + secret: + inlineBytes: Y2xpZW50MTpzZWNyZXQK + name: oauth2/client_secret/securitypolicy/default/policy-for-gateway-2 +- genericSecret: + secret: + inlineBytes: "" + name: oauth2/hmac_secret/securitypolicy/default/policy-for-gateway-2 diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml new file mode 100644 index 00000000000..d4d502ac098 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.secrets.yaml @@ -0,0 +1,6 @@ +- name: envoy-gateway-tls-secret-1 + tlsCertificate: + certificateChain: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + privateKey: + inlineBytes: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index da07465099f..28868500b68 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -41,325 +41,96 @@ var ( overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") ) -func TestTranslateXds(t *testing.T) { - testCases := []struct { - name string - dnsDomain string - requireSecrets bool - requireEnvoyPatchPolicies bool - err bool - }{ - { - name: "empty", - }, - { - name: "http-route", - }, - { - name: "http-route-regex", - }, - { - name: "http-route-redirect", - }, - { - name: "http-route-mirror", - }, - { - name: "http-route-multiple-mirrors", - }, - { - name: "http-route-multiple-matches", - }, - { - name: "http-route-direct-response", - }, - { - name: "http-route-request-headers", - }, - { - name: "http-route-response-add-headers", - }, - { - name: "http-route-response-remove-headers", - }, - { - name: "http-route-response-add-remove-headers", - }, - { - name: "http-route-weighted-invalid-backend", - }, - { - name: "http-route-dns-cluster", - }, - { - name: "http-route-with-tls-system-truststore", - requireSecrets: true, - }, - { - name: "http-route-with-tlsbundle", - requireSecrets: true, - }, - { - name: "http-route-with-tlsbundle-multiple-certs", - requireSecrets: true, - }, - { - name: "simple-tls", - requireSecrets: true, - }, - { - name: "mutual-tls", - requireSecrets: true, - }, - { - name: "mutual-tls-required-client-certificate-disabled", - requireSecrets: true, - }, - { - name: "http3", - requireSecrets: true, - }, - { - name: "tls-route-passthrough", - }, - { - name: "tcp-route-simple", - }, - { - name: "tcp-route-complex", - }, - { - name: "tcp-route-tls-terminate", - }, - { - name: "multiple-simple-tcp-route-same-port", - }, - { - name: "http-route-weighted-backend", - }, - { - name: "tcp-route-weighted-backend", - }, - { - name: "multiple-listeners-same-port", - requireSecrets: true, - }, - { - name: "udp-route", - }, - { - name: "http2-route", - }, - { - name: "http-route-rewrite-url-prefix", - }, - { - name: "http-route-rewrite-root-path-url-prefix", - }, - { - name: "http-route-rewrite-url-fullpath", - }, - { - name: "http-route-rewrite-url-host", - }, - { - name: "http-route-timeout", - }, +type testFileConfig struct { + requireEnvoyPatchPolicies bool + dnsDomain string + errMsg string +} - { - name: "ratelimit", - }, - { - name: "ratelimit-custom-domain", +func TestTranslateXds(t *testing.T) { + testConfigs := map[string]testFileConfig{ + "ratelimit-custom-domain": { dnsDomain: "example-cluster.local", }, - { - name: "ratelimit-sourceip", - }, - { - name: "accesslog", - }, - { - name: "tracing", - }, - { - name: "metrics-virtual-host", - }, - { - name: "jsonpatch", + "jsonpatch": { requireEnvoyPatchPolicies: true, - requireSecrets: true, - err: true, }, - { - name: "jsonpatch-missing-resource", + "jsonpatch-missing-resource": { requireEnvoyPatchPolicies: true, - err: true, }, - { - name: "jsonpatch-invalid-patch", + "jsonpatch-invalid-patch": { requireEnvoyPatchPolicies: true, - err: true, + errMsg: "unable to unmarshal xds resource", }, - { - name: "jsonpatch-add-op-without-value", + "jsonpatch-add-op-without-value": { requireEnvoyPatchPolicies: true, - err: true, + errMsg: "the add operation requires a value", }, - { - name: "jsonpatch-move-op-with-value", + "jsonpatch-move-op-with-value": { requireEnvoyPatchPolicies: true, - err: true, - }, - { - name: "listener-tcp-keepalive", - }, - { - name: "load-balancer", - }, - { - name: "cors", - }, - { - name: "jwt-multi-route-multi-provider", - }, - { - name: "jwt-multi-route-single-provider", - }, - { - name: "jwt-ratelimit", - }, - { - name: "jwt-single-route-single-match", - }, - { - name: "oidc", - requireSecrets: true, - }, - { - name: "http-route-partial-invalid", - }, - { - name: "listener-proxy-protocol", - }, - { - name: "jwt-custom-extractor", - }, - { - name: "proxy-protocol-upstream", - }, - { - name: "basic-auth", - }, - { - name: "health-check", - }, - { - name: "local-ratelimit", - }, - { - name: "circuit-breaker", - }, - { - name: "suppress-envoy-headers", - }, - { - name: "fault-injection", - }, - { - name: "headers-with-underscores-action", - }, - { - name: "tls-with-ciphers-versions-alpn", - }, - { - name: "path-settings", - }, - { - name: "client-ip-detection", + errMsg: "the value field can not be set for the remove operation", }, - { - name: "http1-trailers", + "http-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "http1-preserve-case", + "tcp-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "timeout", + "tcp-route-invalid-endpoint": { + errMsg: "validation failed for xds resource", }, - { - name: "ext-auth", + "udp-route-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "http10", + "jsonpatch-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "upstream-tcpkeepalive", + "jsonpatch-invalid-listener": { + errMsg: "validation failed for xds resource", }, - { - name: "client-timeout", + "accesslog-invalid": { + errMsg: "validation failed for xds resource", }, - { - name: "client-buffer-limit", - }, - { - name: "retry-partial-invalid", - }, - { - name: "multiple-listeners-same-port-with-different-filters", - }, - { - name: "listener-connection-limit", - }, - { - name: "ext-proc", - }, - { - name: "http-endpoint-stats", - }, - { - name: "tcp-endpoint-stats", - }, - { - name: "udp-endpoint-stats", - }, - { - name: "tracing-endpoint-stats", - }, - { - name: "accesslog-endpoint-stats", - }, - { - name: "ratelimit-endpoint-stats", - }, - { - name: "wasm", - }, - { - name: "jwt-optional", - }, - { - name: "http2", + "tracing-invalid": { + errMsg: "validation failed for xds resource", }, } - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - dnsDomain := tc.dnsDomain - if dnsDomain == "" { + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "xds-ir", "*.yaml")) + require.NoError(t, err) + + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + cfg, ok := testConfigs[inputFileName] + if !ok { + cfg = testFileConfig{ + requireEnvoyPatchPolicies: false, + dnsDomain: "", + errMsg: "", + } + } + + dnsDomain := cfg.dnsDomain + if len(dnsDomain) == 0 { dnsDomain = "cluster.local" } - ir := requireXdsIRFromInputTestData(t, "xds-ir", tc.name+".yaml") + + x := requireXdsIRFromInputTestData(t, inputFile) tr := &Translator{ GlobalRateLimit: &GlobalRateLimitSettings{ ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", dnsDomain), }, } - tCtx, err := tr.Translate(ir) - if !strings.HasSuffix(tc.name, "partial-invalid") && !tc.err { + tCtx, err := tr.Translate(x) + if !strings.HasSuffix(inputFileName, "partial-invalid") && len(cfg.errMsg) == 0 { require.NoError(t, err) + } else if len(cfg.errMsg) > 0 { + require.Error(t, err) + require.Contains(t, err.Error(), cfg.errMsg) + return } listeners := tCtx.XdsResources[resourcev3.ListenerType] @@ -367,23 +138,25 @@ func TestTranslateXds(t *testing.T) { clusters := tCtx.XdsResources[resourcev3.ClusterType] endpoints := tCtx.XdsResources[resourcev3.EndpointType] if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "xds-ir", tc.name+".listeners.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "xds-ir", tc.name+".routes.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "xds-ir", tc.name+".clusters.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "xds-ir", tc.name+".endpoints.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "xds-ir", inputFileName+".listeners.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "xds-ir", inputFileName+".routes.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "xds-ir", inputFileName+".clusters.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "xds-ir", inputFileName+".endpoints.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".routes.yaml"), requireResourcesToYAMLString(t, routes)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) - if tc.requireSecrets { - secrets := tCtx.XdsResources[resourcev3.SecretType] + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".routes.yaml"), requireResourcesToYAMLString(t, routes)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) + + secrets, ok := tCtx.XdsResources[resourcev3.SecretType] + if ok && len(secrets) > 0 { if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "xds-ir", tc.name+".secrets.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "xds-ir", inputFileName+".secrets.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "xds-ir", tc.name+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) + require.Equal(t, requireTestDataOutFile(t, "xds-ir", inputFileName+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) } - if tc.requireEnvoyPatchPolicies { + + if cfg.requireEnvoyPatchPolicies { got := tCtx.EnvoyPatchPolicyStatuses for _, e := range got { require.NoError(t, field.SetValue(e, "LastTransitionTime", metav1.NewTime(time.Time{}))) @@ -391,10 +164,10 @@ func TestTranslateXds(t *testing.T) { if *overrideTestData { out, err := yaml.Marshal(got) require.NoError(t, err) - require.NoError(t, file.Write(string(out), filepath.Join("testdata", "out", "xds-ir", tc.name+".envoypatchpolicies.yaml"))) + require.NoError(t, file.Write(string(out), filepath.Join("testdata", "out", "xds-ir", inputFileName+".envoypatchpolicies.yaml"))) } - in := requireTestDataOutFile(t, "xds-ir", tc.name+".envoypatchpolicies.yaml") + in := requireTestDataOutFile(t, "xds-ir", inputFileName+".envoypatchpolicies.yaml") want := xtypes.EnvoyPatchPolicyStatuses{} require.NoError(t, yaml.Unmarshal([]byte(in), &want)) opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") @@ -404,152 +177,52 @@ func TestTranslateXds(t *testing.T) { } } -func TestTranslateXdsNegative(t *testing.T) { - testCases := []struct { - name string - dnsDomain string - requireSecrets bool - }{ - { - name: "http-route-invalid", - }, - { - name: "tcp-route-invalid", - }, - { - name: "tcp-route-invalid-endpoint", - }, - { - name: "udp-route-invalid", - }, - { - name: "jsonpatch-invalid", - }, - { - name: "jsonpatch-invalid-listener", - }, - { - name: "accesslog-invalid", - }, - { - name: "tracing-invalid", - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - dnsDomain := tc.dnsDomain - if dnsDomain == "" { - dnsDomain = "cluster.local" - } - ir := requireXdsIRFromInputTestData(t, "xds-ir", tc.name+".yaml") - tr := &Translator{ - GlobalRateLimit: &GlobalRateLimitSettings{ - ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", dnsDomain), - }, - } - - _, err := tr.Translate(ir) - require.Error(t, err) - if tc.name != "jsonpatch-invalid" { - require.Contains(t, err.Error(), "validation failed for xds resource") - } - }) - } -} - func TestTranslateRateLimitConfig(t *testing.T) { - testCases := []struct { - name string - }{ - { - name: "empty-header-matches", - }, - { - name: "distinct-match", - }, - { - name: "distinct-remote-address-match", - }, - { - name: "value-match", - }, - { - name: "multiple-matches", - }, - { - name: "multiple-rules", - }, - { - name: "multiple-routes", - }, - { - name: "masked-remote-address-match", - }, - { - name: "multiple-masked-remote-address-match-with-same-cidr", - }, - } + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "ratelimit-config", "*.yaml")) + require.NoError(t, err) - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - in := requireXdsIRListenerFromInputTestData(t, "ratelimit-config", tc.name+".yaml") + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + in := requireXdsIRListenerFromInputTestData(t, inputFile) out := BuildRateLimitServiceConfig(in) if *overrideTestData { - require.NoError(t, file.Write(requireYamlRootToYAMLString(t, out), filepath.Join("testdata", "out", "ratelimit-config", tc.name+".yaml"))) + require.NoError(t, file.Write(requireYamlRootToYAMLString(t, out), filepath.Join("testdata", "out", "ratelimit-config", inputFileName+".yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "ratelimit-config", tc.name+".yaml"), requireYamlRootToYAMLString(t, out)) + require.Equal(t, requireTestDataOutFile(t, "ratelimit-config", inputFileName+".yaml"), requireYamlRootToYAMLString(t, out)) }) } } func TestTranslateXdsWithExtension(t *testing.T) { - testCases := []struct { - name string - requireSecrets bool - err string - }{ - // Require secrets for all the tests since the extension for testing always injects one - { - name: "empty", - requireSecrets: true, - err: "", - }, - { - name: "http-route", - requireSecrets: true, - err: "", - }, - { - name: "http-route-extension-filter", - requireSecrets: true, - err: "", - }, - { - name: "http-route-extension-route-error", - requireSecrets: true, - err: "route hook resource error", + testConfigs := map[string]testFileConfig{ + "http-route-extension-route-error": { + errMsg: "route hook resource error", }, - { - name: "http-route-extension-virtualhost-error", - requireSecrets: true, - err: "extension post xds virtual host hook error", + "http-route-extension-virtualhost-error": { + errMsg: "extension post xds virtual host hook error", }, - { - name: "http-route-extension-listener-error", - requireSecrets: true, - err: "extension post xds listener hook error", + "http-route-extension-listener-error": { + errMsg: "extension post xds listener hook error", }, } - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - // Testdata for the extension tests is similar to the ir test dat + inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "extension-xds-ir", "*.yaml")) + require.NoError(t, err) + + for _, inputFile := range inputFiles { + inputFile := inputFile + inputFileName := testName(inputFile) + t.Run(inputFileName, func(t *testing.T) { + cfg, ok := testConfigs[inputFileName] + if !ok { + cfg = testFileConfig{} + } + + // Testdata for the extension tests is similar to the ir test data // New directory is just to keep them separate and easy to understand - ir := requireXdsIRFromInputTestData(t, "extension-xds-ir", tc.name+".yaml") + x := requireXdsIRFromInputTestData(t, inputFile) tr := &Translator{ GlobalRateLimit: &GlobalRateLimitSettings{ ServiceURL: ratelimit.GetServiceURL("envoy-gateway-system", "cluster.local"), @@ -577,10 +250,9 @@ func TestTranslateXdsWithExtension(t *testing.T) { extMgr := testutils.NewManager(ext) tr.ExtensionManager = &extMgr - tCtx, err := tr.Translate(ir) - - if tc.err != "" { - require.EqualError(t, err, tc.err) + tCtx, err := tr.Translate(x) + if len(cfg.errMsg) > 0 { + require.EqualError(t, err, cfg.errMsg) } else { require.NoError(t, err) listeners := tCtx.XdsResources[resourcev3.ListenerType] @@ -588,42 +260,46 @@ func TestTranslateXdsWithExtension(t *testing.T) { clusters := tCtx.XdsResources[resourcev3.ClusterType] endpoints := tCtx.XdsResources[resourcev3.EndpointType] if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".listeners.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".routes.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".clusters.yaml"))) - require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".endpoints.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, listeners), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".listeners.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, routes), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".routes.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, clusters), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".clusters.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, endpoints), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".endpoints.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".routes.yaml"), requireResourcesToYAMLString(t, routes)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) - if tc.requireSecrets { - secrets := tCtx.XdsResources[resourcev3.SecretType] + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".listeners.yaml"), requireResourcesToYAMLString(t, listeners)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".routes.yaml"), requireResourcesToYAMLString(t, routes)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".clusters.yaml"), requireResourcesToYAMLString(t, clusters)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".endpoints.yaml"), requireResourcesToYAMLString(t, endpoints)) + + secrets, ok := tCtx.XdsResources[resourcev3.SecretType] + if ok { if *overrideTestData { - require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "extension-xds-ir", tc.name+".secrets.yaml"))) + require.NoError(t, file.Write(requireResourcesToYAMLString(t, secrets), filepath.Join("testdata", "out", "extension-xds-ir", inputFileName+".secrets.yaml"))) } - require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", tc.name+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) + require.Equal(t, requireTestDataOutFile(t, "extension-xds-ir", inputFileName+".secrets.yaml"), requireResourcesToYAMLString(t, secrets)) } } }) } } -func requireXdsIRFromInputTestData(t *testing.T, name ...string) *ir.Xds { +func testName(inputFile string) string { + _, fileName := filepath.Split(inputFile) + return strings.TrimSuffix(fileName, ".yaml") +} + +func requireXdsIRFromInputTestData(t *testing.T, name string) *ir.Xds { t.Helper() - elems := append([]string{"testdata", "in"}, name...) - content, err := inFiles.ReadFile(filepath.Join(elems...)) + content, err := inFiles.ReadFile(name) require.NoError(t, err) - ir := &ir.Xds{} - err = yaml.Unmarshal(content, ir) + x := &ir.Xds{} + err = yaml.Unmarshal(content, x) require.NoError(t, err) - return ir + return x } -func requireXdsIRListenerFromInputTestData(t *testing.T, name ...string) *ir.HTTPListener { +func requireXdsIRListenerFromInputTestData(t *testing.T, name string) *ir.HTTPListener { t.Helper() - elems := append([]string{"testdata", "in"}, name...) - content, err := inFiles.ReadFile(filepath.Join(elems...)) + content, err := inFiles.ReadFile(name) require.NoError(t, err) listener := &ir.HTTPListener{} err = yaml.Unmarshal(content, listener) From 585cf44106b77cf8b89c0f45af68d63dc9921a1d Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Thu, 25 Apr 2024 12:28:42 -0700 Subject: [PATCH 02/29] Sync envoyproxy docs from latest into v1.0.1 (#3268) Signed-off-by: Arko Dasgupta Co-authored-by: zirain --- .../tasks/operations/customize-envoyproxy.md | 458 +++++++++++++++++- 1 file changed, 457 insertions(+), 1 deletion(-) diff --git a/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md b/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md index abf8d7ed4da..152f9e7ff44 100644 --- a/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/v1.0.1/tasks/operations/customize-envoyproxy.md @@ -15,6 +15,9 @@ Before proceeding, you should be able to query the example backend using HTTP. First, you need to add ParametersRef in GatewayClass, and refer to EnvoyProxy Config: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + ## Customize EnvoyProxy Deployment Replicas You can customize the EnvoyProxy Deployment Replicas via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After you apply the config, you should see the replicas of envoyproxy changes to 2. And also you can dynamically change the value. @@ -62,6 +112,9 @@ kubectl get deployment -l gateway.envoyproxy.io/owning-gateway-name=eg -n envoy- You can customize the EnvoyProxy Image via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the deployment image, and see it has changed. ## Customize EnvoyProxy Pod Annotations You can customize the EnvoyProxy Pod Annotations via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy pods, and see new annotations has been added. ## Customize EnvoyProxy Deployment Resources You can customize the EnvoyProxy Deployment Resources via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + ## Customize EnvoyProxy Deployment Env You can customize the EnvoyProxy Deployment Env via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + > Envoy Gateway has provided two initial `env` `ENVOY_GATEWAY_NAMESPACE` and `ENVOY_POD_NAME` for envoyproxy container. After applying the config, you can get the envoyproxy deployment, and see resources has been changed. @@ -166,6 +332,9 @@ After applying the config, you can get the envoyproxy deployment, and see resour You can customize the EnvoyProxy Deployment Volumes or VolumeMounts via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy deployment, and see resources has been changed. ## Customize EnvoyProxy Service Annotations You can customize the EnvoyProxy Service Annotations via EnvoyProxy Config like: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, you can get the envoyproxy service, and see annotations has been added. ## Customize EnvoyProxy Bootstrap Config @@ -226,6 +452,9 @@ There are two ways to customize it: * Replace: the whole bootstrap config will be replaced by the config you provided. * Merge: the config you provided will be merged into the default bootstrap config. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + You can use [egctl translate][] to get the default xDS Bootstrap configuration used by Envoy Gateway. @@ -323,6 +642,9 @@ You can enable [Horizontal Pod Autoscaler](https://github.com/envoyproxy/gateway Once confirmed, you can apply it via EnvoyProxy Config as shown below: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + After applying the config, the EnvoyProxy HPA (Horizontal Pod Autoscaler) is generated. However, upon activating the EnvoyProxy's HPA, the Envoy Gateway will no longer reference the `replicas` field specified in the `envoyDeployment`, as outlined [here](#customize-envoyproxy-deployment-replicas). ## Customize EnvoyProxy Command line options @@ -354,6 +706,9 @@ After applying the config, the EnvoyProxy HPA (Horizontal Pod Autoscaler) is gen You can customize the EnvoyProxy Command line options via `spec.extraArgs` in EnvoyProxy Config. For example, the following configuration will add `--disable-extensions` arg in order to disable `envoy.access_loggers/envoy.access_loggers.wasm` extension: +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + +## Customize EnvoyProxy with Patches + +You can customize the EnvoyProxy using patches. + +For example, the following configuration will add resource limits to the `envoy` and the `shutdown-manager` containers in the `envoyproxy` deployment: + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +After applying the configuration, you will see the change in both containers in the `envoyproxy` deployment. + [Gateway API documentation]: https://gateway-api.sigs.k8s.io/ [EnvoyProxy]: ../../../api/extension_types#envoyproxy [egctl translate]: ../egctl/#validating-gateway-api-configuration + From 43078077edc5005c45d885c5af71ae3a39c852ae Mon Sep 17 00:00:00 2001 From: Lior Okman Date: Thu, 25 Apr 2024 22:57:31 +0300 Subject: [PATCH 03/29] feat: Implement useClientProtocol (#3254) * api: Enable controlling the HTTP version used to connect to the backend Signed-off-by: Lior Okman * Modified the proposed API as per the discussions in Slack and the community meetings. Signed-off-by: Lior Okman * Removed an old CEL validation that was relevant for the older proposed API. Signed-off-by: Lior Okman * Remove the intermediate http struct and remove the requirement for an upstream TLS backend. Signed-off-by: Lior Okman * Implement UseClientProtocol functionality. Signed-off-by: Lior Okman * Added unit tests for the feature Signed-off-by: Lior Okman --------- Signed-off-by: Lior Okman Co-authored-by: zirain --- internal/gatewayapi/backendtrafficpolicy.go | 10 ++ ...dtrafficpolicy-use-client-protocol.in.yaml | 49 ++++++ ...trafficpolicy-use-client-protocol.out.yaml | 160 ++++++++++++++++++ internal/ir/xds.go | 2 + internal/ir/zz_generated.deepcopy.go | 5 + internal/xds/translator/cluster.go | 69 ++++---- .../xds-ir/http-preserve-client-protocol.yaml | 31 ++++ ...ttp-preserve-client-protocol.clusters.yaml | 23 +++ ...tp-preserve-client-protocol.endpoints.yaml | 12 ++ ...tp-preserve-client-protocol.listeners.yaml | 34 ++++ .../http-preserve-client-protocol.routes.yaml | 14 ++ internal/xds/translator/translator.go | 26 +-- internal/xds/translator/translator_test.go | 3 + 13 files changed, 396 insertions(+), 42 deletions(-) create mode 100644 internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml create mode 100644 internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 5748caee206..55f79723be3 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -389,6 +389,10 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen } r.Timeout = to } + + if policy.Spec.UseClientProtocol != nil { + r.UseClientProtocol = policy.Spec.UseClientProtocol + } } } } @@ -560,6 +564,12 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back r.Timeout = ct } } + + if policy.Spec.UseClientProtocol != nil { + if r.UseClientProtocol == nil { + r.UseClientProtocol = policy.Spec.UseClientProtocol + } + } } } diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml new file mode 100644 index 00000000000..5cb15cfc3c6 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.in.yaml @@ -0,0 +1,49 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + useClientProtocol: true + diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml new file mode 100644 index 00000000000..e2f632b1a52 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-use-client-protocol.out.yaml @@ -0,0 +1,160 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + useClientProtocol: true + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + useClientProtocol: true diff --git a/internal/ir/xds.go b/internal/ir/xds.go index de192170e2e..14884f88101 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -502,6 +502,8 @@ type HTTPRoute struct { // Security holds the features associated with SecurityPolicy Security *SecurityFeatures `json:"security,omitempty" yaml:"security,omitempty"` + // UseClientProtocol enables using the same protocol upstream that was used downstream + UseClientProtocol *bool `json:"useClientProtocol,omitempty" yaml:"useClientProtocol,omitempty"` } // SecurityFeatures holds the information associated with the Security Policy. diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index bffc4639cb6..6edea530914 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -1071,6 +1071,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(SecurityFeatures) (*in).DeepCopyInto(*out) } + if in.UseClientProtocol != nil { + in, out := &in.UseClientProtocol, &out.UseClientProtocol + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 6cbe45def02..8587aca73f9 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -38,18 +38,19 @@ const ( ) type xdsClusterArgs struct { - name string - settings []*ir.DestinationSetting - tSocket *corev3.TransportSocket - endpointType EndpointType - loadBalancer *ir.LoadBalancer - proxyProtocol *ir.ProxyProtocol - circuitBreaker *ir.CircuitBreaker - healthCheck *ir.HealthCheck - http1Settings *ir.HTTP1Settings - timeout *ir.Timeout - tcpkeepalive *ir.TCPKeepalive - metrics *ir.Metrics + name string + settings []*ir.DestinationSetting + tSocket *corev3.TransportSocket + endpointType EndpointType + loadBalancer *ir.LoadBalancer + proxyProtocol *ir.ProxyProtocol + circuitBreaker *ir.CircuitBreaker + healthCheck *ir.HealthCheck + http1Settings *ir.HTTP1Settings + timeout *ir.Timeout + tcpkeepalive *ir.TCPKeepalive + metrics *ir.Metrics + useClientProtocol bool } type EndpointType int @@ -447,7 +448,7 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. requiresHTTP1Options := args.http1Settings != nil && (args.http1Settings.EnableTrailers || args.http1Settings.PreserveHeaderCase || args.http1Settings.HTTP10 != nil) - if !(requiresCommonHTTPOptions || requiresHTTP1Options || requiresHTTP2Options) { + if !(requiresCommonHTTPOptions || requiresHTTP1Options || requiresHTTP2Options || args.useClientProtocol) { return nil } @@ -473,25 +474,11 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. Value: *args.circuitBreaker.MaxRequestsPerConnection, } } - } - // When setting any Typed Extension Protocol Options, UpstreamProtocolOptions are mandatory - // If translation requires HTTP2 enablement or HTTP1 trailers, set appropriate setting - // Default to http1 otherwise - // TODO: If the cluster is TLS enabled, use AutoHTTPConfig instead of ExplicitHttpConfig - // so that when ALPN is supported then enabling http1 options doesn't force HTTP/1.1 - switch { - case requiresHTTP2Options: - protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ - ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ - ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, - }, - } - case requiresHTTP1Options: - http1opts := &corev3.Http1ProtocolOptions{ - EnableTrailers: args.http1Settings.EnableTrailers, - } + http1opts := &corev3.Http1ProtocolOptions{} + if args.http1Settings != nil { + http1opts.EnableTrailers = args.http1Settings.EnableTrailers if args.http1Settings.PreserveHeaderCase { preservecaseAny, _ := anypb.New(&preservecasev3.PreserveCaseFormatterConfig{}) http1opts.HeaderKeyFormat = &corev3.Http1ProtocolOptions_HeaderKeyFormat{ @@ -507,6 +494,28 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. http1opts.AcceptHttp_10 = true http1opts.DefaultHostForHttp_10 = ptr.Deref(args.http1Settings.HTTP10.DefaultHost, "") } + } + + // When setting any Typed Extension Protocol Options, UpstreamProtocolOptions are mandatory + // If translation requires HTTP2 enablement or HTTP1 trailers, set appropriate setting + // Default to http1 otherwise + // TODO: If the cluster is TLS enabled, use AutoHTTPConfig instead of ExplicitHttpConfig + // so that when ALPN is supported then enabling http1 options doesn't force HTTP/1.1 + switch { + case args.useClientProtocol: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_UseDownstreamProtocolConfig{ + UseDownstreamProtocolConfig: &httpv3.HttpProtocolOptions_UseDownstreamHttpConfig{ + HttpProtocolOptions: http1opts, + Http2ProtocolOptions: &corev3.Http2ProtocolOptions{}, + }, + } + case requiresHTTP2Options: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, + }, + } + case requiresHTTP1Options: protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{ diff --git a/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml b/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml new file mode 100644 index 00000000000..bfafbc5b96d --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-preserve-client-protocol.yaml @@ -0,0 +1,31 @@ +http: +- address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + useClientProtocol: true diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml new file mode 100644 index 00000000000..5de1d1cce34 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.clusters.yaml @@ -0,0 +1,23 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/0 + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + useDownstreamProtocolConfig: + http2ProtocolOptions: {} + httpProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml new file mode 100644 index 00000000000..29bb6b4e444 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/0/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml new file mode 100644 index 00000000000..a593a50af36 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.listeners.yaml @@ -0,0 +1,34 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: envoy-gateway/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + useRemoteAddress: true + drainType: MODIFY_ONLY + name: envoy-gateway/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml new file mode 100644 index 00000000000..19e1921fb1e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-preserve-client-protocol.routes.yaml @@ -0,0 +1,14 @@ +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-1/http + virtualHosts: + - domains: + - gateway.envoyproxy.io + name: envoy-gateway/gateway-1/http/gateway_envoyproxy_io + routes: + - match: + prefix: / + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 2d5945d2e96..adb89cfab71 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -24,6 +24,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/wrapperspb" + "k8s.io/utils/ptr" extensionTypes "github.com/envoyproxy/gateway/internal/extension/types" "github.com/envoyproxy/gateway/internal/ir" @@ -638,18 +639,19 @@ func findXdsEndpoint(tCtx *types.ResourceVersionTable, name string) *endpointv3. // processXdsCluster processes a xds cluster by its endpoint address type. func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute, http1Settings *ir.HTTP1Settings, metrics *ir.Metrics) error { if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: httpRoute.Destination.Name, - settings: httpRoute.Destination.Settings, - tSocket: nil, - endpointType: buildEndpointType(httpRoute.Destination.Settings), - loadBalancer: httpRoute.LoadBalancer, - proxyProtocol: httpRoute.ProxyProtocol, - circuitBreaker: httpRoute.CircuitBreaker, - healthCheck: httpRoute.HealthCheck, - http1Settings: http1Settings, - timeout: httpRoute.Timeout, - tcpkeepalive: httpRoute.TCPKeepalive, - metrics: metrics, + name: httpRoute.Destination.Name, + settings: httpRoute.Destination.Settings, + tSocket: nil, + endpointType: buildEndpointType(httpRoute.Destination.Settings), + loadBalancer: httpRoute.LoadBalancer, + proxyProtocol: httpRoute.ProxyProtocol, + circuitBreaker: httpRoute.CircuitBreaker, + healthCheck: httpRoute.HealthCheck, + http1Settings: http1Settings, + timeout: httpRoute.Timeout, + tcpkeepalive: httpRoute.TCPKeepalive, + metrics: metrics, + useClientProtocol: ptr.Deref(httpRoute.UseClientProtocol, false), }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index 28868500b68..6c820adf15b 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -94,6 +94,9 @@ func TestTranslateXds(t *testing.T) { "tracing-invalid": { errMsg: "validation failed for xds resource", }, + { + name: "http-preserve-client-protocol", + }, } inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "xds-ir", "*.yaml")) From a81291ea99d2c36d5e11a1510bedc9052e985e29 Mon Sep 17 00:00:00 2001 From: Alex Volchok Date: Thu, 25 Apr 2024 22:31:46 +0200 Subject: [PATCH 04/29] feat: support backend tls settings with envoyproxy (#3218) * adding backend tls settings support via envoyproxy Signed-off-by: Alexander Volchok * updating Signed-off-by: Alexander Volchok * update docs Signed-off-by: Alexander Volchok * fix generates Signed-off-by: Alexander Volchok * updating Signed-off-by: Alexander Volchok * updating Signed-off-by: Alexander Volchok * adding translation Signed-off-by: Alexander Volchok * updating Signed-off-by: Alexander Volchok * code review changes Signed-off-by: Alexander Volchok * updating Signed-off-by: Alexander Volchok * regenerate Signed-off-by: Alexander Volchok * fix generate Signed-off-by: Alexander Volchok * reuse tls builder Signed-off-by: Alexander Volchok --------- Signed-off-by: Alexander Volchok Co-authored-by: Guy Daich --- api/v1alpha1/clienttrafficpolicy_types.go | 2 +- api/v1alpha1/envoyproxy_types.go | 15 ++ api/v1alpha1/tls_types.go | 14 +- api/v1alpha1/zz_generated.deepcopy.go | 54 ++++- .../gateway.envoyproxy.io_envoyproxies.yaml | 136 ++++++++++++ internal/gatewayapi/backendtlspolicy.go | 27 ++- .../testdata/envoyproxy-tls-settings.in.yaml | 136 ++++++++++++ .../testdata/envoyproxy-tls-settings.out.yaml | 204 ++++++++++++++++++ internal/ir/xds.go | 1 + internal/ir/zz_generated.deepcopy.go | 1 + internal/xds/translator/translator.go | 11 +- internal/xds/translator/utils.go | 10 +- site/content/en/latest/api/extension_types.md | 53 ++++- .../clienttrafficpolicy_test.go | 29 ++- 14 files changed, 656 insertions(+), 37 deletions(-) create mode 100644 internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml create mode 100644 internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 19a854766bb..882f094a071 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -66,7 +66,7 @@ type ClientTrafficPolicySpec struct { // TLS settings configure TLS termination settings with the downstream client. // // +optional - TLS *TLSSettings `json:"tls,omitempty"` + TLS *ClientTLSSettings `json:"tls,omitempty"` // Path enables managing how the incoming path set by clients can be normalized. // // +optional diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index e878c4a88a1..bcec1ff5837 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -7,6 +7,7 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) const ( @@ -116,6 +117,20 @@ type EnvoyProxySpec struct { // +optional // +notImplementedHide FilterOrder []FilterPosition `json:"filterOrder,omitempty"` + // BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends. + // These settings are applied on backends for which TLS policies are specified. + // +optional + BackendTLS *BackendTLSConfig `json:"backendTLS,omitempty"` +} + +// BackendTLSConfig describes the BackendTLS configuration for Envoy Proxy. +type BackendTLSConfig struct { + // ClientCertificateRef defines the reference to a Kubernetes Secret that contains + // the client certificate and private key for Envoy to use when connecting to + // backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. + // +optional + ClientCertificateRef *gwapiv1.SecretObjectReference `json:"clientCertificateRef,omitempty"` + TLSSettings `json:",inline"` } // FilterPosition defines the position of an Envoy HTTP filter in the filter chain. diff --git a/api/v1alpha1/tls_types.go b/api/v1alpha1/tls_types.go index 448913af3eb..38c52761125 100644 --- a/api/v1alpha1/tls_types.go +++ b/api/v1alpha1/tls_types.go @@ -9,10 +9,17 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) +type ClientTLSSettings struct { + // ClientValidation specifies the configuration to validate the client + // initiating the TLS connection to the Gateway listener. + // +optional + ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` + TLSSettings `json:",inline"` +} + // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && self.minVersion == '1.3' ? !has(self.ciphers) : true", message="setting ciphers has no effect if the minimum possible TLS version is 1.3" // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && has(self.maxVersion) ? {\"Auto\":0,\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4}[self.minVersion] <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : true", message="minVersion must be smaller or equal to maxVersion" type TLSSettings struct { - // Min specifies the minimal TLS protocol version to allow. // The default is TLS 1.2 if this is not specified. // @@ -66,11 +73,6 @@ type TLSSettings struct { // // +optional ALPNProtocols []ALPNProtocol `json:"alpnProtocols,omitempty"` - - // ClientValidation specifies the configuration to validate the client - // initiating the TLS connection to the Gateway listener. - // +optional - ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` } // ALPNProtocol specifies the protocol to be negotiated using ALPN diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ed7c22232ac..2dac3319301 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -192,6 +192,27 @@ func (in *BackendRef) DeepCopy() *BackendRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendTLSConfig) DeepCopyInto(out *BackendTLSConfig) { + *out = *in + if in.ClientCertificateRef != nil { + in, out := &in.ClientCertificateRef, &out.ClientCertificateRef + *out = new(v1.SecretObjectReference) + (*in).DeepCopyInto(*out) + } + in.TLSSettings.DeepCopyInto(&out.TLSSettings) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTLSConfig. +func (in *BackendTLSConfig) DeepCopy() *BackendTLSConfig { + if in == nil { + return nil + } + out := new(BackendTLSConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendTrafficPolicy) DeepCopyInto(out *BackendTrafficPolicy) { *out = *in @@ -469,6 +490,27 @@ func (in *ClientIPDetectionSettings) DeepCopy() *ClientIPDetectionSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientTLSSettings) DeepCopyInto(out *ClientTLSSettings) { + *out = *in + if in.ClientValidation != nil { + in, out := &in.ClientValidation, &out.ClientValidation + *out = new(ClientValidationContext) + (*in).DeepCopyInto(*out) + } + in.TLSSettings.DeepCopyInto(&out.TLSSettings) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTLSSettings. +func (in *ClientTLSSettings) DeepCopy() *ClientTLSSettings { + if in == nil { + return nil + } + out := new(ClientTLSSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientTimeout) DeepCopyInto(out *ClientTimeout) { *out = *in @@ -569,7 +611,7 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { } if in.TLS != nil { in, out := &in.TLS, &out.TLS - *out = new(TLSSettings) + *out = new(ClientTLSSettings) (*in).DeepCopyInto(*out) } if in.Path != nil { @@ -1529,6 +1571,11 @@ func (in *EnvoyProxySpec) DeepCopyInto(out *EnvoyProxySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.BackendTLS != nil { + in, out := &in.BackendTLS, &out.BackendTLS + *out = new(BackendTLSConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxySpec. @@ -4069,11 +4116,6 @@ func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { *out = make([]ALPNProtocol, len(*in)) copy(*out, *in) } - if in.ClientValidation != nil { - in, out := &in.ClientValidation, &out.ClientValidation - *out = new(ClientValidationContext) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index aea1c477d94..64ff525cad2 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -43,6 +43,142 @@ spec: spec: description: EnvoyProxySpec defines the desired state of EnvoyProxy. properties: + backendTLS: + description: |- + BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends. + These settings are applied on backends for which TLS policies are specified. + properties: + alpnProtocols: + description: |- + ALPNProtocols supplies the list of ALPN protocols that should be + exposed by the listener. By default h2 and http/1.1 are enabled. + Supported values are: + - http/1.0 + - http/1.1 + - h2 + items: + description: ALPNProtocol specifies the protocol to be negotiated + using ALPN + enum: + - http/1.0 + - http/1.1 + - h2 + type: string + type: array + ciphers: + description: |- + Ciphers specifies the set of cipher suites supported when + negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3. + In non-FIPS Envoy Proxy builds the default cipher list is: + - [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] + - [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] + - ECDHE-ECDSA-AES256-GCM-SHA384 + - ECDHE-RSA-AES256-GCM-SHA384 + In builds using BoringSSL FIPS the default cipher list is: + - ECDHE-ECDSA-AES128-GCM-SHA256 + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + - ECDHE-RSA-AES256-GCM-SHA384 + items: + type: string + type: array + clientCertificateRef: + description: |- + ClientCertificateRef defines the reference to a Kubernetes Secret that contains + the client certificate and private key for Envoy to use when connecting to + backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referenced object. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + ecdhCurves: + description: |- + ECDHCurves specifies the set of supported ECDH curves. + In non-FIPS Envoy Proxy builds the default curves are: + - X25519 + - P-256 + In builds using BoringSSL FIPS the default curve is: + - P-256 + items: + type: string + type: array + maxVersion: + description: |- + Max specifies the maximal TLS protocol version to allow + The default is TLS 1.3 if this is not specified. + enum: + - Auto + - "1.0" + - "1.1" + - "1.2" + - "1.3" + type: string + minVersion: + description: |- + Min specifies the minimal TLS protocol version to allow. + The default is TLS 1.2 if this is not specified. + enum: + - Auto + - "1.0" + - "1.1" + - "1.2" + - "1.3" + type: string + signatureAlgorithms: + description: |- + SignatureAlgorithms specifies which signature algorithms the listener should + support. + items: + type: string + type: array + type: object + x-kubernetes-validations: + - message: setting ciphers has no effect if the minimum possible TLS + version is 1.3 + rule: 'has(self.minVersion) && self.minVersion == ''1.3'' ? !has(self.ciphers) + : true' + - message: minVersion must be smaller or equal to maxVersion + rule: 'has(self.minVersion) && has(self.maxVersion) ? {"Auto":0,"1.0":1,"1.1":2,"1.2":3,"1.3":4}[self.minVersion] + <= {"1.0":1,"1.1":2,"1.2":3,"1.3":4,"Auto":5}[self.maxVersion] + : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {"1.0":1,"1.1":2,"1.2":3,"1.3":4,"Auto":5}[self.maxVersion] + : true' bootstrap: description: |- Bootstrap defines the Envoy Bootstrap as a YAML string. diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index 3a137030a1e..d0b21b35428 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -78,7 +78,32 @@ func (t *Translator) processBackendTLSPolicy( } status.SetAcceptedForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName) - + // apply defaults as per envoyproxy + if resources.EnvoyProxy != nil { + if resources.EnvoyProxy.Spec.BackendTLS != nil { + if len(resources.EnvoyProxy.Spec.BackendTLS.Ciphers) > 0 { + tlsBundle.Ciphers = resources.EnvoyProxy.Spec.BackendTLS.Ciphers + } + if len(resources.EnvoyProxy.Spec.BackendTLS.ECDHCurves) > 0 { + tlsBundle.ECDHCurves = resources.EnvoyProxy.Spec.BackendTLS.ECDHCurves + } + if len(resources.EnvoyProxy.Spec.BackendTLS.SignatureAlgorithms) > 0 { + tlsBundle.SignatureAlgorithms = resources.EnvoyProxy.Spec.BackendTLS.SignatureAlgorithms + } + if resources.EnvoyProxy.Spec.BackendTLS.MinVersion != nil { + tlsBundle.MinVersion = ptr.To(ir.TLSVersion(*resources.EnvoyProxy.Spec.BackendTLS.MinVersion)) + } + if resources.EnvoyProxy.Spec.BackendTLS.MinVersion != nil { + tlsBundle.MaxVersion = ptr.To(ir.TLSVersion(*resources.EnvoyProxy.Spec.BackendTLS.MaxVersion)) + } + if len(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols) > 0 { + tlsBundle.ALPNProtocols = make([]string, len(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols)) + for i := range resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols { + tlsBundle.ALPNProtocols[i] = string(resources.EnvoyProxy.Spec.BackendTLS.ALPNProtocols[i]) + } + } + } + } return tlsBundle } diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml new file mode 100644 index 00000000000..f46ecc052e2 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.in.yaml @@ -0,0 +1,136 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-tls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + namespace: envoy-gateway + group: "" + name: default-cert +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-tls + namespace: envoy-gateway + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-tls + rules: + - backendRefs: + - name: https-backend + namespace: default + port: 443 +referenceGrants: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + name: refg-route-svc + namespace: default + spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: envoy-gateway + - group: gateway.networking.k8s.io + kind: Gateway + namespace: envoy-gateway + - group: gateway.networking.k8s.io + kind: BackendTLSPolicy + namespace: default + to: + - group: "" + kind: Service +services: + - apiVersion: v1 + kind: Service + metadata: + name: https-backend + namespace: default + spec: + clusterIP: 10.11.12.13 + ports: + - port: 443 + name: https + protocol: TCP + targetPort: 443 + +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-https-backend + namespace: default + labels: + kubernetes.io/service-name: https-backend + addressType: IPv4 + ports: + - name: https + protocol: TCP + port: 443 + endpoints: + - addresses: + - "10.244.0.11" + conditions: + ready: true +backendTLSPolicies: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-tls + namespace: default + spec: + targetRef: + group: '' + kind: Service + name: https-backend + tls: + wellKnownCACerts: System + hostname: example.com +envoyproxy: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + namespace: envoy-gateway-system + name: test + spec: + backendTLS: + clientCertificateRef: + group: "" + kind: Secret + namespace: default + name: secret.yaml + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + SignatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + alpnProtocols: + - HTTP/1.1 + - HTTP/2 +secrets: + - apiVersion: v1 + kind: Secret + metadata: + name: default-cert + namespace: envoy-gateway + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV1Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktRd2dnU2dBZ0VBQW9JQkFRQ1pTT21NUlBXWkFqN08KcVFrTVc2d3Bub3NmVCtRMzhmVWJ1U3crRXlablZ1eUNuYlVGZjhIeTVyYkx1K2dmbWszUW8xbnRBVTMzamprUQpXMGQzRHdCdWhKVUM0bkpVRks3cDk2dm9MQ2FTdmlPM0NQbytjUENPdkZ4K1ZrTzYxVkxXOEI2YW04UG5GWndhCmlGRGk0aUdyWXlIK3lsK2RUTmJoZlhIeEJ4T0E1M0IrcTI2K2ZmMFJXUWJKSWNiT1RzOENTSDZJWk1yeGNIcmsKOE1TdjFhWXlQdXpuT1BBQVFsNlRUdlEvNmhJZnF6bXJvd0RIRjRCMENFNUFvb2xFM0ZLT2kwaC9ieTJUN1dxbgo4NkdhdXA0VEtxVnV1Uk5hUU1CZDQ4azA4V3VTUENYSDBoWTVJbm1kdEMxRURKK3pQRk9NUjQycVA0THg5QWdICjNRZTBTMU5yQWdNQkFBRUNnZjk2Zy9QWXh2YVp5NEJuMU5ySkJkOExaT2djYlpjMmdueDZJa3YvVVhaME5obHgKRVlpS2plRmpWNkhXNW9FWHJaKy9tUGY0ZHVzVmFMNzRVOVZvanVQSmNlQWVScmpMM2VPaGJIdGN4KzBnY0dMZwpYeEY5VFJhcDY1VHVVZDFhaTA0aEd3WWY3NXNiUDdSS2JQaXZ3WmdVQWUwQ3BWdWZjaG5YcXJzWXI4cEpZNTFPCldWa1NxejRSWTlXbTBrNUcxSkZ5SXlFQzl1bURsdWpjSE50UlZtYWZrTmZBdENsaVByRktjL245bkpmTzZSRlAKN2c3Vi9JdnFudUlyN1BFM0duNlBhVCtCZ2c0NDh0ZDVKelBwVEE1WkJjQm8yb3J6L2t4WVBGcHIvZ1BVQnFRZApvNm5XcXc3Nlp4d1BsZHdMaEorWFlOWDdvdWN0VVNDTDl1NzdmeUVDZ1lFQXl2N0RseGYrS1FsZkR3bW8vcjFUCjBMMVpuSDQ3MmhpSWVkU2hleVZCSGJFVlRTbXI0MkJSbGpXNERiUmNRTTRWY3h4RGtHclI3NlJHZTlvZzZtemMKUnY4K1ZsQ1gyK3F5OXA1bTZaWHJiQXczMHpDLzVtUGtSV3ViaFVoaSs5ZUNNWmEvaEFJL1JGdjI2OURyQkQyLwo2a2cwRjhYME8vNndJK1dwYXRLM1cwY0NnWUVBd1U5QTZiSnBmYVhLS1hQR21PRy9uVXhUeXp5cVlqS05aSmQvCjlHaEVudUdqSzVDQUVWUEphOGtadmZRemxXbXdaYWZxMERocUk4dkxhRkNEZjhZOEU5OU1hbjNHV2hVYjNWL0oKcU5RUVMzNTZOQ2ZadzdseG9LS0JJdlQ2Y3dpaFRuc0UvUjRIQ3NhbDJ3d040Wmw5SFdOQmdhbVM3VExrejFMaApmd1JEa0wwQ2dZQlo0OWorNW53QTlncG5JVkw1Z3lORGN5WGtlNjNMVlVQU0YwdHV1YitOQTJhNFpiU2RHb0RtCmNHRlJpRVcxMk14OHpjNUpmRlA4dDVVU3NUUVVPeUtNT2VrRDFlcDVVd1B1MjVRYzZldDNUQzNJVW5VWDg3SVkKMzU3ZHRZRkhubFlqMldwemJYOVFxUnk5cmlUMEd0Z0tTZkR2ZWhRK0lQa2szRVZhYlhjT2J3S0JnR0d4QzcwTwp6UUVTcC9nSzZuS1lvNTE2MVY0QWFwcjFzVDhFMFVWUzdGcmU3UGMzTDRHU05saWlhTC8yaVpzWXJteXhUNW1xCjZQanVKUDJ5c3NJQURKeCtYTC8wa0NrMlFiNitpY3NvWUpQR2R6dWthQWpoenVxL05VUFZTanlZUCt6SmZ0dnMKTU9MaFFUQlNCekhidjc3NlNrQ2MwZ1BObEpTeDdnT2l4QUtCQW9HQUpCR1VuM2U1QWZDb21BMUUxRHhSeUxaagpUMFBrQUNlUGpEK3hrRkpod0RoQ2dzd2htNFVKZzFmQW8xaEJRUkZ0dHBWQy91QkxjazE4TUVBSTF2ZGZTeVB2CmtTZzVrVnFQanUzc2czOVRNZ09WZXdqUDNFM0FNUUd1ZzFQNzFZazJ6WUpQbGg5NWRMVTVISlZubzZvdkIrUG0KTHF5K016eDN3a0YwZDhlUFhRND0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml new file mode 100644 index 00000000000..36ecc443361 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings.out.yaml @@ -0,0 +1,204 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-tls + namespace: default + spec: + targetRef: + group: "" + kind: Service + name: https-backend + tls: + hostname: example.com + wellKnownCACerts: System + status: + ancestors: + - ancestorRef: + name: gateway-tls + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-tls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: "" + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: default-cert + namespace: envoy-gateway + mode: Terminate + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: "" + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-tls + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-tls + namespace: envoy-gateway + rules: + - backendRefs: + - name: https-backend + namespace: default + port: 443 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-tls + namespace: envoy-gateway +infraIR: + envoy-gateway/gateway-tls: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + backendTLS: + alpnProtocols: + - HTTP/1.1 + - HTTP/2 + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + clientCertificateRef: + group: "" + kind: Secret + name: secret.yaml + namespace: default + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + signatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + logging: {} + status: {} + listeners: + - address: null + name: envoy-gateway/gateway-tls/ + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-tls + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-tls +xdsIR: + envoy-gateway/gateway-tls: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-tls/ + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/envoy-gateway/httproute-tls/rule/0 + settings: + - addressType: IP + endpoints: + - host: 10.244.0.11 + port: 443 + protocol: HTTP + tls: + alpnProtocols: + - HTTP/1.1 + - HTTP/2 + ciphers: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + ecdhCurves: + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + maxVersion: tls1.3 + minVersion: tls1.2 + signatureAlgorithms: + - RSA-PSS-RSAE-SHA256 + - ECDSA-SECP256R1-SHA256 + sni: example.com + useSystemTrustStore: true + weight: 1 + hostname: '*' + isHTTP2: false + name: httproute/envoy-gateway/httproute-tls/rule/0/match/-1/* + tls: + certificates: + - name: envoy-gateway/default-cert + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV1Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktRd2dnU2dBZ0VBQW9JQkFRQ1pTT21NUlBXWkFqN08KcVFrTVc2d3Bub3NmVCtRMzhmVWJ1U3crRXlablZ1eUNuYlVGZjhIeTVyYkx1K2dmbWszUW8xbnRBVTMzamprUQpXMGQzRHdCdWhKVUM0bkpVRks3cDk2dm9MQ2FTdmlPM0NQbytjUENPdkZ4K1ZrTzYxVkxXOEI2YW04UG5GWndhCmlGRGk0aUdyWXlIK3lsK2RUTmJoZlhIeEJ4T0E1M0IrcTI2K2ZmMFJXUWJKSWNiT1RzOENTSDZJWk1yeGNIcmsKOE1TdjFhWXlQdXpuT1BBQVFsNlRUdlEvNmhJZnF6bXJvd0RIRjRCMENFNUFvb2xFM0ZLT2kwaC9ieTJUN1dxbgo4NkdhdXA0VEtxVnV1Uk5hUU1CZDQ4azA4V3VTUENYSDBoWTVJbm1kdEMxRURKK3pQRk9NUjQycVA0THg5QWdICjNRZTBTMU5yQWdNQkFBRUNnZjk2Zy9QWXh2YVp5NEJuMU5ySkJkOExaT2djYlpjMmdueDZJa3YvVVhaME5obHgKRVlpS2plRmpWNkhXNW9FWHJaKy9tUGY0ZHVzVmFMNzRVOVZvanVQSmNlQWVScmpMM2VPaGJIdGN4KzBnY0dMZwpYeEY5VFJhcDY1VHVVZDFhaTA0aEd3WWY3NXNiUDdSS2JQaXZ3WmdVQWUwQ3BWdWZjaG5YcXJzWXI4cEpZNTFPCldWa1NxejRSWTlXbTBrNUcxSkZ5SXlFQzl1bURsdWpjSE50UlZtYWZrTmZBdENsaVByRktjL245bkpmTzZSRlAKN2c3Vi9JdnFudUlyN1BFM0duNlBhVCtCZ2c0NDh0ZDVKelBwVEE1WkJjQm8yb3J6L2t4WVBGcHIvZ1BVQnFRZApvNm5XcXc3Nlp4d1BsZHdMaEorWFlOWDdvdWN0VVNDTDl1NzdmeUVDZ1lFQXl2N0RseGYrS1FsZkR3bW8vcjFUCjBMMVpuSDQ3MmhpSWVkU2hleVZCSGJFVlRTbXI0MkJSbGpXNERiUmNRTTRWY3h4RGtHclI3NlJHZTlvZzZtemMKUnY4K1ZsQ1gyK3F5OXA1bTZaWHJiQXczMHpDLzVtUGtSV3ViaFVoaSs5ZUNNWmEvaEFJL1JGdjI2OURyQkQyLwo2a2cwRjhYME8vNndJK1dwYXRLM1cwY0NnWUVBd1U5QTZiSnBmYVhLS1hQR21PRy9uVXhUeXp5cVlqS05aSmQvCjlHaEVudUdqSzVDQUVWUEphOGtadmZRemxXbXdaYWZxMERocUk4dkxhRkNEZjhZOEU5OU1hbjNHV2hVYjNWL0oKcU5RUVMzNTZOQ2ZadzdseG9LS0JJdlQ2Y3dpaFRuc0UvUjRIQ3NhbDJ3d040Wmw5SFdOQmdhbVM3VExrejFMaApmd1JEa0wwQ2dZQlo0OWorNW53QTlncG5JVkw1Z3lORGN5WGtlNjNMVlVQU0YwdHV1YitOQTJhNFpiU2RHb0RtCmNHRlJpRVcxMk14OHpjNUpmRlA4dDVVU3NUUVVPeUtNT2VrRDFlcDVVd1B1MjVRYzZldDNUQzNJVW5VWDg3SVkKMzU3ZHRZRkhubFlqMldwemJYOVFxUnk5cmlUMEd0Z0tTZkR2ZWhRK0lQa2szRVZhYlhjT2J3S0JnR0d4QzcwTwp6UUVTcC9nSzZuS1lvNTE2MVY0QWFwcjFzVDhFMFVWUzdGcmU3UGMzTDRHU05saWlhTC8yaVpzWXJteXhUNW1xCjZQanVKUDJ5c3NJQURKeCtYTC8wa0NrMlFiNitpY3NvWUpQR2R6dWthQWpoenVxL05VUFZTanlZUCt6SmZ0dnMKTU9MaFFUQlNCekhidjc3NlNrQ2MwZ1BObEpTeDdnT2l4QUtCQW9HQUpCR1VuM2U1QWZDb21BMUUxRHhSeUxaagpUMFBrQUNlUGpEK3hrRkpod0RoQ2dzd2htNFVKZzFmQW8xaEJRUkZ0dHBWQy91QkxjazE4TUVBSTF2ZGZTeVB2CmtTZzVrVnFQanUzc2czOVRNZ09WZXdqUDNFM0FNUUd1ZzFQNzFZazJ6WUpQbGg5NWRMVTVISlZubzZvdkIrUG0KTHF5K016eDN3a0YwZDhlUFhRND0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo= + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 14884f88101..e28df915e21 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -1885,6 +1885,7 @@ type TLSUpstreamConfig struct { SNI string `json:"sni,omitempty" yaml:"sni,omitempty"` UseSystemTrustStore bool `json:"useSystemTrustStore,omitempty" yaml:"useSystemTrustStore,omitempty"` CACertificate *TLSCACertificate `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty"` + TLSConfig `json:",inline"` } // Connection settings for downstream connections diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 6edea530914..21f6cdf87d7 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -2288,6 +2288,7 @@ func (in *TLSUpstreamConfig) DeepCopyInto(out *TLSUpstreamConfig) { *out = new(TLSCACertificate) (*in).DeepCopyInto(*out) } + in.TLSConfig.DeepCopyInto(&out.TLSConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSUpstreamConfig. diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index adb89cfab71..cd517a4d56e 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -768,12 +768,11 @@ func buildXdsUpstreamTLSCASecret(tlsConfig *ir.TLSUpstreamConfig) *tlsv3.Secret } func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3.TransportSocket, error) { - var tlsCtx *tlsv3.UpstreamTlsContext - if tlsConfig.UseSystemTrustStore { tlsCtx = &tlsv3.UpstreamTlsContext{ CommonTlsContext: &tlsv3.CommonTlsContext{ + TlsCertificates: nil, ValidationContextType: &tlsv3.CommonTlsContext_ValidationContext{ ValidationContext: &tlsv3.CertificateValidationContext{ TrustedCa: &corev3.DataSource{ @@ -807,6 +806,14 @@ func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3. } } + tlsParams := buildTLSParams(&tlsConfig.TLSConfig) + if tlsParams != nil { + tlsCtx.CommonTlsContext.TlsParams = tlsParams + } + + if len(tlsConfig.ALPNProtocols) > 0 { + tlsCtx.CommonTlsContext.AlpnProtocols = buildALPNProtocols(tlsConfig.ALPNProtocols) + } tlsCtxAny, err := anypb.New(tlsCtx) if err != nil { return nil, err diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go index f4d24c9965d..dbcb005ef32 100644 --- a/internal/xds/translator/utils.go +++ b/internal/xds/translator/utils.go @@ -13,16 +13,14 @@ import ( "strconv" "strings" - "k8s.io/utils/ptr" - - "github.com/envoyproxy/gateway/internal/ir" - "github.com/envoyproxy/gateway/internal/xds/types" - corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "google.golang.org/protobuf/types/known/anypb" + "k8s.io/utils/ptr" + + "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/xds/types" ) const ( diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 2b259ff865d..72dbebba440 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -36,6 +36,8 @@ _Underlying type:_ _string_ ALPNProtocol specifies the protocol to be negotiated using ALPN _Appears in:_ +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) - [TLSSettings](#tlssettings) | Value | Description | @@ -206,6 +208,26 @@ _Appears in:_ | `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | +#### BackendTLSConfig + + + +BackendTLSConfig describes the BackendTLS configuration for Envoy Proxy. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `clientCertificateRef` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | false | ClientCertificateRef defines the reference to a Kubernetes Secret that contains
the client certificate and private key for Envoy to use when connecting to
backend services and external services, such as ExtAuth, ALS, OpenTelemetry, etc. | +| `minVersion` | _[TLSVersion](#tlsversion)_ | false | Min specifies the minimal TLS protocol version to allow.
The default is TLS 1.2 if this is not specified. | +| `maxVersion` | _[TLSVersion](#tlsversion)_ | false | Max specifies the maximal TLS protocol version to allow
The default is TLS 1.3 if this is not specified. | +| `ciphers` | _string array_ | false | Ciphers specifies the set of cipher suites supported when
negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3.
In non-FIPS Envoy Proxy builds the default cipher list is:
- [ECDHE-ECDSA-AES128-GCM-SHA256\|ECDHE-ECDSA-CHACHA20-POLY1305]
- [ECDHE-RSA-AES128-GCM-SHA256\|ECDHE-RSA-CHACHA20-POLY1305]
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384
In builds using BoringSSL FIPS the default cipher list is:
- ECDHE-ECDSA-AES128-GCM-SHA256
- ECDHE-RSA-AES128-GCM-SHA256
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384 | +| `ecdhCurves` | _string array_ | false | ECDHCurves specifies the set of supported ECDH curves.
In non-FIPS Envoy Proxy builds the default curves are:
- X25519
- P-256
In builds using BoringSSL FIPS the default curve is:
- P-256 | +| `signatureAlgorithms` | _string array_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | +| `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | + + #### BackendTrafficPolicy @@ -360,6 +382,26 @@ _Appears in:_ | `customHeader` | _[CustomHeaderExtensionSettings](#customheaderextensionsettings)_ | false | CustomHeader provides configuration for determining the client IP address for a request based on
a trusted custom HTTP header. This uses the the custom_header original IP detection extension.
Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto
for more details. | +#### ClientTLSSettings + + + + + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `clientValidation` | _[ClientValidationContext](#clientvalidationcontext)_ | false | ClientValidation specifies the configuration to validate the client
initiating the TLS connection to the Gateway listener. | +| `minVersion` | _[TLSVersion](#tlsversion)_ | false | Min specifies the minimal TLS protocol version to allow.
The default is TLS 1.2 if this is not specified. | +| `maxVersion` | _[TLSVersion](#tlsversion)_ | false | Max specifies the maximal TLS protocol version to allow
The default is TLS 1.3 if this is not specified. | +| `ciphers` | _string array_ | false | Ciphers specifies the set of cipher suites supported when
negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3.
In non-FIPS Envoy Proxy builds the default cipher list is:
- [ECDHE-ECDSA-AES128-GCM-SHA256\|ECDHE-ECDSA-CHACHA20-POLY1305]
- [ECDHE-RSA-AES128-GCM-SHA256\|ECDHE-RSA-CHACHA20-POLY1305]
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384
In builds using BoringSSL FIPS the default cipher list is:
- ECDHE-ECDSA-AES128-GCM-SHA256
- ECDHE-RSA-AES128-GCM-SHA256
- ECDHE-ECDSA-AES256-GCM-SHA384
- ECDHE-RSA-AES256-GCM-SHA384 | +| `ecdhCurves` | _string array_ | false | ECDHCurves specifies the set of supported ECDH curves.
In non-FIPS Envoy Proxy builds the default curves are:
- X25519
- P-256
In builds using BoringSSL FIPS the default curve is:
- P-256 | +| `signatureAlgorithms` | _string array_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | +| `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | + + #### ClientTimeout @@ -423,7 +465,7 @@ _Appears in:_ | `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ | false | TcpKeepalive settings associated with the downstream client connection.
If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives.
Disabled by default. | | `enableProxyProtocol` | _boolean_ | false | EnableProxyProtocol interprets the ProxyProtocol header and adds the
Client Address into the X-Forwarded-For header.
Note Proxy Protocol must be present when this field is set, else the connection
is closed. | | `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ | false | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. | -| `tls` | _[TLSSettings](#tlssettings)_ | false | TLS settings configure TLS termination settings with the downstream client. | +| `tls` | _[ClientTLSSettings](#clienttlssettings)_ | false | TLS settings configure TLS termination settings with the downstream client. | | `path` | _[PathSettings](#pathsettings)_ | false | Path enables managing how the incoming path set by clients can be normalized. | | `headers` | _[HeaderSettings](#headersettings)_ | false | HeaderSettings provides configuration for header management. | | `timeout` | _[ClientTimeout](#clienttimeout)_ | false | Timeout settings for the client connections. | @@ -442,7 +484,7 @@ to the Gateway. By default, no client specific configuration is validated. _Appears in:_ -- [TLSSettings](#tlssettings) +- [ClientTLSSettings](#clienttlssettings) | Field | Type | Required | Description | | --- | --- | --- | --- | @@ -1118,6 +1160,7 @@ _Appears in:_ | `extraArgs` | _string array_ | false | ExtraArgs defines additional command line options that are provided to Envoy.
More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options
Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here. | | `mergeGateways` | _boolean_ | false | MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure.
Setting this field to true would merge all Gateway Listeners under the parent Gateway Class.
This means that the port, protocol and hostname tuple must be unique for every listener.
If a duplicate listener is detected, the newer listener (based on timestamp) will be rejected and its status will be updated with a "Accepted=False" condition. | | `shutdown` | _[ShutdownConfig](#shutdownconfig)_ | false | Shutdown defines configuration for graceful envoy shutdown process. | +| `backendTLS` | _[BackendTLSConfig](#backendtlsconfig)_ | false | BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends.
These settings are applied on backends for which TLS policies are specified. | @@ -3063,7 +3106,8 @@ _Appears in:_ _Appears in:_ -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) | Field | Type | Required | Description | | --- | --- | --- | --- | @@ -3073,7 +3117,6 @@ _Appears in:_ | `ecdhCurves` | _string array_ | false | ECDHCurves specifies the set of supported ECDH curves.
In non-FIPS Envoy Proxy builds the default curves are:
- X25519
- P-256
In builds using BoringSSL FIPS the default curve is:
- P-256 | | `signatureAlgorithms` | _string array_ | false | SignatureAlgorithms specifies which signature algorithms the listener should
support. | | `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be
exposed by the listener. By default h2 and http/1.1 are enabled.
Supported values are:
- http/1.0
- http/1.1
- h2 | -| `clientValidation` | _[ClientValidationContext](#clientvalidationcontext)_ | false | ClientValidation specifies the configuration to validate the client
initiating the TLS connection to the Gateway listener. | #### TLSVersion @@ -3083,6 +3126,8 @@ _Underlying type:_ _string_ TLSVersion specifies the TLS version _Appears in:_ +- [BackendTLSConfig](#backendtlsconfig) +- [ClientTLSSettings](#clienttlssettings) - [TLSSettings](#tlssettings) | Value | Description | diff --git a/test/cel-validation/clienttrafficpolicy_test.go b/test/cel-validation/clienttrafficpolicy_test.go index 554d6240d8e..2b132ea969e 100644 --- a/test/cel-validation/clienttrafficpolicy_test.go +++ b/test/cel-validation/clienttrafficpolicy_test.go @@ -16,7 +16,6 @@ import ( "time" "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -150,9 +149,11 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MinVersion: ptr.To(egv1a1.TLSv12), - MaxVersion: ptr.To(egv1a1.TLSv11), + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MinVersion: ptr.To(egv1a1.TLSv12), + MaxVersion: ptr.To(egv1a1.TLSv11), + }, }, } }, @@ -171,8 +172,10 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MaxVersion: ptr.To(egv1a1.TLSv11), + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MaxVersion: ptr.To(egv1a1.TLSv11), + }, }, } }, @@ -217,8 +220,10 @@ func TestClientTrafficPolicyTarget(t *testing.T) { }, }, HTTP3: &egv1a1.HTTP3Settings{}, - TLS: &egv1a1.TLSSettings{ - Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + }, }, } }, @@ -235,9 +240,11 @@ func TestClientTrafficPolicyTarget(t *testing.T) { Name: gwapiv1a2.ObjectName("eg"), }, }, - TLS: &egv1a1.TLSSettings{ - MinVersion: ptr.To(egv1a1.TLSv13), - Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + TLS: &egv1a1.ClientTLSSettings{ + TLSSettings: egv1a1.TLSSettings{ + MinVersion: ptr.To(egv1a1.TLSv13), + Ciphers: []string{"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]"}, + }, }, } }, From 6407e8290947fa9785e238bb417d163918d2f613 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Fri, 26 Apr 2024 03:15:25 +0300 Subject: [PATCH 05/29] chore: resolve protoc-gen-go-grpc vulnerability (#3267) * chore: resolve protoc-gen-go-grpc vulnerability Signed-off-by: Shahar Harari * chore: resolve protoc-gen-go-grpc vulnerability Signed-off-by: Shahar Harari --------- Signed-off-by: Shahar Harari --- tools/src/protoc-gen-go-grpc/go.mod | 2 +- tools/src/protoc-gen-go-grpc/go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/src/protoc-gen-go-grpc/go.mod b/tools/src/protoc-gen-go-grpc/go.mod index 77ab0f34488..df13e99fa8f 100644 --- a/tools/src/protoc-gen-go-grpc/go.mod +++ b/tools/src/protoc-gen-go-grpc/go.mod @@ -4,4 +4,4 @@ go 1.22.2 require google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 -require google.golang.org/protobuf v1.28.1 // indirect +require google.golang.org/protobuf v1.33.0 // indirect diff --git a/tools/src/protoc-gen-go-grpc/go.sum b/tools/src/protoc-gen-go-grpc/go.sum index 8d750cf2b44..310db1131fb 100644 --- a/tools/src/protoc-gen-go-grpc/go.sum +++ b/tools/src/protoc-gen-go-grpc/go.sum @@ -1,10 +1,8 @@ -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= From 3f8d05b3bb5e5dce9644d756870459fdba811431 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Thu, 25 Apr 2024 20:05:44 -0700 Subject: [PATCH 06/29] fix CI (#3277) fix test Signed-off-by: huabing zhao Co-authored-by: zirain --- internal/xds/translator/translator_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index 6c820adf15b..28868500b68 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -94,9 +94,6 @@ func TestTranslateXds(t *testing.T) { "tracing-invalid": { errMsg: "validation failed for xds resource", }, - { - name: "http-preserve-client-protocol", - }, } inputFiles, err := filepath.Glob(filepath.Join("testdata", "in", "xds-ir", "*.yaml")) From f8ede249d65ff1a195b0de2a1be8b336a5c09c65 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Sat, 27 Apr 2024 14:11:47 +0300 Subject: [PATCH 07/29] ci: add trivy image vulnerabilities scan workflow (#3287) * ci: add trivy image scan workflow Signed-off-by: Shahar Harari * fix lint errors Signed-off-by: Shahar Harari --------- Signed-off-by: Shahar Harari --- .github/workflows/trivy.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/trivy.yml diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 00000000000..7e20d40b8dd --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,31 @@ +name: trivy + +on: + push: + branches: + - "main" + schedule: + - cron: '55 17 * * 5' + +permissions: + contents: read + +jobs: + image-scan: + permissions: + contents: read # for actions/checkout to fetch code + name: Image Scan + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + + - name: Build an image from Dockerfile + run: | + IMAGE=envoy-proxy/gateway-dev TAG=${{ github.sha }} make image + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 + with: + image-ref: envoy-proxy/gateway-dev:${{ github.sha }} + exit-code: '1' From 2322ef0a405f5aeb72ec9d5accb9a722d90775c3 Mon Sep 17 00:00:00 2001 From: shahar-h Date: Sun, 28 Apr 2024 14:13:35 +0300 Subject: [PATCH 08/29] ci: add badges for security scans (#3288) * ci: add badges for security scans Signed-off-by: Shahar Harari * change trivy workflow name to upper-case Signed-off-by: Shahar Harari * trivy -> Trivy Signed-off-by: Shahar Harari --------- Signed-off-by: Shahar Harari --- .github/workflows/trivy.yml | 2 +- README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 7e20d40b8dd..d8e8c9eeebe 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -1,4 +1,4 @@ -name: trivy +name: Trivy on: push: diff --git a/README.md b/README.md index 8529e20b15f..25fa9af8d94 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/envoyproxy/gateway/badge)](https://securityscorecards.dev/viewer/?uri=github.com/envoyproxy/gateway) [![Build and Test](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml) [![codecov](https://codecov.io/gh/envoyproxy/gateway/branch/main/graph/badge.svg)](https://codecov.io/gh/envoyproxy/gateway) +[![CodeQL](https://github.com/envoyproxy/gateway/actions/workflows/codeql.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/codeql.yml) +[![OSV-Scanner](https://github.com/envoyproxy/gateway/actions/workflows/osv-scanner.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/osv-scanner.yml) +[![Trivy](https://github.com/envoyproxy/gateway/actions/workflows/trivy.yml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/trivy.yml) Envoy Gateway is an open source project for managing Envoy Proxy as a standalone or Kubernetes-based application gateway. From 57471234a5ce0c639aee3a3bb196d84be69706b1 Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 30 Apr 2024 05:30:53 +0800 Subject: [PATCH 09/29] lint: enable gofumpt (#3291) Signed-off-by: zirain --- api/v1alpha1/clienttrafficpolicy_types.go | 3 +- api/v1alpha1/compression_types.go | 3 +- api/v1alpha1/envoygateway_types.go | 1 - api/v1alpha1/fault_injection.go | 1 - api/v1alpha1/healthcheck_types.go | 1 - api/v1alpha1/jwt_types.go | 2 - .../validation/envoygateway_validate_test.go | 6 +- .../validation/envoyproxy_validate.go | 6 +- .../validation/envoyproxy_validate_test.go | 21 +- internal/admin/server.go | 4 +- internal/cmd/egctl/config_ratelimit.go | 11 +- internal/cmd/egctl/config_test.go | 26 +- internal/cmd/egctl/envoy_stats.go | 4 +- internal/cmd/egctl/install.go | 1 - internal/cmd/egctl/translate.go | 6 +- internal/cmd/egctl/translate_test.go | 5 +- internal/cmd/egctl/uninstall.go | 1 - internal/cmd/envoy/shutdown_manager.go | 10 +- internal/cmd/server.go | 6 +- internal/cmd/server_test.go | 1 - internal/crypto/certgen.go | 1 - internal/crypto/certgen_test.go | 1 - internal/envoygateway/config/decoder_test.go | 4 +- internal/envoygateway/scheme.go | 16 +- internal/extension/registry/xds_hook.go | 4 - internal/extension/testutils/hooks.go | 2 - internal/gatewayapi/backendtlspolicy.go | 5 +- internal/gatewayapi/backendtrafficpolicy.go | 5 +- internal/gatewayapi/clienttrafficpolicy.go | 9 +- internal/gatewayapi/envoyextensionpolicy.go | 12 +- internal/gatewayapi/ext_service.go | 3 +- internal/gatewayapi/filters.go | 22 +- internal/gatewayapi/resource.go | 6 +- internal/gatewayapi/route.go | 14 +- internal/gatewayapi/runner/runner_test.go | 4 +- internal/gatewayapi/securitypolicy.go | 24 +- internal/gatewayapi/sort.go | 1 - internal/gatewayapi/tls.go | 1 - internal/gatewayapi/translator.go | 4 +- internal/gatewayapi/translator_test.go | 6 +- internal/gatewayapi/validate.go | 28 +- .../kubernetes/proxy/resource.go | 3 +- .../proxy/resource_provider_test.go | 11 +- .../kubernetes/proxy_infra_test.go | 1 - .../kubernetes/ratelimit/resource.go | 9 +- .../ratelimit/resource_provider_test.go | 14 +- .../kubernetes/ratelimit/resource_test.go | 2 - .../kubernetes/resource/resource_test.go | 6 +- internal/infrastructure/runner/runner.go | 2 +- internal/ir/xds_test.go | 312 +++++++++--------- internal/kubernetes/port_forwarder.go | 1 - internal/logging/log.go | 2 +- internal/message/watchutil.go | 2 +- internal/metrics/metadata.go | 3 +- internal/metrics/metrics_test.go | 9 +- internal/provider/kubernetes/controller.go | 26 +- internal/provider/kubernetes/helpers.go | 4 +- .../provider/kubernetes/kubernetes_test.go | 23 +- internal/provider/kubernetes/predicates.go | 1 - internal/provider/kubernetes/routes.go | 15 +- internal/provider/kubernetes/secrets.go | 4 +- internal/provider/kubernetes/status.go | 3 +- internal/status/conditions.go | 3 +- internal/status/policy.go | 7 +- internal/utils/field/field_test.go | 29 +- internal/utils/file/file.go | 2 +- internal/utils/helm/package.go | 17 +- internal/utils/protocov/protocov.go | 4 +- internal/xds/bootstrap/bootstrap_test.go | 2 +- internal/xds/bootstrap/util_test.go | 6 +- internal/xds/translator/accesslog.go | 14 +- internal/xds/translator/basicauth.go | 3 +- internal/xds/translator/cluster.go | 12 +- internal/xds/translator/cors.go | 6 +- internal/xds/translator/extauth.go | 6 +- internal/xds/translator/extproc.go | 6 +- internal/xds/translator/fault.go | 5 +- internal/xds/translator/httpfilters.go | 10 +- internal/xds/translator/jwt.go | 9 +- internal/xds/translator/listener.go | 8 +- internal/xds/translator/local_ratelimit.go | 9 +- internal/xds/translator/oidc.go | 16 +- internal/xds/translator/runner/runner_test.go | 1 - internal/xds/translator/tcpkeepalive.go | 1 - internal/xds/translator/translator.go | 6 +- internal/xds/translator/wasm.go | 6 +- internal/xds/types/resourceversiontable.go | 2 +- .../backendtrafficpolicy_test.go | 2 - test/conformance/conformance_test.go | 1 - .../experimental_conformance_test.go | 2 +- test/e2e/tests/backend_tls.go | 1 - test/e2e/tests/connection_limit.go | 1 - test/e2e/tests/gateway_infra_resource.go | 2 +- test/e2e/tests/jwt.go | 1 - test/e2e/tests/merge_gateways.go | 1 - test/e2e/tests/preservecase.go | 1 - test/e2e/tests/ratelimit.go | 1 - .../redirect_replaceprefixmatch_slash.go | 1 - test/e2e/tests/retry.go | 1 - test/e2e/tests/tcp_route.go | 2 - test/e2e/tests/tracing.go | 1 - test/e2e/tests/weighted_backend.go | 4 - tools/linter/golangci-lint/.golangci.yml | 1 + 103 files changed, 462 insertions(+), 495 deletions(-) diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 882f094a071..8f85d0617c7 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -176,8 +176,7 @@ type CustomHeaderExtensionSettings struct { } // HTTP3Settings provides HTTP/3 configuration on the listener. -type HTTP3Settings struct { -} +type HTTP3Settings struct{} // HTTP1Settings provides HTTP/1 configuration on the listener. type HTTP1Settings struct { diff --git a/api/v1alpha1/compression_types.go b/api/v1alpha1/compression_types.go index 37c0ec8587b..73cb0109ae5 100644 --- a/api/v1alpha1/compression_types.go +++ b/api/v1alpha1/compression_types.go @@ -13,8 +13,7 @@ type CompressorType string // GzipCompressor defines the config for the Gzip compressor. // The default values can be found here: // https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor -type GzipCompressor struct { -} +type GzipCompressor struct{} // Compression defines the config of enabling compression. // This can help reduce the bandwidth at the expense of higher CPU. diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index ade9e056b1e..3ae313dc409 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -506,7 +506,6 @@ type ExtensionTLS struct { // EnvoyGatewayAdmin defines the Envoy Gateway Admin configuration. type EnvoyGatewayAdmin struct { - // Address defines the address of Envoy Gateway Admin Server. // // +optional diff --git a/api/v1alpha1/fault_injection.go b/api/v1alpha1/fault_injection.go index d27a5c5ee12..a8b7e1f5412 100644 --- a/api/v1alpha1/fault_injection.go +++ b/api/v1alpha1/fault_injection.go @@ -13,7 +13,6 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // // +kubebuilder:validation:XValidation:rule=" has(self.delay) || has(self.abort) ",message="Delay and abort faults are set at least one." type FaultInjection struct { - // If specified, a delay will be injected into the request. // // +optional diff --git a/api/v1alpha1/healthcheck_types.go b/api/v1alpha1/healthcheck_types.go index 61172273e3d..cea83d2f5a1 100644 --- a/api/v1alpha1/healthcheck_types.go +++ b/api/v1alpha1/healthcheck_types.go @@ -22,7 +22,6 @@ type HealthCheck struct { // PassiveHealthCheck defines the configuration for passive health checks in the context of Envoy's Outlier Detection, // see https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier type PassiveHealthCheck struct { - // SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. // // +kubebuilder:default=false diff --git a/api/v1alpha1/jwt_types.go b/api/v1alpha1/jwt_types.go index 4f844b0e9fc..4bc8a994f5d 100644 --- a/api/v1alpha1/jwt_types.go +++ b/api/v1alpha1/jwt_types.go @@ -7,7 +7,6 @@ package v1alpha1 // JWT defines the configuration for JSON Web Token (JWT) authentication. type JWT struct { - // Optional determines whether a missing JWT is acceptable, defaulting to false if not specified. // Note: Even if optional is set to true, JWT authentication will still fail if an invalid JWT is presented. Optional *bool `json:"optional,omitempty"` @@ -91,7 +90,6 @@ type RemoteJWKS struct { // ClaimToHeader defines a configuration to convert JWT claims into HTTP headers type ClaimToHeader struct { - // Header defines the name of the HTTP request header that the JWT Claim will be saved into. Header string `json:"header"` diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 6978a52e35f..aa76a90ec7b 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -660,7 +660,8 @@ func TestEnvoyGatewayProvider(t *testing.T) { Replicas: nil, Pod: nil, Container: nil, - }} + }, + } assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas) assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod) assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container) @@ -674,7 +675,8 @@ func TestEnvoyGatewayProvider(t *testing.T) { SecurityContext: nil, Image: nil, }, - }} + }, + } assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources) envoyGatewayProvider.GetEnvoyGatewayKubeProvider() diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index b885d8fadfc..0e4f7e22221 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -110,14 +110,12 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error { errs = append(errs, fmt.Errorf("unsupported envoy service type %v", serviceType)) } } - if serviceType, serviceAllocateLoadBalancerNodePorts := - spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.AllocateLoadBalancerNodePorts; serviceType != nil && serviceAllocateLoadBalancerNodePorts != nil { + if serviceType, serviceAllocateLoadBalancerNodePorts := spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.AllocateLoadBalancerNodePorts; serviceType != nil && serviceAllocateLoadBalancerNodePorts != nil { if *serviceType != egv1a1.ServiceTypeLoadBalancer { errs = append(errs, fmt.Errorf("allocateLoadBalancerNodePorts can only be set for %v type", egv1a1.ServiceTypeLoadBalancer)) } } - if serviceType, serviceLoadBalancerSourceRanges := - spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.LoadBalancerSourceRanges; serviceType != nil && serviceLoadBalancerSourceRanges != nil { + if serviceType, serviceLoadBalancerSourceRanges := spec.Provider.Kubernetes.EnvoyService.Type, spec.Provider.Kubernetes.EnvoyService.LoadBalancerSourceRanges; serviceType != nil && serviceLoadBalancerSourceRanges != nil { if *serviceType != egv1a1.ServiceTypeLoadBalancer { errs = append(errs, fmt.Errorf("loadBalancerSourceRanges can only be set for %v type", egv1a1.ServiceTypeLoadBalancer)) } diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go index 27ab08f3091..6619888bdc8 100644 --- a/api/v1alpha1/validation/envoyproxy_validate_test.go +++ b/api/v1alpha1/validation/envoyproxy_validate_test.go @@ -447,7 +447,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should invalid when metrics type is OpenTelemetry, but `OpenTelemetry` field being empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -467,7 +468,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should valid when metrics type is OpenTelemetry and `OpenTelemetry` field being not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -491,7 +493,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should be invalid when service patch type is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -514,7 +517,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should be invalid when deployment patch type is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -537,7 +541,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should invalid when patch object is empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -558,7 +563,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: false, - }, { + }, + { name: "should valid when patch type and object are both not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ @@ -582,7 +588,8 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, - }, { + }, + { name: "should valid when patch type is empty and object is not empty", proxy: &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ diff --git a/internal/admin/server.go b/internal/admin/server.go index 9c035b43816..29901814381 100644 --- a/internal/admin/server.go +++ b/internal/admin/server.go @@ -17,9 +17,7 @@ import ( "github.com/envoyproxy/gateway/internal/logging" ) -var ( - adminLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") -) +var adminLogger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("admin") func Init(cfg *config.Server) error { if cfg.EnvoyGateway.GetEnvoyGatewayAdmin().EnableDumpConfig { diff --git a/internal/cmd/egctl/config_ratelimit.go b/internal/cmd/egctl/config_ratelimit.go index 376ff65cd06..089a52f1f69 100644 --- a/internal/cmd/egctl/config_ratelimit.go +++ b/internal/cmd/egctl/config_ratelimit.go @@ -32,10 +32,7 @@ var ( ) func ratelimitConfigCommand() *cobra.Command { - - var ( - namespace string - ) + var namespace string rlConfigCmd := &cobra.Command{ Use: "envoy-ratelimit", @@ -57,7 +54,6 @@ func ratelimitConfigCommand() *cobra.Command { } func runRateLimitConfig(c *cobra.Command, ns string) error { - cli, err := getCLIClient() if err != nil { return err @@ -73,7 +69,6 @@ func runRateLimitConfig(c *cobra.Command, ns string) error { } func retrieveRateLimitConfig(cli kubernetes.CLIClient, ns string) ([]byte, error) { - // Before retrieving the rate limit configuration // we make sure that the global rate limit feature is enabled if enable, err := checkEnableGlobalRateLimit(cli); !enable { @@ -103,7 +98,6 @@ func retrieveRateLimitConfig(cli kubernetes.CLIClient, ns string) ([]byte, error // fetchRunningRateLimitPods gets the rate limit Pods, based on the labelSelectors. // It further filters out only those rate limit Pods that are in "Running" state. func fetchRunningRateLimitPods(cli kubernetes.CLIClient, namespace string, labelSelector []string) ([]types.NamespacedName, error) { - // Since multiple replicas of the rate limit are configured to be equal, // we do not need to use the pod name to obtain the specified pod. rlPods, err := cli.PodsForSelector(namespace, labelSelector...) @@ -134,7 +128,6 @@ func fetchRunningRateLimitPods(cli kubernetes.CLIClient, namespace string, label // checkRateLimitPodStatusReady Check that the rate limit pod is ready func checkRateLimitPodStatusReady(status corev1.PodStatus) bool { - if status.Phase != corev1.PodRunning { return false } @@ -152,7 +145,6 @@ func checkRateLimitPodStatusReady(status corev1.PodStatus) bool { // extractRateLimitConfig After turning on port forwarding through PortForwarder, // construct a request and send it to the rate limit Pod to obtain relevant configuration information. func extractRateLimitConfig(fw kubernetes.PortForwarder, rlPod types.NamespacedName) ([]byte, error) { - if err := fw.Start(); err != nil { return nil, fmt.Errorf("failed to start port forwarding for pod %s/%s: %w", rlPod.Namespace, rlPod.Name, err) } @@ -168,7 +160,6 @@ func extractRateLimitConfig(fw kubernetes.PortForwarder, rlPod types.NamespacedN // checkEnableGlobalRateLimit Check whether the Global Rate Limit function is enabled func checkEnableGlobalRateLimit(cli kubernetes.CLIClient) (bool, error) { - kubeCli := cli.Kube() cm, err := kubeCli.CoreV1(). ConfigMaps(defaultRateLimitNamespace). diff --git a/internal/cmd/egctl/config_test.go b/internal/cmd/egctl/config_test.go index ff1ad2f8ace..8d1eb45b934 100644 --- a/internal/cmd/egctl/config_test.go +++ b/internal/cmd/egctl/config_test.go @@ -156,7 +156,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: BootstrapEnvoyConfigType, expected: "out.bootstrap.yaml", - }, { + }, + { output: "json", resourceType: ClusterEnvoyConfigType, expected: "out.cluster.json", @@ -165,7 +166,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: ClusterEnvoyConfigType, expected: "out.cluster.yaml", - }, { + }, + { output: "json", resourceType: ListenerEnvoyConfigType, expected: "out.listener.json", @@ -174,7 +176,8 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { output: "yaml", resourceType: ListenerEnvoyConfigType, expected: "out.listener.yaml", - }, { + }, + { output: "json", resourceType: RouteEnvoyConfigType, expected: "out.route.json", @@ -303,7 +306,6 @@ func (f *fakeCLIClient) Kube() kubernetes.Interface { } func TestFetchRunningRateLimitPods(t *testing.T) { - cases := []struct { caseName string rlPods []corev1.Pod @@ -363,23 +365,18 @@ func TestFetchRunningRateLimitPods(t *testing.T) { } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fakeCli := &fakeCLIClient{ pods: tc.rlPods, } _, err := fetchRunningRateLimitPods(fakeCli, tc.namespace, tc.labelSelector) require.Equal(t, tc.expectErr, err) - }) - } } func TestCheckEnableGlobalRateLimit(t *testing.T) { - cases := []struct { caseName string egConfigMap *corev1.ConfigMap @@ -433,9 +430,7 @@ gateway: } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fakeCli := &fakeCLIClient{ cm: tc.egConfigMap, } @@ -443,14 +438,11 @@ gateway: actual, err := checkEnableGlobalRateLimit(fakeCli) require.Equal(t, tc.expect, actual) require.NoError(t, err) - }) - } } func TestExtractRateLimitConfig(t *testing.T) { - cases := []struct { caseName string responseBody []byte @@ -467,23 +459,18 @@ func TestExtractRateLimitConfig(t *testing.T) { } for _, tc := range cases { - t.Run(tc.caseName, func(t *testing.T) { - fw, err := newFakePortForwarder(tc.responseBody) require.NoError(t, err) out, err := extractRateLimitConfig(fw, tc.rlPod) require.NoError(t, err) require.NotEmpty(t, out) - }) - } } func TestCheckRateLimitPodStatusReady(t *testing.T) { - cases := []struct { caseName string status corev1.PodStatus @@ -538,5 +525,4 @@ func TestCheckRateLimitPodStatusReady(t *testing.T) { require.Equal(t, tc.expect, actual) }) } - } diff --git a/internal/cmd/egctl/envoy_stats.go b/internal/cmd/egctl/envoy_stats.go index c7701da0bcd..c8b22c8d05d 100644 --- a/internal/cmd/egctl/envoy_stats.go +++ b/internal/cmd/egctl/envoy_stats.go @@ -24,9 +24,7 @@ const ( prometheusOutput = "prom" ) -var ( - statsType, outputFormat string -) +var statsType, outputFormat string func newEnvoyStatsCmd() *cobra.Command { var podName, podNamespace string diff --git a/internal/cmd/egctl/install.go b/internal/cmd/egctl/install.go index 640dfca0bd0..076ecb8d2f2 100644 --- a/internal/cmd/egctl/install.go +++ b/internal/cmd/egctl/install.go @@ -13,7 +13,6 @@ import ( ) func newInstallCommand() *cobra.Command { - packageFlags := &helm.PackageOptions{} pt := helm.NewPackageTool() diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index a441378f52a..9d21b20105e 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -161,12 +161,14 @@ func getValidOutputTypesStr() string { } func validResourceTypes() []envoyConfigType { - return []envoyConfigType{BootstrapEnvoyConfigType, + return []envoyConfigType{ + BootstrapEnvoyConfigType, EndpointEnvoyConfigType, ClusterEnvoyConfigType, ListenerEnvoyConfigType, RouteEnvoyConfigType, - AllEnvoyConfigType} + AllEnvoyConfigType, + } } func isValidResourceType(outType envoyConfigType) bool { diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 6159b832b41..96707159a99 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -26,9 +26,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils/file" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestTranslate(t *testing.T) { testCases := []struct { @@ -353,7 +351,6 @@ func TestTranslate(t *testing.T) { mustUnmarshal(t, requireTestDataOutFile(t, fn), want) opts := cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime") require.Empty(t, cmp.Diff(want, got, opts)) - }) } } diff --git a/internal/cmd/egctl/uninstall.go b/internal/cmd/egctl/uninstall.go index 769222fe271..9241db83197 100644 --- a/internal/cmd/egctl/uninstall.go +++ b/internal/cmd/egctl/uninstall.go @@ -13,7 +13,6 @@ import ( ) func newUnInstallCommand() *cobra.Command { - packageFlags := &helm.PackageOptions{} pt := helm.NewPackageTool() diff --git a/internal/cmd/envoy/shutdown_manager.go b/internal/cmd/envoy/shutdown_manager.go index 5f517365c74..257a3d323bc 100644 --- a/internal/cmd/envoy/shutdown_manager.go +++ b/internal/cmd/envoy/shutdown_manager.go @@ -23,9 +23,7 @@ import ( "github.com/envoyproxy/gateway/internal/xds/bootstrap" ) -var ( - logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("shutdown-manager") -) +var logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("shutdown-manager") const ( // ShutdownManagerPort is the port Envoy shutdown manager will listen on. @@ -88,7 +86,7 @@ func ShutdownManager(readyTimeout time.Duration) error { // container to block until ready to terminate. After the graceful drain process // has completed a file will be written to indicate shutdown readiness. func shutdownReadyHandler(w http.ResponseWriter, readyTimeout time.Duration, readyFile string) { - var startTime = time.Now() + startTime := time.Now() logger.Info("received shutdown ready request") @@ -119,8 +117,8 @@ func shutdownReadyHandler(w http.ResponseWriter, readyTimeout time.Duration, rea // it will initiate a graceful drain sequence on the Envoy proxy and block until // connections are drained or a timeout is exceeded. func Shutdown(drainTimeout time.Duration, minDrainDuration time.Duration, exitAtConnections int) error { - var startTime = time.Now() - var allowedToExit = false + startTime := time.Now() + allowedToExit := false // Reconfigure logger to write to stdout of main process if running in Kubernetes if _, k8s := os.LookupEnv("KUBERNETES_SERVICE_HOST"); k8s && os.Getpid() != 1 { diff --git a/internal/cmd/server.go b/internal/cmd/server.go index 6dc25a19946..e4bf36a5ae5 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -23,10 +23,8 @@ import ( xdstranslatorrunner "github.com/envoyproxy/gateway/internal/xds/translator/runner" ) -var ( - // cfgPath is the path to the EnvoyGateway configuration file. - cfgPath string -) +// cfgPath is the path to the EnvoyGateway configuration file. +var cfgPath string // getServerCommand returns the server cobra command to be executed. func getServerCommand() *cobra.Command { diff --git a/internal/cmd/server_test.go b/internal/cmd/server_test.go index b6608445e3d..dffe10670c9 100644 --- a/internal/cmd/server_test.go +++ b/internal/cmd/server_test.go @@ -71,5 +71,4 @@ func TestGetConfigValidate(t *testing.T) { } }) } - } diff --git a/internal/crypto/certgen.go b/internal/crypto/certgen.go index 6c6ef10ccbf..de5a6584843 100644 --- a/internal/crypto/certgen.go +++ b/internal/crypto/certgen.go @@ -225,7 +225,6 @@ func newCert(request *certificateRequest) ([]byte, []byte, error) { Bytes: newCert, }) return newCertPEM, newKeyPEM, nil - } // newCA generates a new CA, given the CA's CN and an expiry time. diff --git a/internal/crypto/certgen_test.go b/internal/crypto/certgen_test.go index eb09d6d2c34..429fea518e7 100644 --- a/internal/crypto/certgen_test.go +++ b/internal/crypto/certgen_test.go @@ -129,7 +129,6 @@ func TestGeneratedValidKubeCerts(t *testing.T) { require.NoErrorf(t, err, "Validating %s failed", tc.name) }) } - } func verifyCert(certPEM []byte, roots *x509.CertPool, dnsname string, currentTime time.Time) error { diff --git a/internal/envoygateway/config/decoder_test.go b/internal/envoygateway/config/decoder_test.go index d8c8e36a230..28ce394cb7c 100644 --- a/internal/envoygateway/config/decoder_test.go +++ b/internal/envoygateway/config/decoder_test.go @@ -18,9 +18,7 @@ import ( "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - inPath = "./testdata/decoder/in/" -) +var inPath = "./testdata/decoder/in/" func TestDecode(t *testing.T) { testCases := []struct { diff --git a/internal/envoygateway/scheme.go b/internal/envoygateway/scheme.go index 911ae708351..78567e9208c 100644 --- a/internal/envoygateway/scheme.go +++ b/internal/envoygateway/scheme.go @@ -16,15 +16,13 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - // scheme contains all the API types necessary for the provider's dynamic - // clients to work. Any new non-core types must be added here. - // - // NOTE: The discovery mechanism used by the client doesn't automatically - // refresh, so only add types here that are guaranteed to exist before the - // provider starts. - scheme = runtime.NewScheme() -) +// scheme contains all the API types necessary for the provider's dynamic +// clients to work. Any new non-core types must be added here. +// +// NOTE: The discovery mechanism used by the client doesn't automatically +// refresh, so only add types here that are guaranteed to exist before the +// provider starts. +var scheme = runtime.NewScheme() func init() { if err := clientgoscheme.AddToScheme(scheme); err != nil { diff --git a/internal/extension/registry/xds_hook.go b/internal/extension/registry/xds_hook.go index a7962d62e7f..e53d90dcd5e 100644 --- a/internal/extension/registry/xds_hook.go +++ b/internal/extension/registry/xds_hook.go @@ -53,7 +53,6 @@ func (h *XDSHook) PostRouteModifyHook(route *route.Route, routeHostnames []strin ExtensionResources: extensionResourceBytes, }, }) - if err != nil { return nil, err } @@ -69,7 +68,6 @@ func (h *XDSHook) PostVirtualHostModifyHook(vh *route.VirtualHost) (*route.Virtu VirtualHost: vh, PostVirtualHostContext: &extension.PostVirtualHostExtensionContext{}, }) - if err != nil { return nil, err } @@ -85,7 +83,6 @@ func (h *XDSHook) PostHTTPListenerModifyHook(l *listener.Listener) (*listener.Li Listener: l, PostListenerContext: &extension.PostHTTPListenerExtensionContext{}, }) - if err != nil { return nil, err } @@ -102,7 +99,6 @@ func (h *XDSHook) PostTranslateModifyHook(clusters []*cluster.Cluster, secrets [ Clusters: clusters, Secrets: secrets, }) - if err != nil { return nil, nil, err } diff --git a/internal/extension/testutils/hooks.go b/internal/extension/testutils/hooks.go index f6b699b34b8..b7b38c1660f 100644 --- a/internal/extension/testutils/hooks.go +++ b/internal/extension/testutils/hooks.go @@ -103,7 +103,6 @@ func (c *XDSHookClient) PostVirtualHostModifyHook(vh *routeV3.VirtualHost) (*rou // A more useful use-case for an extension would be looping through the FilterChains to find the // HTTPConnectionManager(s) and inject a custom HTTPFilter, but that for testing purposes we don't need to make a complex change func (c *XDSHookClient) PostHTTPListenerModifyHook(l *listenerV3.Listener) (*listenerV3.Listener, error) { - // Only make the change when the listener's name matches the expected testdata // This prevents us from having to update every single testfile.out if l.Name == "extension-post-xdslistener-hook-error" { @@ -120,7 +119,6 @@ func (c *XDSHookClient) PostHTTPListenerModifyHook(l *listenerV3.Listener) (*lis // PostTranslateModifyHook inserts and overrides some clusters/secrets func (c *XDSHookClient) PostTranslateModifyHook(clusters []*clusterV3.Cluster, secrets []*tlsV3.Secret) ([]*clusterV3.Cluster, []*tlsV3.Secret, error) { - extensionSvcEndpoint := &endpointV3.LbEndpoint_Endpoint{ Endpoint: &endpointV3.Endpoint{ Address: &coreV3.Address{ diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index d0b21b35428..3dcfc9ad214 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -21,7 +21,8 @@ func (t *Translator) processBackendTLSPolicy( backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1a2.ParentReference, - resources *Resources) *ir.TLSUpstreamConfig { + resources *Resources, +) *ir.TLSUpstreamConfig { tlsBundle, err := getBackendTLSBundle(resources.BackendTLSPolicies, resources.ConfigMaps, backendRef, backendNamespace) if err == nil && tlsBundle == nil { return nil @@ -108,7 +109,6 @@ func (t *Translator) processBackendTLSPolicy( } func backendTLSTargetMatched(policy gwapiv1a2.BackendTLSPolicy, target gwapiv1a2.PolicyTargetReferenceWithSectionName) bool { - policyTarget := policy.Spec.TargetRef if target.Group == policyTarget.Group && @@ -134,7 +134,6 @@ func getBackendTLSPolicy(policies []*gwapiv1a2.BackendTLSPolicy, backendRef gwap } func getBackendTLSBundle(policies []*gwapiv1a2.BackendTLSPolicy, configmaps []*corev1.ConfigMap, backendRef gwapiv1a2.BackendObjectReference, backendNamespace string) (*ir.TLSUpstreamConfig, error) { - backendTLSPolicy := getBackendTLSPolicy(policies, backendRef, backendNamespace) if backendTLSPolicy == nil { diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 55f79723be3..b77a551d439 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -31,7 +31,8 @@ import ( func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv1a1.BackendTrafficPolicy, gateways []*GatewayContext, routes []RouteContext, - xdsIR XdsIRMap) []*egv1a1.BackendTrafficPolicy { + xdsIR XdsIRMap, +) []*egv1a1.BackendTrafficPolicy { var res []*egv1a1.BackendTrafficPolicy // Sort based on timestamp @@ -631,7 +632,7 @@ func (t *Translator) buildLocalRateLimit(policy *egv1a1.BackendTrafficPolicy) (* var err error var irRule *ir.RateLimitRule - var irRules = make([]*ir.RateLimitRule, 0) + irRules := make([]*ir.RateLimitRule, 0) for _, rule := range local.Rules { // We don't process the rule without clientSelectors here because it's // previously used as the default route-level limit. diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 866e9844289..d4d059dc462 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -41,7 +41,8 @@ func hasSectionName(policy *egv1a1.ClientTrafficPolicy) bool { func (t *Translator) ProcessClientTrafficPolicies(resources *Resources, gateways []*GatewayContext, - xdsIR XdsIRMap, infraIR InfraIRMap) []*egv1a1.ClientTrafficPolicy { + xdsIR XdsIRMap, infraIR InfraIRMap, +) []*egv1a1.ClientTrafficPolicy { var res []*egv1a1.ClientTrafficPolicy clientTrafficPolicies := resources.ClientTrafficPolicies @@ -362,7 +363,8 @@ func validatePortOverlapForClientTrafficPolicy(l *ListenerContext, xds *ir.Xds, } func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.ClientTrafficPolicy, l *ListenerContext, - xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources) error { + xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources, +) error { // Find IR irKey := t.getIRKey(l.gateway) // It must exist since we've already finished processing the gateways @@ -632,7 +634,8 @@ func translateHTTP2Settings(http2Settings *egv1a1.HTTP2Settings, httpIR *ir.HTTP } func (t *Translator) translateListenerTLSParameters(policy *egv1a1.ClientTrafficPolicy, - httpIR *ir.HTTPListener, resources *Resources) error { + httpIR *ir.HTTPListener, resources *Resources, +) error { // Return if this listener isn't a TLS listener. There has to be // at least one certificate defined, which would cause httpIR to // have a TLS structure. diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 3c0305db71b..655d4cb798b 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -30,7 +30,8 @@ func (t *Translator) ProcessEnvoyExtensionPolicies(envoyExtensionPolicies []*egv gateways []*GatewayContext, routes []RouteContext, resources *Resources, - xdsIR XdsIRMap) []*egv1a1.EnvoyExtensionPolicy { + xdsIR XdsIRMap, +) []*egv1a1.EnvoyExtensionPolicy { var res []*egv1a1.EnvoyExtensionPolicy // Sort based on timestamp @@ -293,7 +294,8 @@ func resolveEEPolicyRouteTargetRef(policy *egv1a1.EnvoyExtensionPolicy, routes m } func (t *Translator) translateEnvoyExtensionPolicyForRoute(policy *egv1a1.EnvoyExtensionPolicy, route RouteContext, - xdsIR XdsIRMap, resources *Resources) error { + xdsIR XdsIRMap, resources *Resources, +) error { var ( extProcs []ir.ExtProc wasms []ir.Wasm @@ -343,7 +345,8 @@ func (t *Translator) buildExtProcs(policy *egv1a1.EnvoyExtensionPolicy, resource } func (t *Translator) translateEnvoyExtensionPolicyForGateway(policy *egv1a1.EnvoyExtensionPolicy, - gateway *GatewayContext, xdsIR XdsIRMap, resources *Resources) error { + gateway *GatewayContext, xdsIR XdsIRMap, resources *Resources, +) error { var ( extProcs []ir.ExtProc wasms []ir.Wasm @@ -398,7 +401,8 @@ func (t *Translator) buildExtProc( policyNamespacedName types.NamespacedName, extProc egv1a1.ExtProc, extProcIdx int, - resources *Resources) (*ir.ExtProc, error) { + resources *Resources, +) (*ir.ExtProc, error) { var ( backendRef *gwapiv1.BackendObjectReference ds *ir.DestinationSetting diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index a14e2b1258e..6a9a5e225dc 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -26,7 +26,8 @@ func (t *Translator) processExtServiceDestination( policyNamespacedName types.NamespacedName, policyKind string, protocol ir.AppProtocol, - resources *Resources) (*ir.DestinationSetting, error) { + resources *Resources, +) (*ir.DestinationSetting, error) { var ( endpoints []*ir.DestinationEndpoint addrType *ir.DestinationAddressType diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index c728e1e863b..1cde4541f48 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -64,7 +64,8 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, route RouteContext, filters []gwapiv1.HTTPRouteFilter, ruleIdx int, - resources *Resources) *HTTPFiltersContext { + resources *Resources, +) *HTTPFiltersContext { httpFiltersContext := &HTTPFiltersContext{ ParentRef: parentRef, Route: route, @@ -107,7 +108,8 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext, func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, route RouteContext, filters []v1alpha2.GRPCRouteFilter, - resources *Resources) *HTTPFiltersContext { + resources *Resources, +) *HTTPFiltersContext { httpFiltersContext := &HTTPFiltersContext{ ParentRef: parentRef, Route: route, @@ -144,7 +146,8 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext, func (t *Translator) processURLRewriteFilter( rewrite *gwapiv1.HTTPURLRewriteFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { if filterContext.URLRewrite != nil { filterContext.ParentRef.SetCondition(filterContext.Route, gwapiv1.RouteConditionAccepted, @@ -246,7 +249,8 @@ func (t *Translator) processURLRewriteFilter( func (t *Translator) processRedirectFilter( redirect *gwapiv1.HTTPRequestRedirectFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Can't have two redirects for the same route if filterContext.RedirectResponse != nil { filterContext.ParentRef.SetCondition(filterContext.Route, @@ -347,7 +351,8 @@ func (t *Translator) processRedirectFilter( func (t *Translator) processRequestHeaderModifierFilter( headerModifier *gwapiv1.HTTPHeaderFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Make sure the header modifier config actually exists if headerModifier == nil { return @@ -500,7 +505,8 @@ func (t *Translator) processRequestHeaderModifierFilter( func (t *Translator) processResponseHeaderModifierFilter( headerModifier *gwapiv1.HTTPHeaderFilter, - filterContext *HTTPFiltersContext) { + filterContext *HTTPFiltersContext, +) { // Make sure the header modifier config actually exists if headerModifier == nil { return @@ -693,8 +699,8 @@ func (t *Translator) processRequestMirrorFilter( filterIdx int, mirrorFilter *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, - resources *Resources) { - + resources *Resources, +) { // Make sure the config actually exists if mirrorFilter == nil { return diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index f930801c2bf..7ba85502b99 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -22,8 +22,10 @@ import ( "github.com/envoyproxy/gateway/internal/ir" ) -type XdsIRMap map[string]*ir.Xds -type InfraIRMap map[string]*ir.Infra +type ( + XdsIRMap map[string]*ir.Xds + InfraIRMap map[string]*ir.Infra +) // Resources holds the Gateway API and related // resources that the translators needs as inputs. diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 1b0ac613bdd..ce2efc55be6 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -132,7 +132,7 @@ func (t *Translator) processHTTPRouteParentRefs(httpRoute *HTTPRouteContext, res continue } - var hasHostnameIntersection = t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(httpRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { parentRef.SetCondition(httpRoute, gwapiv1.RouteConditionAccepted, @@ -391,7 +391,6 @@ func applyHTTPFiltersContextToIRRoute(httpFiltersContext *HTTPFiltersContext, ir if len(httpFiltersContext.ExtensionRefs) > 0 { irRoute.ExtensionRefs = httpFiltersContext.ExtensionRefs } - } func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, resources *Resources, xdsIR XdsIRMap) { @@ -424,7 +423,7 @@ func (t *Translator) processGRPCRouteParentRefs(grpcRoute *GRPCRouteContext, res if parentRef.HasCondition(grpcRoute, gwapiv1.RouteConditionAccepted, metav1.ConditionFalse) { continue } - var hasHostnameIntersection = t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) + hasHostnameIntersection := t.processHTTPRouteParentRefListener(grpcRoute, routeRoutes, parentRef, xdsIR) if !hasHostnameIntersection { parentRef.SetCondition(grpcRoute, gwapiv1.RouteConditionAccepted, @@ -801,7 +800,8 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour } func (t *Translator) ProcessUDPRoutes(udpRoutes []*gwapiv1a2.UDPRoute, gateways []*GatewayContext, resources *Resources, - xdsIR XdsIRMap) []*UDPRouteContext { + xdsIR XdsIRMap, +) []*UDPRouteContext { var relevantUDPRoutes []*UDPRouteContext for _, u := range udpRoutes { @@ -932,7 +932,8 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour } func (t *Translator) ProcessTCPRoutes(tcpRoutes []*gwapiv1a2.TCPRoute, gateways []*GatewayContext, resources *Resources, - xdsIR XdsIRMap) []*TCPRouteContext { + xdsIR XdsIRMap, +) []*TCPRouteContext { var relevantTCPRoutes []*TCPRouteContext for _, tcp := range tcpRoutes { @@ -1068,7 +1069,8 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour func (t *Translator) processDestination(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, - resources *Resources) (ds *ir.DestinationSetting, backendWeight uint32) { + resources *Resources, +) (ds *ir.DestinationSetting, backendWeight uint32) { routeType := GetRouteType(route) weight := uint32(1) backendRef := GetBackendRef(backendRefContext) diff --git a/internal/gatewayapi/runner/runner_test.go b/internal/gatewayapi/runner/runner_test.go index 772f0372a3c..a48188cccb7 100644 --- a/internal/gatewayapi/runner/runner_test.go +++ b/internal/gatewayapi/runner/runner_test.go @@ -59,7 +59,6 @@ func TestRunner(t *testing.T) { // Ensure ir is empty return (reflect.DeepEqual(xdsIR.LoadAll(), map[string]*ir.Xds{})) && (reflect.DeepEqual(infraIR.LoadAll(), map[string]*ir.Infra{})) }, time.Second*1, time.Millisecond*20) - } func TestGetIRKeysToDelete(t *testing.T) { @@ -75,7 +74,8 @@ func TestGetIRKeysToDelete(t *testing.T) { newKeys: []string{}, delKeys: []string{}, }, - {name: "no new keys", + { + name: "no new keys", curKeys: []string{"one", "two"}, newKeys: []string{}, delKeys: []string{"one", "two"}, diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index f03e46590db..6723376c00c 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -45,7 +45,8 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security gateways []*GatewayContext, routes []RouteContext, resources *Resources, - xdsIR XdsIRMap) []*egv1a1.SecurityPolicy { + xdsIR XdsIRMap, +) []*egv1a1.SecurityPolicy { var res []*egv1a1.SecurityPolicy // Sort based on timestamp @@ -225,7 +226,8 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security func resolveSecurityPolicyGatewayTargetRef( policy *egv1a1.SecurityPolicy, - gateways map[types.NamespacedName]*policyGatewayTargetContext) (*GatewayContext, *status.PolicyResolveError) { + gateways map[types.NamespacedName]*policyGatewayTargetContext, +) (*GatewayContext, *status.PolicyResolveError) { targetNs := policy.Spec.TargetRef.Namespace // If empty, default to namespace of policy if targetNs == nil { @@ -278,7 +280,8 @@ func resolveSecurityPolicyGatewayTargetRef( func resolveSecurityPolicyRouteTargetRef( policy *egv1a1.SecurityPolicy, - routes map[policyTargetRouteKey]*policyRouteTargetContext) (RouteContext, *status.PolicyResolveError) { + routes map[policyTargetRouteKey]*policyRouteTargetContext, +) (RouteContext, *status.PolicyResolveError) { targetNs := policy.Spec.TargetRef.Namespace // If empty, default to namespace of policy if targetNs == nil { @@ -333,7 +336,8 @@ func resolveSecurityPolicyRouteTargetRef( func (t *Translator) translateSecurityPolicyForRoute( policy *egv1a1.SecurityPolicy, route RouteContext, - resources *Resources, xdsIR XdsIRMap) error { + resources *Resources, xdsIR XdsIRMap, +) error { // Build IR var ( cors *ir.CORS @@ -404,7 +408,8 @@ func (t *Translator) translateSecurityPolicyForRoute( func (t *Translator) translateSecurityPolicyForGateway( policy *egv1a1.SecurityPolicy, gateway *GatewayContext, - resources *Resources, xdsIR XdsIRMap) error { + resources *Resources, xdsIR XdsIRMap, +) error { // Build IR var ( cors *ir.CORS @@ -534,7 +539,8 @@ func (t *Translator) buildJWT(jwt *egv1a1.JWT) *ir.JWT { func (t *Translator) buildOIDC( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.OIDC, error) { + resources *Resources, +) (*ir.OIDC, error) { var ( oidc = policy.Spec.OIDC clientSecret *v1.Secret @@ -726,7 +732,8 @@ func validateTokenEndpoint(tokenEndpoint string) error { func (t *Translator) buildBasicAuth( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.BasicAuth, error) { + resources *Resources, +) (*ir.BasicAuth, error) { var ( basicAuth = policy.Spec.BasicAuth usersSecret *v1.Secret @@ -758,7 +765,8 @@ func (t *Translator) buildBasicAuth( func (t *Translator) buildExtAuth( policy *egv1a1.SecurityPolicy, - resources *Resources) (*ir.ExtAuth, error) { + resources *Resources, +) (*ir.ExtAuth, error) { var ( http = policy.Spec.ExtAuth.HTTP grpc = policy.Spec.ExtAuth.GRPC diff --git a/internal/gatewayapi/sort.go b/internal/gatewayapi/sort.go index 75d9ebc503a..c11787a60dc 100644 --- a/internal/gatewayapi/sort.go +++ b/internal/gatewayapi/sort.go @@ -16,7 +16,6 @@ type XdsIRRoutes []*ir.HTTPRoute func (x XdsIRRoutes) Len() int { return len(x) } func (x XdsIRRoutes) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x XdsIRRoutes) Less(i, j int) bool { - // 1. Sort based on path match type // Exact > RegularExpression > PathPrefix if x[i].PathMatch != nil && x[i].PathMatch.Exact != nil { diff --git a/internal/gatewayapi/tls.go b/internal/gatewayapi/tls.go index f37c53b9526..cc01c4c56c1 100644 --- a/internal/gatewayapi/tls.go +++ b/internal/gatewayapi/tls.go @@ -57,7 +57,6 @@ func validateTLSSecretsData(secrets []*corev1.Secret, host *v1.Hostname) error { if matchedFQDN, ok := pkaSecretSet[pkaSecretKey]; ok { return fmt.Errorf("%s/%s public key algorithm must be unique, matched certificate FQDN %s has a conflicting algorithm [%s]", secret.Namespace, secret.Name, matchedFQDN, publicKeyAlgorithm) - } pkaSecretSet[pkaSecretKey] = matchedFQDN diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 9dc93532479..1827d962d57 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -115,7 +115,8 @@ func newTranslateResult(gateways []*GatewayContext, securityPolicies []*egv1a1.SecurityPolicy, backendTLSPolicies []*egv1a2.BackendTLSPolicy, envoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy, - xdsIR XdsIRMap, infraIR InfraIRMap) *TranslateResult { + xdsIR XdsIRMap, infraIR InfraIRMap, +) *TranslateResult { translateResult := &TranslateResult{ XdsIR: xdsIR, InfraIR: infraIR, @@ -220,7 +221,6 @@ func (t *Translator) Translate(resources *Resources) *TranslateResult { tcpRoutes, udpRoutes, clientTrafficPolicies, backendTrafficPolicies, securityPolicies, resources.BackendTLSPolicies, envoyExtensionPolicies, xdsIR, infraIR) - } // GetRelevantGateways returns GatewayContexts, containing a copy of the original diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index a22b69b534f..23ade13da9b 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -34,9 +34,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils/file" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func mustUnmarshal(t *testing.T, val []byte, out interface{}) { require.NoError(t, yaml.UnmarshalStrict(val, out, yaml.DisallowUnknownFields)) @@ -444,7 +442,7 @@ func TestTranslateWithExtensionKinds(t *testing.T) { func overrideOutputConfig(t *testing.T, data string, filepath string) { t.Helper() - file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) + file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) require.NoError(t, err) defer file.Close() write := bufio.NewWriter(file) diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index e7ddb427a15..09561698c66 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -23,7 +23,8 @@ import ( ) func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, - resources *Resources, backendNamespace string, routeKind gwapiv1.Kind) bool { + resources *Resources, backendNamespace string, routeKind gwapiv1.Kind, +) bool { if !t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind) { return false } @@ -112,7 +113,8 @@ func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, par } func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext, - resources *Resources, routeKind gwapiv1.Kind) bool { + resources *Resources, routeKind gwapiv1.Kind, +) bool { if backendRef.Namespace != nil && string(*backendRef.Namespace) != "" && string(*backendRef.Namespace) != route.GetNamespace() { if !t.validateCrossNamespaceRef( crossNamespaceFrom{ @@ -152,8 +154,10 @@ func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, paren } return true } + func (t *Translator) validateBackendService(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *Resources, - serviceNamespace string, route RouteContext, protocol v1.Protocol) bool { + serviceNamespace string, route RouteContext, protocol v1.Protocol, +) bool { service := resources.GetService(serviceNamespace, string(backendRef.Name)) if service == nil { parentRef.SetCondition(route, @@ -191,7 +195,8 @@ func (t *Translator) validateBackendService(backendRef *gwapiv1a2.BackendRef, pa } func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *Resources, - serviceImportNamespace string, route RouteContext, protocol v1.Protocol) bool { + serviceImportNamespace string, route RouteContext, protocol v1.Protocol, +) bool { serviceImport := resources.GetServiceImport(serviceImportNamespace, string(backendRef.Name)) if serviceImport == nil { parentRef.SetCondition(route, @@ -767,8 +772,8 @@ func (t *Translator) validateSecretRef( allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1b1.SecretObjectReference, - resources *Resources) (*v1.Secret, error) { - + resources *Resources, +) (*v1.Secret, error) { if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { return nil, err } @@ -791,8 +796,8 @@ func (t *Translator) validateConfigMapRef( allowCrossNamespace bool, from crossNamespaceFrom, secretObjRef gwapiv1b1.SecretObjectReference, - resources *Resources) (*v1.ConfigMap, error) { - + resources *Resources, +) (*v1.ConfigMap, error) { if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { return nil, err } @@ -815,7 +820,8 @@ func (t *Translator) validateSecretObjectRef( allowCrossNamespace bool, from crossNamespaceFrom, secretRef gwapiv1b1.SecretObjectReference, - resources *Resources) error { + resources *Resources, +) error { var kind string if secretRef.Group != nil && string(*secretRef.Group) != "" { return errors.New("secret ref group must be unspecified/empty") @@ -875,8 +881,8 @@ func (t *Translator) validateSecretObjectRef( func (t *Translator) validateExtServiceBackendReference( backendRef *gwapiv1.BackendObjectReference, ownerNamespace string, - resources *Resources) error { - + resources *Resources, +) error { // These are sanity checks, they should never happen because the API server // should have caught them if backendRef.Group != nil && *backendRef.Group != "" { diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index 323d2593d6e..f74481f281b 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -102,7 +102,8 @@ func enablePrometheus(infra *ir.ProxyInfra) bool { // expectedProxyContainers returns expected proxy containers. func expectedProxyContainers(infra *ir.ProxyInfra, containerSpec *egv1a1.KubernetesContainerSpec, - shutdownConfig *egv1a1.ShutdownConfig) ([]corev1.Container, error) { + shutdownConfig *egv1a1.ShutdownConfig, +) ([]corev1.Container, error) { // Define slice to hold container ports var ports []corev1.ContainerPort diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index 6a9548817a9..0d4a5999368 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -30,9 +30,7 @@ import ( "github.com/envoyproxy/gateway/internal/ir" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") const ( // envoyHTTPPort is the container port number of Envoy's HTTP endpoint. @@ -565,7 +563,7 @@ func TestDeployment(t *testing.T) { deploymentYAML, err := yaml.Marshal(dp) require.NoError(t, err) // nolint: gosec - err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } @@ -986,7 +984,7 @@ func TestDaemonSet(t *testing.T) { deploymentYAML, err := yaml.Marshal(ds) require.NoError(t, err) // nolint: gosec - err = os.WriteFile(fmt.Sprintf("testdata/daemonsets/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/daemonsets/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } @@ -1150,7 +1148,6 @@ func loadConfigmap(tc string) (*corev1.ConfigMap, error) { } func TestServiceAccount(t *testing.T) { - cfg, err := config.New() require.NoError(t, err) cases := []struct { @@ -1276,7 +1273,6 @@ func loadHPA(caseName string) (*autoscalingv2.HorizontalPodAutoscaler, error) { } func TestOwningGatewayLabelsAbsent(t *testing.T) { - cases := []struct { caseName string labels map[string]string @@ -1324,5 +1320,4 @@ func TestOwningGatewayLabelsAbsent(t *testing.T) { require.Equal(t, tc.expect, actual) }) } - } diff --git a/internal/infrastructure/kubernetes/proxy_infra_test.go b/internal/infrastructure/kubernetes/proxy_infra_test.go index d39f8059799..5c8a8d34695 100644 --- a/internal/infrastructure/kubernetes/proxy_infra_test.go +++ b/internal/infrastructure/kubernetes/proxy_infra_test.go @@ -192,7 +192,6 @@ func TestCreateProxyInfra(t *testing.T) { } func TestDeleteProxyInfra(t *testing.T) { - testCases := []struct { name string in *ir.Infra diff --git a/internal/infrastructure/kubernetes/ratelimit/resource.go b/internal/infrastructure/kubernetes/ratelimit/resource.go index 9f6303247cd..6ab5b19433f 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource.go @@ -115,7 +115,6 @@ func GetServiceURL(namespace string, dnsDomain string) string { // LabelSelector returns the string slice form labels used for all envoy rate limit resources. func LabelSelector() []string { - rlLabelMap := rateLimitLabels() retLabels := make([]string, 0, len(rlLabelMap)) @@ -138,7 +137,8 @@ func rateLimitLabels() map[string]string { // expectedRateLimitContainers returns expected rateLimit containers. func expectedRateLimitContainers(rateLimit *egv1a1.RateLimit, rateLimitDeployment *egv1a1.KubernetesDeploymentSpec, - namespace string) []corev1.Container { + namespace string, +) []corev1.Container { ports := []corev1.ContainerPort{ { Name: "grpc", @@ -289,7 +289,8 @@ func expectedDeploymentVolumes(rateLimit *egv1a1.RateLimit, rateLimitDeployment // expectedRateLimitContainerEnv returns expected rateLimit container envs. func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeployment *egv1a1.KubernetesDeploymentSpec, - namespace string) []corev1.EnvVar { + namespace string, +) []corev1.EnvVar { env := []corev1.EnvVar{ { Name: RuntimeRootEnvVar, @@ -399,7 +400,7 @@ func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeploym } if enableTracing(rateLimit) { - var sampleRate = 1.0 + sampleRate := 1.0 if rateLimit.Telemetry.Tracing.SamplingRate != nil { sampleRate = float64(*rateLimit.Telemetry.Tracing.SamplingRate) / 100.0 } diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go index 03d794d0ed1..6345aebdc55 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go @@ -27,9 +27,7 @@ import ( "github.com/envoyproxy/gateway/internal/envoygateway/config" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") const ( // RedisAuthEnvVar is the redis auth. @@ -43,7 +41,6 @@ var ownerReferenceUID = map[string]types.UID{ } func TestRateLimitLabelSelector(t *testing.T) { - cases := []struct { name string expected []string @@ -65,7 +62,6 @@ func TestRateLimitLabelSelector(t *testing.T) { require.ElementsMatch(t, tc.expected, got) }) } - } func TestRateLimitLabels(t *testing.T) { @@ -126,7 +122,6 @@ func loadServiceAccount() (*corev1.ServiceAccount, error) { } func TestService(t *testing.T) { - cfg, err := config.New() require.NoError(t, err) @@ -209,7 +204,7 @@ func TestConfigmap(t *testing.T) { cmYAML, err := yaml.Marshal(cm) require.NoError(t, err) // nolint:gosec - err = os.WriteFile("testdata/envoy-ratelimit-configmap.yaml", cmYAML, 0644) + err = os.WriteFile("testdata/envoy-ratelimit-configmap.yaml", cmYAML, 0o644) require.NoError(t, err) return } @@ -694,7 +689,8 @@ func TestDeployment(t *testing.T) { Type: egv1a1.ProviderTypeKubernetes, Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ RateLimitDeployment: tc.deploy, - }} + }, + } r := NewResourceRender(cfg.Namespace, cfg.EnvoyGateway, ownerReferenceUID) dp, err := r.Deployment() require.NoError(t, err) @@ -703,7 +699,7 @@ func TestDeployment(t *testing.T) { deploymentYAML, err := yaml.Marshal(dp) require.NoError(t, err) // nolint:gosec - err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0644) + err = os.WriteFile(fmt.Sprintf("testdata/deployments/%s.yaml", tc.caseName), deploymentYAML, 0o644) require.NoError(t, err) return } diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_test.go index 71179c8c7c4..61d24eac8da 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_test.go @@ -12,7 +12,6 @@ import ( ) func TestCheckTraceEndpointScheme(t *testing.T) { - cases := []struct { caseName string actualURL string @@ -36,5 +35,4 @@ func TestCheckTraceEndpointScheme(t *testing.T) { require.Equal(t, tc.expectedURL, actual) }) } - } diff --git a/internal/infrastructure/kubernetes/resource/resource_test.go b/internal/infrastructure/kubernetes/resource/resource_test.go index 14df266e187..b65549911c7 100644 --- a/internal/infrastructure/kubernetes/resource/resource_test.go +++ b/internal/infrastructure/kubernetes/resource/resource_test.go @@ -213,7 +213,8 @@ func TestCompareSvc(t *testing.T) { Type: "NodePort", }, }, - }, { + }, + { // Only Spec.Ports[*].Port is different ExpectRet: false, NewSvc: &corev1.Service{ @@ -298,7 +299,8 @@ func TestCompareSvc(t *testing.T) { Type: "ClusterIP", }, }, - }, { + }, + { // Finalizers field differs ExpectRet: true, NewSvc: &corev1.Service{ diff --git a/internal/infrastructure/runner/runner.go b/internal/infrastructure/runner/runner.go index 8da18e46443..d9376eb8499 100644 --- a/internal/infrastructure/runner/runner.go +++ b/internal/infrastructure/runner/runner.go @@ -44,7 +44,7 @@ func (r *Runner) Start(ctx context.Context) (err error) { return err } - var initInfra = func() { + initInfra := func() { go r.subscribeToProxyInfraIR(ctx) // Enable global ratelimit if it has been configured. diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 8b16cf6e9a4..30c07a70001 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -35,11 +35,11 @@ var ( Hostnames: []string{"example.com"}, TLS: &TLSConfig{ Certificates: []TLSCertificate{{ - Name: "happy", ServerCertificate: []byte{1, 2, 3}, PrivateKey: []byte{1, 2, 3}, - }}}, + }}, + }, Routes: []*HTTPRoute{&happyHTTPRoute}, } redactedHappyHTTPSListener = HTTPListener{ @@ -49,11 +49,11 @@ var ( Hostnames: []string{"example.com"}, TLS: &TLSConfig{ Certificates: []TLSCertificate{{ - Name: "happy", ServerCertificate: []byte{1, 2, 3}, PrivateKey: redacted, - }}}, + }}, + }, Routes: []*HTTPRoute{&happyHTTPRoute}, } invalidAddrHTTPListener = HTTPListener{ @@ -96,7 +96,8 @@ var ( Name: "happy", ServerCertificate: []byte("server-cert"), PrivateKey: []byte("priv-key"), - }}}}, + }}, + }}, Destination: &happyRouteDestination, } @@ -658,7 +659,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { Certificates: []TLSCertificate{{ ServerCertificate: []byte("server-cert"), PrivateKey: []byte("priv-key"), - }}}, + }}, + }, want: nil, }, { @@ -666,7 +668,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { input: TLSConfig{ Certificates: []TLSCertificate{{ PrivateKey: []byte("priv-key"), - }}}, + }}, + }, want: ErrTLSServerCertEmpty, }, { @@ -674,7 +677,8 @@ func TestValidateTLSListenerConfig(t *testing.T) { input: TLSConfig{ Certificates: []TLSCertificate{{ ServerCertificate: []byte("server-cert"), - }}}, + }}, + }, want: ErrTLSPrivateKey, }, } @@ -1253,231 +1257,244 @@ func TestValidateHealthCheck(t *testing.T) { }{ { name: "invalid timeout", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Duration(0)}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Duration(0)}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckTimeoutInvalid, }, { name: "invalid interval", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Duration(0)}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodGet), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Duration(0)}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodGet), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckIntervalInvalid, }, { name: "invalid unhealthy threshold", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](0), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodPatch), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](0), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodPatch), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckUnhealthyThresholdInvalid, }, { name: "invalid healthy threshold", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](0), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodPost), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](0), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodPost), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckHealthyThresholdInvalid, }, { name: "http-health-check: invalid host", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Path: "/healthz", - Method: ptr.To(http.MethodPut), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Path: "/healthz", + Method: ptr.To(http.MethodPut), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPHostInvalid, }, { name: "http-health-check: invalid path", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To[uint32](3), - HealthyThreshold: ptr.To[uint32](3), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "", - Method: ptr.To(http.MethodPut), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To[uint32](3), + HealthyThreshold: ptr.To[uint32](3), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "", + Method: ptr.To(http.MethodPut), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPPathInvalid, }, { name: "http-health-check: invalid method", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodConnect), - ExpectedStatuses: []HTTPStatus{200, 400}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodConnect), + ExpectedStatuses: []HTTPStatus{200, 400}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPMethodInvalid, }, { name: "http-health-check: invalid expected-statuses", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodDelete), - ExpectedStatuses: []HTTPStatus{}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodDelete), + ExpectedStatuses: []HTTPStatus{}, + }, }, - }, &OutlierDetection{}, }, want: ErrHCHTTPExpectedStatusesInvalid, }, { name: "http-health-check: invalid range", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodHead), - ExpectedStatuses: []HTTPStatus{100, 600}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodHead), + ExpectedStatuses: []HTTPStatus{100, 600}, + }, }, - }, &OutlierDetection{}, }, want: ErrHTTPStatusInvalid, }, { name: "http-health-check: invalid expected-responses", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - HTTP: &HTTPHealthChecker{ - Host: "*", - Path: "/healthz", - Method: ptr.To(http.MethodOptions), - ExpectedStatuses: []HTTPStatus{200, 300}, - ExpectedResponse: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + HTTP: &HTTPHealthChecker{ + Host: "*", + Path: "/healthz", + Method: ptr.To(http.MethodOptions), + ExpectedStatuses: []HTTPStatus{200, 300}, + ExpectedResponse: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid send payload", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - TCP: &TCPHealthChecker{ - Send: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, - }, - Receive: &HealthCheckPayload{ - Text: ptr.To("foo"), + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + TCP: &TCPHealthChecker{ + Send: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, + Receive: &HealthCheckPayload{ + Text: ptr.To("foo"), + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid receive payload", - input: HealthCheck{&ActiveHealthCheck{ - Timeout: &metav1.Duration{Duration: time.Second}, - Interval: &metav1.Duration{Duration: time.Second}, - UnhealthyThreshold: ptr.To(uint32(3)), - HealthyThreshold: ptr.To(uint32(3)), - TCP: &TCPHealthChecker{ - Send: &HealthCheckPayload{ - Text: ptr.To("foo"), - }, - Receive: &HealthCheckPayload{ - Text: ptr.To("foo"), - Binary: []byte{'f', 'o', 'o'}, + input: HealthCheck{ + &ActiveHealthCheck{ + Timeout: &metav1.Duration{Duration: time.Second}, + Interval: &metav1.Duration{Duration: time.Second}, + UnhealthyThreshold: ptr.To(uint32(3)), + HealthyThreshold: ptr.To(uint32(3)), + TCP: &TCPHealthChecker{ + Send: &HealthCheckPayload{ + Text: ptr.To("foo"), + }, + Receive: &HealthCheckPayload{ + Text: ptr.To("foo"), + Binary: []byte{'f', 'o', 'o'}, + }, }, }, - }, &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "OutlierDetection invalid interval", - input: HealthCheck{&ActiveHealthCheck{}, + input: HealthCheck{ + &ActiveHealthCheck{}, &OutlierDetection{ Interval: &metav1.Duration{Duration: time.Duration(0)}, BaseEjectionTime: &metav1.Duration{Duration: time.Second}, @@ -1487,7 +1504,8 @@ func TestValidateHealthCheck(t *testing.T) { }, { name: "OutlierDetection invalid BaseEjectionTime", - input: HealthCheck{&ActiveHealthCheck{}, + input: HealthCheck{ + &ActiveHealthCheck{}, &OutlierDetection{ Interval: &metav1.Duration{Duration: time.Second}, BaseEjectionTime: &metav1.Duration{Duration: time.Duration(0)}, diff --git a/internal/kubernetes/port_forwarder.go b/internal/kubernetes/port_forwarder.go index ceb439d7721..176610dab3e 100644 --- a/internal/kubernetes/port_forwarder.go +++ b/internal/kubernetes/port_forwarder.go @@ -86,7 +86,6 @@ func (f *localForwarder) Start() error { readyCh = nil } - }() select { diff --git a/internal/logging/log.go b/internal/logging/log.go index 0d6d36f8f95..8f90a9c8e0a 100644 --- a/internal/logging/log.go +++ b/internal/logging/log.go @@ -34,7 +34,7 @@ func NewLogger(logging *v1alpha1.EnvoyGatewayLogging) Logger { } func FileLogger(file string, name string, level v1alpha1.LogLevel) Logger { - writer, err := os.OpenFile(file, os.O_WRONLY, 0666) + writer, err := os.OpenFile(file, os.O_WRONLY, 0o666) if err != nil { panic(err) } diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go index b938f276b7d..bd7829f3cbd 100644 --- a/internal/message/watchutil.go +++ b/internal/message/watchutil.go @@ -49,7 +49,7 @@ func HandleSubscription[K comparable, V any]( subscription <-chan watchable.Snapshot[K, V], handle func(updateFunc Update[K, V], errChans chan error), ) { - //TODO: find a suitable value + // TODO: find a suitable value errChans := make(chan error, 10) go func() { for err := range errChans { diff --git a/internal/metrics/metadata.go b/internal/metrics/metadata.go index f2ab8498407..255619bbd11 100644 --- a/internal/metrics/metadata.go +++ b/internal/metrics/metadata.go @@ -94,7 +94,8 @@ func (d *store) preAddOptions() []metric.Option { metric.Stream{ Aggregation: metric.AggregationExplicitBucketHistogram{ Boundaries: store.Bounds, - }}, + }, + }, )) opts = append(opts, v) } diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index 560141c6266..9b1aafcd5e2 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -29,12 +29,9 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.17.0" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestCounter(t *testing.T) { - name := "counter_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -87,7 +84,6 @@ func TestCounter(t *testing.T) { } func TestGauge(t *testing.T) { - name := "gauge_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -130,7 +126,6 @@ func TestGauge(t *testing.T) { } func TestHistogram(t *testing.T) { - name := "histogram_metric" var writer io.ReadWriter = bytes.NewBuffer(nil) @@ -219,7 +214,7 @@ func exporterWriter(name string, origin io.ReadWriter) (io.ReadWriter, error) { fname := fmt.Sprintf("testdata/%s.json", name) // nolint:gosec - f, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0644) + f, err := os.OpenFile(fname, os.O_CREATE|os.O_RDWR, 0o644) if err != nil { return nil, err } diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 571a45c5764..cf707f07922 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -59,7 +59,8 @@ type gatewayAPIReconciler struct { // newGatewayAPIController func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status.Updater, - resources *message.ProviderResources) error { + resources *message.ProviderResources, +) error { ctx := context.Background() // Gather additional resources to watch from registered extensions @@ -374,7 +375,8 @@ func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResour // - Secrets for OIDC and BasicAuth // - BackendRefs for ExAuth func (r *gatewayAPIReconciler) processSecurityPolicyObjectRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { // we don't return errors from this method, because we want to continue reconciling // the rest of the SecurityPolicies despite that one reference is invalid. This // allows Envoy Gateway to continue serving traffic even if some SecurityPolicies @@ -477,7 +479,6 @@ func (r *gatewayAPIReconciler) processOIDCHMACSecret(ctx context.Context, resour types.NamespacedName{Namespace: r.namespace, Name: oidcHMACSecretName}, &secret, ) - // We don't return an error here, because we want to continue reconciling // despite that the OIDC HMAC secret can't be found. // If the OIDC HMAC Secret is missing, the SecurityPolicy with OIDC will be @@ -550,7 +551,8 @@ func (r *gatewayAPIReconciler) processSecretRef( // processCtpConfigMapRefs adds the referenced ConfigMaps in ClientTrafficPolicies // to the resourceTree func (r *gatewayAPIReconciler) processCtpConfigMapRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { for _, policy := range resourceTree.ClientTrafficPolicies { tls := policy.Spec.TLS @@ -734,7 +736,6 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g gtw.Namespace, gtw.Name, certRef); err != nil { - r.log.Error(err, "failed to process TLS SecretRef for gateway", "gateway", gtw, "secretRef", certRef) @@ -799,7 +800,8 @@ func (r *gatewayAPIReconciler) processEnvoyPatchPolicies(ctx context.Context, re // processClientTrafficPolicies adds ClientTrafficPolicies to the resourceTree func (r *gatewayAPIReconciler) processClientTrafficPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { clientTrafficPolicies := egv1a1.ClientTrafficPolicyList{} if err := r.client.List(ctx, &clientTrafficPolicies); err != nil { return fmt.Errorf("error listing ClientTrafficPolicies: %w", err) @@ -837,7 +839,8 @@ func (r *gatewayAPIReconciler) processBackendTrafficPolicies(ctx context.Context // processSecurityPolicies adds SecurityPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processSecurityPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { securityPolicies := egv1a1.SecurityPolicyList{} if err := r.client.List(ctx, &securityPolicies); err != nil { return fmt.Errorf("error listing SecurityPolicies: %w", err) @@ -861,7 +864,8 @@ func (r *gatewayAPIReconciler) processSecurityPolicies( // processBackendTLSPolicies adds BackendTLSPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processBackendTLSPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { backendTLSPolicies := gwapiv1a2.BackendTLSPolicyList{} if err := r.client.List(ctx, &backendTLSPolicies); err != nil { return fmt.Errorf("error listing BackendTLSPolicies: %w", err) @@ -1435,7 +1439,8 @@ func (r *gatewayAPIReconciler) processBackendTLSPolicyConfigMapRefs(ctx context. // processEnvoyExtensionPolicies adds EnvoyExtensionPolicies and their referenced resources to the resourceTree func (r *gatewayAPIReconciler) processEnvoyExtensionPolicies( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) error { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) error { envoyExtensionPolicies := egv1a1.EnvoyExtensionPolicyList{} if err := r.client.List(ctx, &envoyExtensionPolicies); err != nil { return fmt.Errorf("error listing EnvoyExtensionPolicies: %w", err) @@ -1459,7 +1464,8 @@ func (r *gatewayAPIReconciler) processEnvoyExtensionPolicies( // to the resourceTree // - BackendRefs for ExtProcs func (r *gatewayAPIReconciler) processEnvoyExtensionPolicyObjectRefs( - ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings, +) { // we don't return errors from this method, because we want to continue reconciling // the rest of the EnvoyExtensionPolicies despite that one reference is invalid. This // allows Envoy Gateway to continue serving traffic even if some EnvoyExtensionPolicies diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go index 00029f1cb92..d3a1d972a42 100644 --- a/internal/provider/kubernetes/helpers.go +++ b/internal/provider/kubernetes/helpers.go @@ -36,8 +36,8 @@ type ObjectKindNamespacedName struct { // is a Gateway. func validateParentRefs(ctx context.Context, client client.Client, namespace string, gatewayClassController gwapiv1.GatewayController, - routeParentReferences []gwapiv1.ParentReference) ([]gwapiv1.Gateway, error) { - + routeParentReferences []gwapiv1.ParentReference, +) ([]gwapiv1.Gateway, error) { var gateways []gwapiv1.Gateway for i := range routeParentReferences { ref := routeParentReferences[i] diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index 2187e5b5df1..c0ca5d094bb 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -442,7 +442,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour rewriteHostname := gwapiv1.PreciseHostname("rewrite.hostname.local") - var testCases = []struct { + testCases := []struct { name string route gwapiv1.HTTPRoute }{ @@ -986,7 +986,7 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc require.NoError(t, cli.Delete(ctx, svc)) }() - var testCases = []struct { + testCases := []struct { name string route gwapiv1a2.TLSRoute }{ @@ -1149,13 +1149,17 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov }}, }, Hostnames: []gwapiv1a2.Hostname{"test-tls.hostname.local"}, - Rules: []gwapiv1a2.TLSRouteRule{{ - BackendRefs: []gwapiv1a2.BackendRef{{ - BackendObjectReference: gwapiv1a2.BackendObjectReference{ - Name: "test-common-svc", - Port: ptr.To(gwapiv1.PortNumber(90)), - }}, - }}, + Rules: []gwapiv1a2.TLSRouteRule{ + { + BackendRefs: []gwapiv1a2.BackendRef{ + { + BackendObjectReference: gwapiv1a2.BackendObjectReference{ + Name: "test-common-svc", + Port: ptr.To(gwapiv1.PortNumber(90)), + }, + }, + }, + }, }, }, } @@ -1585,7 +1589,6 @@ func TestNamespaceSelectorProvider(t *testing.T) { } return res != nil && len(res.GRPCRoutes) == 1 }, defaultWait, defaultTick) - } func waitUntilGatewayClassResourcesAreReady(resources *message.ProviderResources, gatewayClassName string) (*gatewayapi.Resources, bool) { diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index f25c0092326..4faf3d0d5e7 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -69,7 +69,6 @@ type NamespaceGetter interface { // checkObjectNamespaceLabels checks if labels of namespace of the object is a subset of namespaceLabels func (r *gatewayAPIReconciler) checkObjectNamespaceLabels(obj metav1.Object) (bool, error) { - var nsString string // TODO: it requires extra condition validate cluster resources or resources without namespace? if nsString = obj.GetNamespace(); len(nsString) == 0 { diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index 20d690f574a..b1b2524e25a 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -23,7 +23,8 @@ import ( // processTLSRoutes finds TLSRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the TLSRoutes to the resourceTree. func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { tlsRouteList := &gwapiv1a2.TLSRouteList{} if err := r.client.List(ctx, tlsRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayTLSRouteIndex, gatewayNamespaceName), @@ -93,7 +94,8 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName // processGRPCRoutes finds GRPCRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the GRPCRoutes to the resourceTree. func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { grpcRouteList := &gwapiv1a2.GRPCRouteList{} if err := r.client.List(ctx, grpcRouteList, &client.ListOptions{ @@ -203,7 +205,8 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam // processHTTPRoutes finds HTTPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the HTTPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { httpRouteList := &gwapiv1.HTTPRouteList{} extensionRefFilters, err := r.getExtensionRefFilters(ctx) @@ -376,7 +379,8 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam // processTCPRoutes finds TCPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the TCPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { tcpRouteList := &gwapiv1a2.TCPRouteList{} if err := r.client.List(ctx, tcpRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayTCPRouteIndex, gatewayNamespaceName), @@ -446,7 +450,8 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName // processUDPRoutes finds UDPRoutes corresponding to a gatewayNamespaceName, further checks for // the backend references and pushes the UDPRoutes to the resourceTree. func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayNamespaceName string, - resourceMap *resourceMappings, resourceTree *gatewayapi.Resources) error { + resourceMap *resourceMappings, resourceTree *gatewayapi.Resources, +) error { udpRouteList := &gwapiv1a2.UDPRouteList{} if err := r.client.List(ctx, udpRouteList, &client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(gatewayUDPRouteIndex, gatewayNamespaceName), diff --git a/internal/provider/kubernetes/secrets.go b/internal/provider/kubernetes/secrets.go index ab67f6e1608..953127e781b 100644 --- a/internal/provider/kubernetes/secrets.go +++ b/internal/provider/kubernetes/secrets.go @@ -20,9 +20,7 @@ import ( "github.com/envoyproxy/gateway/internal/utils" ) -var ( - ErrSecretExists = errors.New("skipped creating secret since it already exists") -) +var ErrSecretExists = errors.New("skipped creating secret since it already exists") // caCertificateKey is the key name for accessing TLS CA certificate bundles // in Kubernetes Secrets. diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go index 5aa8af4fa57..33988675073 100644 --- a/internal/provider/kubernetes/status.go +++ b/internal/provider/kubernetes/status.go @@ -447,7 +447,8 @@ func (r *gatewayAPIReconciler) updateStatusForGatewayClass( gc *gwapiv1.GatewayClass, accepted bool, reason, - msg string) error { + msg string, +) error { if r.statusUpdater != nil { r.statusUpdater.Send(status.Update{ NamespacedName: types.NamespacedName{Name: gc.Name}, diff --git a/internal/status/conditions.go b/internal/status/conditions.go index 092513184bb..955dc26a7ab 100644 --- a/internal/status/conditions.go +++ b/internal/status/conditions.go @@ -34,7 +34,8 @@ const ( // computeGatewayClassAcceptedCondition computes the GatewayClass Accepted status condition. func computeGatewayClassAcceptedCondition(gatewayClass *gwapiv1.GatewayClass, accepted bool, - reason, msg string) metav1.Condition { + reason, msg string, +) metav1.Condition { switch accepted { case true: return metav1.Condition{ diff --git a/internal/status/policy.go b/internal/status/policy.go index e60b52d40db..a5c7a21a92f 100644 --- a/internal/status/policy.go +++ b/internal/status/policy.go @@ -59,15 +59,16 @@ func setAcceptedForPolicyAncestor(policyStatus *gwv1a2.PolicyStatus, ancestorRef } func SetConditionForPolicyAncestors(policyStatus *gwv1a2.PolicyStatus, ancestorRefs []gwv1a2.ParentReference, controllerName string, - conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64) { + conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64, +) { for _, ancestorRef := range ancestorRefs { SetConditionForPolicyAncestor(policyStatus, ancestorRef, controllerName, conditionType, status, reason, message, generation) } } func SetConditionForPolicyAncestor(policyStatus *gwv1a2.PolicyStatus, ancestorRef gwv1a2.ParentReference, controllerName string, - conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64) { - + conditionType gwv1a2.PolicyConditionType, status metav1.ConditionStatus, reason gwv1a2.PolicyConditionReason, message string, generation int64, +) { if policyStatus.Ancestors == nil { policyStatus.Ancestors = []gwv1a2.PolicyAncestorStatus{} } diff --git a/internal/utils/field/field_test.go b/internal/utils/field/field_test.go index fe8460973b3..8e8322d9ad3 100644 --- a/internal/utils/field/field_test.go +++ b/internal/utils/field/field_test.go @@ -19,22 +19,25 @@ func TestSetValue(t *testing.T) { fieldValue any expect any expectedErr bool - }{{ - name: "field name cannot be empty", - input: "", - expectedErr: true, - }, + }{ + { + name: "field name cannot be empty", + input: "", + expectedErr: true, + }, { name: "input cannot be a string", input: "", fieldName: "K", expectedErr: true, - }, { + }, + { name: "input cannot be a struct", input: struct{}{}, fieldName: "K", expectedErr: true, - }, { + }, + { name: "field cannot be unexported", input: &struct { name string @@ -45,7 +48,8 @@ func TestSetValue(t *testing.T) { expectedErr: true, fieldName: "name", fieldValue: "test1", - }, { + }, + { name: "simple struct set value", input: &struct { Name string @@ -56,7 +60,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive struct set value", input: &struct { Name string @@ -77,7 +82,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive child struct in slice set value", input: &struct { Name string @@ -100,7 +106,8 @@ func TestSetValue(t *testing.T) { expectedErr: false, fieldName: "Name", fieldValue: "test1", - }, { + }, + { name: "simple recursive child struct in map set value", input: &struct { Name string diff --git a/internal/utils/file/file.go b/internal/utils/file/file.go index 369920b0f9a..51a02571493 100644 --- a/internal/utils/file/file.go +++ b/internal/utils/file/file.go @@ -11,7 +11,7 @@ import ( ) func Write(data string, filepath string) error { - file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644) if err != nil { return err } diff --git a/internal/utils/helm/package.go b/internal/utils/helm/package.go index f057b0744c3..4cbf81eff4c 100644 --- a/internal/utils/helm/package.go +++ b/internal/utils/helm/package.go @@ -77,7 +77,6 @@ func NewPackageTool() *PackageTool { // Setup Configuration required to initialize helm action. func (pt *PackageTool) Setup() error { - // Since envoy-gateway uses docker's oci to store charts, // we need to create a registry client to make sure we can retrieve envoy-gateway chart registryCli, err := registry.NewClient() @@ -112,7 +111,6 @@ func (pt *PackageTool) Setup() error { // SetInstallEnvSettings set the installation flags we are interested in func (pt *PackageTool) SetInstallEnvSettings(installCmd *cobra.Command, opts *PackageOptions) { - // add helm flags // we use a temporary flag to be set by helm env flags, // from which we can retrieve the flags we are interested @@ -139,12 +137,10 @@ func (pt *PackageTool) SetInstallEnvSettings(installCmd *cobra.Command, opts *Pa installCmd.Flags().StringSliceVarP(&pt.valuesOpts.ValueFiles, "values", "f", []string{}, "Specify values in a YAML file or a URL (can specify multiple)") installCmd.Flags().StringArrayVar(&pt.valuesOpts.Values, "set", []string{}, "Set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - } // SetUninstallEnvSetting set the uninstallation flags we are interested in func (pt *PackageTool) SetUninstallEnvSetting(uninstallCmd *cobra.Command, opts *PackageOptions) { - uninstallCmd.Flags().DurationVar(&opts.Timeout, "timeout", helmOperateTimeout, "time to wait for any individual Kubernetes operation") uninstallCmd.Flags().StringVar(&opts.ReleaseName, "name", egReleaseName, "name of the envoy-gateway release to uninstall") uninstallCmd.Flags().StringVarP(&opts.ReleaseNamespace, "namespace", "n", "", "if set, specify the namespace where envoy gateway is uninstalled") @@ -152,12 +148,10 @@ func (pt *PackageTool) SetUninstallEnvSetting(uninstallCmd *cobra.Command, opts uninstallCmd.Flags().BoolVar(&opts.DryRun, "dry-run", false, "console output only, make no changes") uninstallCmd.Flags().BoolVar(&opts.WithCRD, "with-crds", false, "if set, the CRDs will also be removed") uninstallCmd.Flags().Bool("debug", false, "if set, the will output detailed execution logs") - } // loadChart Load the chart instance according to the chart name and version func (pt *PackageTool) loadChart(opts *PackageOptions) (*chart.Chart, error) { - pt.actionInstall.Version = opts.Version chartName, err := pt.actionInstall.LocateChart(pt.chartName, pt.envSettings) if err != nil { @@ -182,7 +176,6 @@ func (pt *PackageTool) loadChart(opts *PackageOptions) (*chart.Chart, error) { // extractCRDs Extract the CRDs part of the chart func (pt *PackageTool) extractCRDs(ch *chart.Chart) ([]*resource.Info, error) { - crdResInfo := make([]*resource.Info, 0, len(ch.CRDObjects())) for _, crd := range ch.CRDObjects() { @@ -204,7 +197,6 @@ func (pt *PackageTool) extractCRDs(ch *chart.Chart) ([]*resource.Info, error) { // This is done to avoid garbage collection on CRs in the cluster during uninstallation, // preventing the potential loss of crucial CR instances. func (pt *PackageTool) RunInstall(opts *PackageOptions) error { - if opts.Version == "v0.0.0-latest" { warningMarker := color.New(color.FgYellow).Add(color.Bold).Sprintf("WARNING") pt.logger.Println(fmt.Sprintf("%s: Currently using the latest version of envoy gateway chart, it is recommended to use the fixed version", @@ -270,7 +262,7 @@ func (pt *PackageTool) RunInstall(opts *PackageOptions) error { var outputErr error var outputFile *os.File - if outputFile, outputErr = os.OpenFile(opts.Output, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666); outputErr == nil { + if outputFile, outputErr = os.OpenFile(opts.Output, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0o666); outputErr == nil { _, outputErr = fmt.Fprint(outputFile, release.Manifest) } if outputErr != nil { @@ -290,7 +282,6 @@ func (pt *PackageTool) RunInstall(opts *PackageOptions) error { // RunUninstall By default, we only uninstall instances of the Envoy Gateway resources. func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { - pt.setUninstallOptions(opts) resp, err := pt.actionUninstall.Run(opts.ReleaseName) @@ -304,7 +295,6 @@ func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { } if opts.WithCRD { - if crdInfo, err := pt.extractCRDs(resp.Release.Chart); err != nil { return err } else if len(crdInfo) == 0 { @@ -312,7 +302,6 @@ func (pt *PackageTool) RunUninstall(opts *PackageOptions) error { } else if _, errors := pt.actionConfig.KubeClient.Delete(crdInfo); len(errors) != 0 { return fmt.Errorf("failed to delete CRDs error: %s", util.MultipleErrors("", errors)) } - } successMarker := color.New(color.FgGreen).Add(color.Bold).Sprintf("SUCCESS") @@ -330,7 +319,6 @@ func (pt *PackageTool) setCommonValue() { // setInstallOptions Sets the options required before install func (pt *PackageTool) setInstallOptions(opts *PackageOptions) { - if opts.DryRun { // When dry-run is set up, we do not need to connect to k8s-api server. // Since the kubernetes version needs to be higher than the value in the Helm library @@ -375,7 +363,6 @@ func (pt *PackageTool) setUninstallOptions(opts *PackageOptions) { func (pt *PackageTool) SetPreRun(cmd *cobra.Command) { existPreRunE := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { - pt.setPrinter(cmd) pt.setNamespace(cmd) @@ -426,7 +413,6 @@ func createDummyK8sVersion() *chartutil.KubeVersion { // detectExistCRDs Check if envoy-gateway and gateway-api CRDs already exist in the cluster func detectExistCRDs(crdResInfo []*resource.Info) (*bool, error) { - exist := false existObj := make([]runtime.Object, 0, len(crdResInfo)) @@ -455,7 +441,6 @@ func detectExistCRDs(crdResInfo []*resource.Info) (*bool, error) { // installCRDs Install CRDs to the cluster func installCRDs(crds []*resource.Info, actionConfig *action.Configuration) error { - // Create all CRDs in the envoy gateway chart result, err := actionConfig.KubeClient.Create(crds) if err != nil { diff --git a/internal/utils/protocov/protocov.go b/internal/utils/protocov/protocov.go index 52bb952269e..6533f84c543 100644 --- a/internal/utils/protocov/protocov.go +++ b/internal/utils/protocov/protocov.go @@ -16,9 +16,7 @@ const ( APIPrefix = "type.googleapis.com/" ) -var ( - marshalOpts = proto.MarshalOptions{} -) +var marshalOpts = proto.MarshalOptions{} func ToAnyWithError(msg proto.Message) (*anypb.Any, error) { if msg == nil { diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index a913fbb082c..54ee52f3d4e 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -145,7 +145,7 @@ func TestGetRenderedBootstrapConfig(t *testing.T) { if *overrideTestData { // nolint:gosec - err = os.WriteFile(path.Join("testdata", "render", fmt.Sprintf("%s.yaml", tc.name)), []byte(got), 0644) + err = os.WriteFile(path.Join("testdata", "render", fmt.Sprintf("%s.yaml", tc.name)), []byte(got), 0o644) require.NoError(t, err) return } diff --git a/internal/xds/bootstrap/util_test.go b/internal/xds/bootstrap/util_test.go index b0d27460093..5591d0e4f53 100644 --- a/internal/xds/bootstrap/util_test.go +++ b/internal/xds/bootstrap/util_test.go @@ -18,9 +18,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -var ( - overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") -) +var overrideTestData = flag.Bool("override-testdata", false, "if override the test output data.") func TestApplyBootstrapConfig(t *testing.T) { str, _ := readTestData("enable-prometheus") @@ -56,7 +54,7 @@ func TestApplyBootstrapConfig(t *testing.T) { if *overrideTestData { // nolint:gosec - err = os.WriteFile(path.Join("testdata", "merge", fmt.Sprintf("%s.out.yaml", tc.name)), []byte(data), 0644) + err = os.WriteFile(path.Join("testdata", "merge", fmt.Sprintf("%s.out.yaml", tc.name)), []byte(data), 0o644) require.NoError(t, err) return } diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go index 63e6d46c9fd..9f1f17a09d9 100644 --- a/internal/xds/translator/accesslog.go +++ b/internal/xds/translator/accesslog.go @@ -48,14 +48,12 @@ const ( otelAccessLog = "envoy.access_loggers.open_telemetry" ) -var ( - // for the case when a route does not exist to upstream, hcm logs will not be present - listenerAccessLogFilter = &accesslog.AccessLogFilter{ - FilterSpecifier: &accesslog.AccessLogFilter_ResponseFlagFilter{ - ResponseFlagFilter: &accesslog.ResponseFlagFilter{Flags: []string{"NR"}}, - }, - } -) +// for the case when a route does not exist to upstream, hcm logs will not be present +var listenerAccessLogFilter = &accesslog.AccessLogFilter{ + FilterSpecifier: &accesslog.AccessLogFilter_ResponseFlagFilter{ + ResponseFlagFilter: &accesslog.ResponseFlagFilter{Flags: []string{"NR"}}, + }, +} func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLog { if al == nil { diff --git a/internal/xds/translator/basicauth.go b/internal/xds/translator/basicauth.go index 5733cc34209..e22febfca4b 100644 --- a/internal/xds/translator/basicauth.go +++ b/internal/xds/translator/basicauth.go @@ -27,8 +27,7 @@ func init() { registerHTTPFilter(&basicAuth{}) } -type basicAuth struct { -} +type basicAuth struct{} var _ httpFilter = &basicAuth{} diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 8587aca73f9..bb18a7e0286 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -82,7 +82,9 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { DnsLookupFamily: clusterv3.Cluster_V4_ONLY, CommonLbConfig: &clusterv3.Cluster_CommonLbConfig{ LocalityConfigSpecifier: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig_{ - LocalityWeightedLbConfig: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig{}}}, + LocalityWeightedLbConfig: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig{}, + }, + }, OutlierDetection: &clusterv3.OutlierDetection{}, PerConnectionBufferLimitBytes: wrapperspb.UInt32(tcpClusterPerConnectionBufferLimitBytes), } @@ -191,7 +193,6 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { if args.healthCheck != nil && args.healthCheck.Passive != nil { cluster.OutlierDetection = buildXdsOutlierDetection(args.healthCheck.Passive) - } cluster.CircuitBreakers = buildXdsClusterCircuitBreaker(args.circuitBreaker) @@ -459,13 +460,11 @@ func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb. if args.timeout != nil && args.timeout.HTTP != nil { if args.timeout.HTTP.ConnectionIdleTimeout != nil { - protocolOptions.CommonHttpProtocolOptions.IdleTimeout = - durationpb.New(args.timeout.HTTP.ConnectionIdleTimeout.Duration) + protocolOptions.CommonHttpProtocolOptions.IdleTimeout = durationpb.New(args.timeout.HTTP.ConnectionIdleTimeout.Duration) } if args.timeout.HTTP.MaxConnectionDuration != nil { - protocolOptions.CommonHttpProtocolOptions.MaxConnectionDuration = - durationpb.New(args.timeout.HTTP.MaxConnectionDuration.Duration) + protocolOptions.CommonHttpProtocolOptions.MaxConnectionDuration = durationpb.New(args.timeout.HTTP.MaxConnectionDuration.Duration) } } @@ -626,5 +625,4 @@ func buildXdsClusterUpstreamOptions(tcpkeepalive *ir.TCPKeepalive) *clusterv3.Up } return ka - } diff --git a/internal/xds/translator/cors.go b/internal/xds/translator/cors.go index cd46b6f41a6..6090bc21689 100644 --- a/internal/xds/translator/cors.go +++ b/internal/xds/translator/cors.go @@ -27,8 +27,7 @@ func init() { registerHTTPFilter(&cors{}) } -type cors struct { -} +type cors struct{} var _ httpFilter = &cors{} @@ -36,7 +35,8 @@ var _ httpFilter = &cors{} // applicable. func (*cors) patchHCM( mgr *hcmv3.HttpConnectionManager, - irListener *ir.HTTPListener) error { + irListener *ir.HTTPListener, +) error { if mgr == nil { return errors.New("hcm is nil") } diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index 43712564e16..ead7ceccdf9 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -29,8 +29,7 @@ func init() { registerHTTPFilter(&extAuth{}) } -type extAuth struct { -} +type extAuth struct{} var _ httpFilter = &extAuth{} @@ -212,7 +211,8 @@ func routeContainsExtAuth(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the external auth services. func (*extAuth) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index ac03a49d08e..7ed060824ce 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -27,8 +27,7 @@ func init() { registerHTTPFilter(&extProc{}) } -type extProc struct { -} +type extProc struct{} var _ httpFilter = &extProc{} @@ -130,7 +129,8 @@ func routeContainsExtProc(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the external services. func (*extProc) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } diff --git a/internal/xds/translator/fault.go b/internal/xds/translator/fault.go index ae01b566c84..46642934ce1 100644 --- a/internal/xds/translator/fault.go +++ b/internal/xds/translator/fault.go @@ -30,8 +30,7 @@ func init() { registerHTTPFilter(&fault{}) } -type fault struct { -} +type fault struct{} var _ httpFilter = &fault{} @@ -39,7 +38,6 @@ var _ httpFilter = &fault{} // if applicable, and it does not already exist. // Note: this method creates an fault filter for each route that contains an Fault config. func (*fault) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { - if mgr == nil { return errors.New("hcm is nil") } @@ -179,7 +177,6 @@ func (*fault) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { route.TypedPerFilterConfig[wellknown.Fault] = routeCfgAny return nil - } // translatePercentToFractionalPercent translates an v1alpha3 Percent instance diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 143c8d77320..0b8f6dbeff9 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -159,7 +159,8 @@ func sortHTTPFilters(filters []*hcmv3.HttpFilter) []*hcmv3.HttpFilter { // newOrderedHTTPFilter method. func (t *Translator) patchHCMWithFilters( mgr *hcmv3.HttpConnectionManager, - irListener *ir.HTTPListener) error { + irListener *ir.HTTPListener, +) error { // The order of filter patching is not relevant here. // All the filters will be sorted in correct order after the patching is done. // @@ -197,8 +198,8 @@ func (t *Translator) patchHCMWithFilters( // provided route. func patchRouteWithPerRouteConfig( route *routev3.Route, - irRoute *ir.HTTPRoute) error { - + irRoute *ir.HTTPRoute, +) error { for _, filter := range httpFilters { if err := filter.patchRoute(route, irRoute); err != nil { return err @@ -207,8 +208,7 @@ func patchRouteWithPerRouteConfig( // RateLimit filter is handled separately because it relies on the global // rate limit server configuration. - if err := - patchRouteWithRateLimit(route.GetRoute(), irRoute); err != nil { + if err := patchRouteWithRateLimit(route.GetRoute(), irRoute); err != nil { return nil } diff --git a/internal/xds/translator/jwt.go b/internal/xds/translator/jwt.go index b6bf2275efa..27697043a46 100644 --- a/internal/xds/translator/jwt.go +++ b/internal/xds/translator/jwt.go @@ -34,8 +34,7 @@ func init() { registerHTTPFilter(&jwt{}) } -type jwt struct { -} +type jwt struct{} var _ httpFilter = &jwt{} @@ -134,7 +133,8 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, for _, claimToHeader := range irProvider.ClaimToHeaders { claimToHeader := &jwtauthnv3.JwtClaimToHeader{ HeaderName: claimToHeader.Header, - ClaimName: claimToHeader.Claim} + ClaimName: claimToHeader.Claim, + } claimToHeaders = append(claimToHeaders, claimToHeader) } jwtProvider := &jwtauthnv3.JwtProvider{ @@ -242,7 +242,8 @@ func (*jwt) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { } routeCfgProto := &jwtauthnv3.PerRouteConfig{ - RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}} + RequirementSpecifier: &jwtauthnv3.PerRouteConfig_RequirementName{RequirementName: irRoute.Name}, + } routeCfgAny, err := anypb.New(routeCfgProto) if err != nil { diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 55b29d168eb..af81f20aa89 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -209,7 +209,8 @@ func buildXdsQuicListener(name, address string, port uint32, accesslog *ir.Acces // The newly created TCP filter chain is configured with a filter chain match to // match the server names(SNI) based on the listener's hostnames. func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irListener *ir.HTTPListener, - accesslog *ir.AccessLog, tracing *ir.Tracing, http3Listener bool, connection *ir.Connection) error { + accesslog *ir.AccessLog, tracing *ir.Tracing, http3Listener bool, connection *ir.Connection, +) error { al := buildXdsAccessLog(accesslog, false) hcmTracing, err := buildHCMTracing(tracing) @@ -226,8 +227,8 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis } // Client IP detection - var useRemoteAddress = true - var originalIPDetectionExtensions = originalIPDetectionExtensions(irListener.ClientIPDetection) + useRemoteAddress := true + originalIPDetectionExtensions := originalIPDetectionExtensions(irListener.ClientIPDetection) if originalIPDetectionExtensions != nil { useRemoteAddress = false } @@ -720,7 +721,6 @@ func makeConfigSource() *corev3.ConfigSource { } func translateEscapePath(in ir.PathEscapedSlashAction) hcmv3.HttpConnectionManager_PathWithEscapedSlashesAction { - lookup := map[ir.PathEscapedSlashAction]hcmv3.HttpConnectionManager_PathWithEscapedSlashesAction{ ir.KeepUnchangedAction: hcmv3.HttpConnectionManager_KEEP_UNCHANGED, ir.RejectRequestAction: hcmv3.HttpConnectionManager_REJECT_REQUEST, diff --git a/internal/xds/translator/local_ratelimit.go b/internal/xds/translator/local_ratelimit.go index a3110cbf98e..adbcca6e749 100644 --- a/internal/xds/translator/local_ratelimit.go +++ b/internal/xds/translator/local_ratelimit.go @@ -35,8 +35,7 @@ func init() { registerHTTPFilter(&localRateLimit{}) } -type localRateLimit struct { -} +type localRateLimit struct{} var _ httpFilter = &localRateLimit{} @@ -106,7 +105,8 @@ func routeContainsLocalRateLimit(irRoute *ir.HTTPRoute) bool { } func (*localRateLimit) patchResources(*types.ResourceVersionTable, - []*ir.HTTPRoute) error { + []*ir.HTTPRoute, +) error { return nil } @@ -188,7 +188,8 @@ func (*localRateLimit) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) e } func buildRouteLocalRateLimits(local *ir.LocalRateLimit) ( - []*routev3.RateLimit, []*rlv3.LocalRateLimitDescriptor, error) { + []*routev3.RateLimit, []*rlv3.LocalRateLimitDescriptor, error, +) { var rateLimits []*routev3.RateLimit var descriptors []*rlv3.LocalRateLimitDescriptor diff --git a/internal/xds/translator/oidc.go b/internal/xds/translator/oidc.go index f7202a7f407..d005f4b4914 100644 --- a/internal/xds/translator/oidc.go +++ b/internal/xds/translator/oidc.go @@ -31,8 +31,7 @@ func init() { registerHTTPFilter(&oidc{}) } -type oidc struct { -} +type oidc struct{} var _ httpFilter = &oidc{} @@ -187,7 +186,8 @@ func routeContainsOIDC(irRoute *ir.HTTPRoute) bool { } func (*oidc) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if err := createOAuth2TokenEndpointClusters(tCtx, routes); err != nil { return err } @@ -200,7 +200,8 @@ func (*oidc) patchResources(tCtx *types.ResourceVersionTable, // createOAuth2TokenEndpointClusters creates token endpoint clusters from the // provided routes, if needed. func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } @@ -236,9 +237,10 @@ func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, ds = &ir.DestinationSetting{ Weight: ptr.To[uint32](1), - Endpoints: []*ir.DestinationEndpoint{ir.NewDestEndpoint( - cluster.hostname, - cluster.port), + Endpoints: []*ir.DestinationEndpoint{ + ir.NewDestEndpoint( + cluster.hostname, + cluster.port), }, } diff --git a/internal/xds/translator/runner/runner_test.go b/internal/xds/translator/runner/runner_test.go index 9f3d7035bd6..a7be53236c8 100644 --- a/internal/xds/translator/runner/runner_test.go +++ b/internal/xds/translator/runner/runner_test.go @@ -98,7 +98,6 @@ func TestRunner(t *testing.T) { // Ensure that xds has no key, value pairs return len(out) == 0 }, time.Second*5, time.Millisecond*50) - } func TestRunner_withExtensionManager(t *testing.T) { diff --git a/internal/xds/translator/tcpkeepalive.go b/internal/xds/translator/tcpkeepalive.go index 9d4c71d6d30..fcdd2a46992 100644 --- a/internal/xds/translator/tcpkeepalive.go +++ b/internal/xds/translator/tcpkeepalive.go @@ -62,5 +62,4 @@ func buildTCPSocketOptions(keepAlive *ir.TCPKeepalive) []*corev3.SocketOption { } return socketOptions - } diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index cd517a4d56e..19ab59f853c 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -301,7 +301,8 @@ func (t *Translator) addRouteToRouteConfig( xdsRouteCfg *routev3.RouteConfiguration, httpListener *ir.HTTPListener, metrics *ir.Metrics, - http3Enabled bool) error { + http3Enabled bool, +) error { var ( vHosts = map[string]*routev3.VirtualHost{} // store virtual hosts by domain vHostList []*routev3.VirtualHost // keep track of order by using a list as well as the map @@ -555,7 +556,8 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe // findXdsListenerByHostPort finds a xds listener with the same address, port and protocol, and returns nil if there is no match. func findXdsListenerByHostPort(tCtx *types.ResourceVersionTable, address string, port uint32, - protocol corev3.SocketAddress_Protocol) *listenerv3.Listener { + protocol corev3.SocketAddress_Protocol, +) *listenerv3.Listener { if tCtx == nil || tCtx.XdsResources == nil || tCtx.XdsResources[resourcev3.ListenerType] == nil { return nil } diff --git a/internal/xds/translator/wasm.go b/internal/xds/translator/wasm.go index 1c8c03951ca..4d358d707f7 100644 --- a/internal/xds/translator/wasm.go +++ b/internal/xds/translator/wasm.go @@ -30,8 +30,7 @@ func init() { registerHTTPFilter(&wasm{}) } -type wasm struct { -} +type wasm struct{} var _ httpFilter = &wasm{} @@ -172,7 +171,8 @@ func routeContainsWasm(irRoute *ir.HTTPRoute) bool { // patchResources patches the cluster resources for the http wasm code source. func (*wasm) patchResources(tCtx *types.ResourceVersionTable, - routes []*ir.HTTPRoute) error { + routes []*ir.HTTPRoute, +) error { if tCtx == nil || tCtx.XdsResources == nil { return errors.New("xds resource table is nil") } diff --git a/internal/xds/types/resourceversiontable.go b/internal/xds/types/resourceversiontable.go index 672096e6ab7..2f7a7926bd8 100644 --- a/internal/xds/types/resourceversiontable.go +++ b/internal/xds/types/resourceversiontable.go @@ -46,7 +46,7 @@ func (t *ResourceVersionTable) DeepCopyInto(out *ResourceVersionTable) { (*out)[key] = nil } else { // Snippet was generated by controller-gen - //G601: Implicit memory aliasing in for loop. + // G601: Implicit memory aliasing in for loop. in, out := &val, &outVal //nolint:gosec,scopelint *out = make([]types.Resource, len(*in)) for i := range *in { diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 64968c9e009..2cefef85e3e 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -810,7 +810,6 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { { desc: "valid count of Global rate limit rules items", mutate: func(btp *egv1a1.BackendTrafficPolicy) { - rules := make([]egv1a1.RateLimitRule, 64) rule := egv1a1.RateLimitRule{ Limit: egv1a1.RateLimitValue{ @@ -843,7 +842,6 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { { desc: "invalid count of Global rate limit rules items", mutate: func(btp *egv1a1.BackendTrafficPolicy) { - rules := make([]egv1a1.RateLimitRule, 65) rule := egv1a1.RateLimitRule{ Limit: egv1a1.RateLimitValue{ diff --git a/test/conformance/conformance_test.go b/test/conformance/conformance_test.go index 149909e2ce4..7eca6ea9d26 100644 --- a/test/conformance/conformance_test.go +++ b/test/conformance/conformance_test.go @@ -54,5 +54,4 @@ func TestGatewayAPIConformance(t *testing.T) { }) cSuite.Setup(t) cSuite.Run(t, tests.ConformanceTests) - } diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index b6d6b19e953..fa3598be1e0 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -129,7 +129,7 @@ func experimentalConformanceReport(logf func(string, ...any), report confv1a1.Co } if output != "" { - if err = os.WriteFile(output, rawReport, 0600); err != nil { + if err = os.WriteFile(output, rawReport, 0o600); err != nil { return err } } diff --git a/test/e2e/tests/backend_tls.go b/test/e2e/tests/backend_tls.go index 1c556a0bb78..dea222b477f 100644 --- a/test/e2e/tests/backend_tls.go +++ b/test/e2e/tests/backend_tls.go @@ -63,6 +63,5 @@ var BackendTLSTest = suite.ConformanceTest{ http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) }) - }, } diff --git a/test/e2e/tests/connection_limit.go b/test/e2e/tests/connection_limit.go index 220be1a5616..62f8f0011da 100644 --- a/test/e2e/tests/connection_limit.go +++ b/test/e2e/tests/connection_limit.go @@ -82,7 +82,6 @@ var ConnectionLimitTest = suite.ConformanceTest{ } else { t.Errorf("expected error when connection limit is reached") } - }) }, } diff --git a/test/e2e/tests/gateway_infra_resource.go b/test/e2e/tests/gateway_infra_resource.go index 864cc4b1b11..c14cb145050 100644 --- a/test/e2e/tests/gateway_infra_resource.go +++ b/test/e2e/tests/gateway_infra_resource.go @@ -25,7 +25,7 @@ import ( func init() { // nolint - //ConformanceTests = append(ConformanceTests, GatewayInfraResourceTest) + // ConformanceTests = append(ConformanceTests, GatewayInfraResourceTest) } // nolint diff --git a/test/e2e/tests/jwt.go b/test/e2e/tests/jwt.go index 73de072e62a..fc7e826dd46 100644 --- a/test/e2e/tests/jwt.go +++ b/test/e2e/tests/jwt.go @@ -170,6 +170,5 @@ var OptionalJWTTest = suite.ConformanceTest{ http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) }) } - }, } diff --git a/test/e2e/tests/merge_gateways.go b/test/e2e/tests/merge_gateways.go index 9b725cb40f2..abcd809f70d 100644 --- a/test/e2e/tests/merge_gateways.go +++ b/test/e2e/tests/merge_gateways.go @@ -146,6 +146,5 @@ var MergeGatewaysTest = suite.ConformanceTest{ Namespace: ns, }) }) - }, } diff --git a/test/e2e/tests/preservecase.go b/test/e2e/tests/preservecase.go index 59d54c2f84e..458bebd8219 100644 --- a/test/e2e/tests/preservecase.go +++ b/test/e2e/tests/preservecase.go @@ -135,6 +135,5 @@ var PreserveCaseTest = suite.ConformanceTest{ t.Errorf("case was not preserved for test header: %+v", respBody) } }) - }, } diff --git a/test/e2e/tests/ratelimit.go b/test/e2e/tests/ratelimit.go index c02802abe1f..0115dbe0089 100644 --- a/test/e2e/tests/ratelimit.go +++ b/test/e2e/tests/ratelimit.go @@ -284,7 +284,6 @@ var RateLimitBasedJwtClaimsTest = suite.ConformanceTest{ if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, noTokenReq, noTokenResp); err != nil { t.Errorf("failed to get expected response: %v", err) } - }) }, } diff --git a/test/e2e/tests/redirect_replaceprefixmatch_slash.go b/test/e2e/tests/redirect_replaceprefixmatch_slash.go index 3dcc4e90873..c1986809000 100644 --- a/test/e2e/tests/redirect_replaceprefixmatch_slash.go +++ b/test/e2e/tests/redirect_replaceprefixmatch_slash.go @@ -19,7 +19,6 @@ import ( func init() { ConformanceTests = append(ConformanceTests, RedirectTrailingSlashTest) - } // RedirectTrailingSlashTest tests that only one slash in the redirect URL diff --git a/test/e2e/tests/retry.go b/test/e2e/tests/retry.go index c2acfecf34c..c067df3752d 100644 --- a/test/e2e/tests/retry.go +++ b/test/e2e/tests/retry.go @@ -24,7 +24,6 @@ import ( func init() { ConformanceTests = append(ConformanceTests, RetryTest) - } var RetryTest = suite.ConformanceTest{ diff --git a/test/e2e/tests/tcp_route.go b/test/e2e/tests/tcp_route.go index 0aa8b609e79..f09521db010 100644 --- a/test/e2e/tests/tcp_route.go +++ b/test/e2e/tests/tcp_route.go @@ -77,7 +77,6 @@ var TCPRouteTest = suite.ConformanceTest{ // Send a request to an valid path and expect a successful response http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, OkResp) }) - }, } @@ -124,7 +123,6 @@ func GatewayAndTCPRoutesMustBeAccepted(t *testing.T, c client.Client, timeoutCon } return gwAddr - } // WaitForGatewayAddress waits until at least one IP Address has been set in the diff --git a/test/e2e/tests/tracing.go b/test/e2e/tests/tracing.go index 880b166b4f8..9ded2662cf9 100644 --- a/test/e2e/tests/tracing.go +++ b/test/e2e/tests/tracing.go @@ -119,7 +119,6 @@ func QueryTraceFromTempo(t *testing.T, c client.Client, tags map[string]string) req, err := http.NewRequest("GET", tempoURL.String(), nil) if err != nil { - return -1, err } diff --git a/test/e2e/tests/weighted_backend.go b/test/e2e/tests/weighted_backend.go index b31dce8f04f..250c6ef4cc3 100644 --- a/test/e2e/tests/weighted_backend.go +++ b/test/e2e/tests/weighted_backend.go @@ -70,7 +70,6 @@ var WeightEqualTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -135,7 +134,6 @@ var WeightBlueGreenTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -200,7 +198,6 @@ var WeightCompleteRolloutTest = suite.ConformanceTest{ if len(podName) == 0 { // it shouldn't be missing here t.Errorf("failed to get pod header in response: %v", err) - } else { // all we need is the pod Name prefix podNamePrefix := ExtractPodNamePrefix(podName) @@ -222,7 +219,6 @@ var WeightCompleteRolloutTest = suite.ConformanceTest{ // ExtractPodNamePrefix Extract the Pod Name prefix func ExtractPodNamePrefix(podName string) string { - pattern := regexp.MustCompile(`infra-backend-(.+?)-`) match := pattern.FindStringSubmatch(podName) if len(match) > 1 { diff --git a/tools/linter/golangci-lint/.golangci.yml b/tools/linter/golangci-lint/.golangci.yml index 36ed0cb1ff2..267fbc46c9a 100644 --- a/tools/linter/golangci-lint/.golangci.yml +++ b/tools/linter/golangci-lint/.golangci.yml @@ -8,6 +8,7 @@ linters: - errorlint - exportloopref - gofmt + - gofumpt - goimports - goheader - gocritic From 892d2e3abe19cc0932de5b36260cb6d345d27b44 Mon Sep 17 00:00:00 2001 From: Huabing Zhao Date: Mon, 29 Apr 2024 20:50:55 -0700 Subject: [PATCH 10/29] doc: update oidc docs (#3275) * update oidc docs Signed-off-by: huabing zhao * update oidc docs Signed-off-by: huabing zhao * fix docs lint Signed-off-by: huabing zhao * fix docs lint Signed-off-by: huabing zhao --------- Signed-off-by: huabing zhao --- site/content/en/latest/tasks/security/oidc.md | 139 ++++++++++-- .../latest/tasks/security/secure-gateways.md | 4 +- site/content/en/v1.0.1/tasks/security/oidc.md | 208 +++++++++++++++--- .../v1.0.1/tasks/security/secure-gateways.md | 4 +- 4 files changed, 305 insertions(+), 50 deletions(-) diff --git a/site/content/en/latest/tasks/security/oidc.md b/site/content/en/latest/tasks/security/oidc.md index 0360ccd496f..ac7d6d60ba9 100644 --- a/site/content/en/latest/tasks/security/oidc.md +++ b/site/content/en/latest/tasks/security/oidc.md @@ -4,7 +4,7 @@ title: "OIDC Authentication" This task provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. -It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) +It enables EG to rely on authentication that is performed by an OpenID Connect Provider (OP) to verify the identity of a user. Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC @@ -16,17 +16,15 @@ This instantiated resource can be linked to a [Gateway][Gateway] and [HTTPRoute] Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. +EG OIDC authentication requires the redirect URL to be HTTPS. Follow the [Secure Gateways](../secure-gateways) guide +to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. + Verify the Gateway status: ```shell kubectl get gateway/eg -o yaml ``` -OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with -the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. - -This task demonstrates the configuration of OIDC at the HTTPRoute level. - Let's create an HTTPRoute that represents an application protected by OIDC. {{< tabpane text=true >}} @@ -86,16 +84,21 @@ Verify the HTTPRoute status: kubectl get httproute/myapp -o yaml ``` -## Configuration +## OIDC Authentication for a HTTPRoute -This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC -providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a specific HTTPRoute. ### Register an OIDC application +This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC +providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. + Follow the steps in the [Google OIDC documentation][google-oidc] to register an OIDC application. Please make sure the redirect URL is set to the one you configured in the SecurityPolicy that you will create in the step below. In this example, -the redirect URL is `http://www.example.com:8080/myapp/oauth2/callback`. +the redirect URL is `http://www.example.com:8443/myapp/oauth2/callback`. After registering the application, you should have the following information: * Client ID: The client ID of the OIDC application. @@ -109,15 +112,14 @@ and the Client Secret must be stored in the key "client-secret". Note: please replace the ${CLIENT_SECRET} with the actual Client Secret that you got from the previous step. ```shell -$ kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} -secret "my-app-client-secret" created +kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} ``` ### Create a SecurityPolicy -Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute. In this example, the target +**Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute.** In this example, the target HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed -with `http://www.example.com:8080/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication +with `https://www.example.com:8443/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed by the OAuth2 filter on that HTTPRoute. @@ -143,7 +145,7 @@ spec: clientID: "${CLIENT_ID}" clientSecret: name: "my-app-client-secret" - redirectURL: "http://www.example.com:8080/myapp/oauth2/callback" + redirectURL: "https://www.example.com:8443/myapp/oauth2/callback" logoutPath: "/myapp/logout" EOF ``` @@ -169,7 +171,7 @@ spec: clientID: "${CLIENT_ID}" clientSecret: name: "my-app-client-secret" - redirectURL: "http://www.example.com:8080/myapp/oauth2/callback" + redirectURL: "https://www.example.com:8443/myapp/oauth2/callback" logoutPath: "/myapp/logout" ``` @@ -182,14 +184,14 @@ Verify the SecurityPolicy configuration: kubectl get securitypolicy/oidc-example -o yaml ``` -## Testing +### Testing Port forward gateway port to localhost: ```shell export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8080:80 +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 ``` Put www.example.com in the /etc/hosts file in your test machine, so we can use this host name to access the gateway from a browser: @@ -199,9 +201,104 @@ Put www.example.com in the /etc/hosts file in your test machine, so we can use t 127.0.0.1 www.example.com ``` -Open a browser and navigate to the `http://www.example.com:8080/myapp` address. You should be redirected to the Google +Open a browser and navigate to the `https://www.example.com:8443/myapp` address. You should be redirected to the Google +login page. After you successfully login, you should see the response from the backend service. + +Clean the cookies in the browser and try to access `https://www.example.com:8443/foo` address. You should be able to see +this page since the path `/foo` is not protected by the OIDC policy. + +## OIDC Authentication for a Gateway + +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a Gateway. + +### Register an OIDC application + +If you haven't registered an OIDC application, follow the steps in the previous section to register an OIDC application. + +### Create a kubernetes secret + +If you haven't created a kubernetes secret, follow the steps in the previous section to create a kubernetes secret. + +### Create a SecurityPolicy + +Create or update the SecurityPolicy to target the Gateway instead of the HTTPRoute. **Please notice that the `redirectURL` +and `logoutPath` must match one of the HTTPRoutes associated with the Gateway.** In this example, the target Gateway has +two HTTPRoutes associated with it, one with the host `www.example.com` and the path `/myapp`, and the other with the host +`www.example.com` and the path `/`. Either one of the HTTPRoutes can be used to match the `redirectURL` and `logoutPath`. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/oidc-example -o yaml +``` + +### Testing + +If you haven't done so, follow the steps in the previous section to port forward gateway port to localhost and put +www.example.com in the /etc/hosts file in your test machine. + +Open a browser and navigate to the `https://www.example.com:8443/foo` address. You should be redirected to the Google login page. After you successfully login, you should see the response from the backend service. +You can also try to access `https://www.example.com:8443/myapp` address. You should be able to see this page since the +path `/myapp` is protected by the same OIDC policy. + ## Clean-Up Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. @@ -216,10 +313,10 @@ kubectl delete httproute/myapp ## Next Steps -Checkout the [Developer Guide](../../../contributions/develop) to get involved in the project. +Checkout the [Developer Guide](../../../../contributions/develop) to get involved in the project. [oidc]: https://openid.net/connect/ [google-oidc]: https://developers.google.com/identity/protocols/oauth2/openid-connect -[SecurityPolicy]: ../../../contributions/design/security-policy +[SecurityPolicy]: ../../../../contributions/design/security-policy [Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway [HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute diff --git a/site/content/en/latest/tasks/security/secure-gateways.md b/site/content/en/latest/tasks/security/secure-gateways.md index e57b1236389..92f685705a4 100644 --- a/site/content/en/latest/tasks/security/secure-gateways.md +++ b/site/content/en/latest/tasks/security/secure-gateways.md @@ -297,7 +297,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: @@ -423,7 +423,7 @@ This sections gives a walkthrough to generate multiple certificates correspondin ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. Follow the steps in the [TLS Certificates](#tls-certificates) section to generate self-signed RSA derived Server certificate and private key, and configure those in the Gateway listener configuration to terminate HTTPS traffic. diff --git a/site/content/en/v1.0.1/tasks/security/oidc.md b/site/content/en/v1.0.1/tasks/security/oidc.md index 81bdaa882ac..c11a52bbfef 100644 --- a/site/content/en/v1.0.1/tasks/security/oidc.md +++ b/site/content/en/v1.0.1/tasks/security/oidc.md @@ -2,9 +2,9 @@ title: "OIDC Authentication" --- -This guide provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. +This task provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. -It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) +It enables EG to rely on authentication that is performed by an OpenID Connect Provider (OP) to verify the identity of a user. Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC @@ -13,22 +13,23 @@ This instantiated resource can be linked to a [Gateway][Gateway] and [HTTPRoute] ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) guide to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. +EG OIDC authentication requires the redirect URL to be HTTPS. Follow the [Secure Gateways](../secure-gateways) guide +to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. + Verify the Gateway status: ```shell kubectl get gateway/eg -o yaml ``` -OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with -the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. - -This guide demonstrates the configuration of OIDC at the HTTPRoute level. - Let's create an HTTPRoute that represents an application protected by OIDC. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + Verify the HTTPRoute status: ```shell kubectl get httproute/myapp -o yaml ``` -## Configuration +## OIDC Authentication for a HTTPRoute -This guide uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC -providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a specific HTTPRoute. ### Register an OIDC application +This task uses Google as the OIDC provider to demonstrate the configuration of OIDC. However, EG works with any OIDC +providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, etc. + Follow the steps in the [Google OIDC documentation][google-oidc] to register an OIDC application. Please make sure the redirect URL is set to the one you configured in the SecurityPolicy that you will create in the step below. In this example, -the redirect URL is `http://www.example.com:8080/myapp/oauth2/callback`. +the redirect URL is `http://www.example.com:8443/myapp/oauth2/callback`. After registering the application, you should have the following information: * Client ID: The client ID of the OIDC application. @@ -79,20 +112,22 @@ and the Client Secret must be stored in the key "client-secret". Note: please replace the ${CLIENT_SECRET} with the actual Client Secret that you got from the previous step. ```shell -$ kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} -secret "my-app-client-secret" created +kubectl create secret generic my-app-client-secret --from-literal=client-secret=${CLIENT_SECRET} ``` ### Create a SecurityPolicy -Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute. In this example, the target -HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed -with `http://www.example.com:8080/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication -will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed +**Please notice that the `redirectURL` and `logoutPath` must match the target HTTPRoute.** In this example, the target +HTTPRoute is configured to match the host `www.example.com` and the path `/myapp`, so the `redirectURL` must be prefixed +with `https://www.example.com:8443/myapp`, and `logoutPath` must be prefixed with`/myapp`, otherwise the OIDC authentication +will fail because the redirect and logout requests will not match the target HTTPRoute and therefore can't be processed by the OAuth2 filter on that HTTPRoute. Note: please replace the ${CLIENT_ID} in the below yaml snippet with the actual Client ID that you got from the OIDC provider. +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + ```shell cat <}} + Verify the SecurityPolicy configuration: ```shell kubectl get securitypolicy/oidc-example -o yaml ``` -## Testing +### Testing Port forward gateway port to localhost: ```shell export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8080:80 +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 ``` Put www.example.com in the /etc/hosts file in your test machine, so we can use this host name to access the gateway from a browser: @@ -138,12 +201,107 @@ Put www.example.com in the /etc/hosts file in your test machine, so we can use t 127.0.0.1 www.example.com ``` -Open a browser and navigate to the `http://www.example.com:8080/myapp` address. You should be redirected to the Google +Open a browser and navigate to the `https://www.example.com:8443/myapp` address. You should be redirected to the Google login page. After you successfully login, you should see the response from the backend service. +Clean the cookies in the browser and try to access `https://www.example.com:8443/foo` address. You should be able to see +this page since the path `/foo` is not protected by the OIDC policy. + +## OIDC Authentication for a Gateway + +OIDC can be configured at the Gateway level to authenticate all the HTTPRoutes that are associated with the Gateway with +the same OIDC configuration, or at the HTTPRoute level to authenticate each HTTPRoute with different OIDC configurations. + +This section demonstrates how to configure OIDC authentication for a Gateway. + +### Register an OIDC application + +If you haven't registered an OIDC application, follow the steps in the previous section to register an OIDC application. + +### Create a kubernetes secret + +If you haven't created a kubernetes secret, follow the steps in the previous section to create a kubernetes secret. + +### Create a SecurityPolicy + +Create or update the SecurityPolicy to target the Gateway instead of the HTTPRoute. **Please notice that the `redirectURL` +and `logoutPath` must match one of the HTTPRoutes associated with the Gateway.** In this example, the target Gateway has +two HTTPRoutes associated with it, one with the host `www.example.com` and the path `/myapp`, and the other with the host +`www.example.com` and the path `/`. Either one of the HTTPRoutes can be used to match the `redirectURL` and `logoutPath`. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +Verify the SecurityPolicy configuration: + +```shell +kubectl get securitypolicy/oidc-example -o yaml +``` + +### Testing + +If you haven't done so, follow the steps in the previous section to port forward gateway port to localhost and put +www.example.com in the /etc/hosts file in your test machine. + +Open a browser and navigate to the `https://www.example.com:8443/foo` address. You should be redirected to the Google +login page. After you successfully login, you should see the response from the backend service. + +You can also try to access `https://www.example.com:8443/myapp` address. You should be able to see this page since the +path `/myapp` is protected by the same OIDC policy. + ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) guide to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the SecurityPolicy, the secret and the HTTPRoute: @@ -155,10 +313,10 @@ kubectl delete httproute/myapp ## Next Steps -Checkout the [Developer Guide](../../../contributions/develop) to get involved in the project. +Checkout the [Developer Guide](../../../../contributions/develop) to get involved in the project. [oidc]: https://openid.net/connect/ [google-oidc]: https://developers.google.com/identity/protocols/oauth2/openid-connect -[SecurityPolicy]: ../../../contributions/design/security-policy +[SecurityPolicy]: ../../../../contributions/design/security-policy [Gateway]: https://gateway-api.sigs.k8s.io/api-types/gateway [HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute diff --git a/site/content/en/v1.0.1/tasks/security/secure-gateways.md b/site/content/en/v1.0.1/tasks/security/secure-gateways.md index e56a496e022..52bf8c9cb78 100644 --- a/site/content/en/v1.0.1/tasks/security/secure-gateways.md +++ b/site/content/en/v1.0.1/tasks/security/secure-gateways.md @@ -236,7 +236,7 @@ Lastly, test connectivity using the above [Testing section](#testing). ## Clean-Up -Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to uninstall Envoy Gateway and the example manifest. Delete the Secrets: @@ -362,7 +362,7 @@ This sections gives a walkthrough to generate multiple certificates correspondin ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. +Follow the steps from the [Quickstart](../quickstart) to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP. Follow the steps in the [TLS Certificates](#tls-certificates) section to generate self-signed RSA derived Server certificate and private key, and configure those in the Gateway listener configuration to terminate HTTPS traffic. From 9a33089bb2340338355e2d8153f8e91c4fcafb4b Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 30 Apr 2024 20:09:51 +0800 Subject: [PATCH 11/29] e2e: disable unstable tests (#3306) * e2e: disable unstable tests Signed-off-by: zirain * ref issue Signed-off-by: zirain * disable EnvoyShutdownTest Signed-off-by: zirain --------- Signed-off-by: zirain --- test/e2e/e2e_test.go | 3 +++ test/e2e/merge_gateways/merge_gateways_test.go | 6 ++++-- test/e2e/upgrade/eg_upgrade_test.go | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 46e0fb30bec..3159f0bd2a4 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -51,6 +51,9 @@ func TestE2E(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, FS: &Manifests, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.ClientTimeoutTest.ShortName, // https://github.com/envoyproxy/gateway/issues/2720 + }, }) cSuite.Setup(t) diff --git a/test/e2e/merge_gateways/merge_gateways_test.go b/test/e2e/merge_gateways/merge_gateways_test.go index 30e82aa6cdd..9c056875c32 100644 --- a/test/e2e/merge_gateways/merge_gateways_test.go +++ b/test/e2e/merge_gateways/merge_gateways_test.go @@ -52,14 +52,16 @@ func TestMergeGateways(t *testing.T) { Debug: *flags.ShowDebug, CleanupBaseResources: *flags.CleanupBaseResources, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.MergeGatewaysTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3290 + }, }) // Setting up the necessary arguments for the suite instead of calling Suite.Setup method again, // since this test suite reuse the base resources of previous test suite. cSuite.Applier.FS = e2e.Manifests cSuite.Applier.GatewayClass = *flags.GatewayClassName - cSuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, - cSuite.Client, cSuite.TimeoutConfig, cSuite.GatewayClassName) + cSuite.ControllerName = kubernetes.GWCMustHaveAcceptedConditionTrue(t, cSuite.Client, cSuite.TimeoutConfig, cSuite.GatewayClassName) t.Logf("Running %d MergeGateways tests", len(tests.MergeGatewaysTests)) cSuite.Run(t, tests.MergeGatewaysTests) diff --git a/test/e2e/upgrade/eg_upgrade_test.go b/test/e2e/upgrade/eg_upgrade_test.go index a1be622cb0f..6ad83b14bd4 100644 --- a/test/e2e/upgrade/eg_upgrade_test.go +++ b/test/e2e/upgrade/eg_upgrade_test.go @@ -52,6 +52,9 @@ func TestEGUpgrade(t *testing.T) { CleanupBaseResources: *flags.CleanupBaseResources, FS: &e2e.Manifests, RunTest: *flags.RunTest, + SkipTests: []string{ + tests.EnvoyShutdownTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3262 + }, }) cSuite.Setup(t) From d38c09f3d1eee2a9b56a11477b11d5e3703a46ef Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Tue, 30 Apr 2024 07:17:39 -0500 Subject: [PATCH 12/29] feat(translator): extproc timeout, failopen and backendRefs (#3206) * impl extproc timeout, failopen, backendRefs Signed-off-by: Guy Daich * fix xds translator test Signed-off-by: Guy Daich * fix xds translator test Signed-off-by: Guy Daich * fix gen Signed-off-by: Guy Daich * impl procmode Signed-off-by: Guy Daich * fix test Signed-off-by: Guy Daich * fixes Signed-off-by: Guy Daich * remove unused struct Signed-off-by: Guy Daich --------- Signed-off-by: Guy Daich --- api/v1alpha1/ext_proc_types.go | 23 +- api/v1alpha1/zz_generated.deepcopy.go | 17 -- ....envoyproxy.io_envoyextensionpolicies.yaml | 96 +----- internal/gatewayapi/envoyextensionpolicy.go | 85 ++++-- internal/gatewayapi/ext_service.go | 7 +- ...tensionpolicy-invalid-cross-ns-ref.in.yaml | 4 +- ...ensionpolicy-invalid-cross-ns-ref.out.yaml | 4 +- ...oyextensionpolicy-override-replace.in.yaml | 8 +- ...yextensionpolicy-override-replace.out.yaml | 12 +- ...h-extproc-invalid-no-matching-port.in.yaml | 4 +- ...-extproc-invalid-no-matching-port.out.yaml | 4 +- ...olicy-with-extproc-invalid-no-port.in.yaml | 4 +- ...licy-with-extproc-invalid-no-port.out.yaml | 4 +- ...extproc-invalid-no-reference-grant.in.yaml | 4 +- ...xtproc-invalid-no-reference-grant.out.yaml | 4 +- ...cy-with-extproc-invalid-no-service.in.yaml | 4 +- ...y-with-extproc-invalid-no-service.out.yaml | 4 +- ...with-extproc-with-backendtlspolicy.in.yaml | 18 +- ...ith-extproc-with-backendtlspolicy.out.yaml | 30 +- ...-extproc-with-multiple-backendrefs.in.yaml | 192 ++++++++++++ ...extproc-with-multiple-backendrefs.out.yaml | 277 ++++++++++++++++++ internal/ir/xds.go | 34 ++- internal/ir/zz_generated.deepcopy.go | 20 ++ internal/provider/kubernetes/controller.go | 66 +++-- internal/provider/kubernetes/indexers.go | 18 +- .../provider/kubernetes/predicates_test.go | 16 +- internal/xds/translator/extproc.go | 50 +++- .../testdata/in/xds-ir/ext-proc.yaml | 73 +++-- .../out/xds-ir/ext-proc.clusters.yaml | 88 ++++++ .../out/xds-ir/ext-proc.endpoints.yaml | 20 ++ .../out/xds-ir/ext-proc.listeners.yaml | 64 ++++ .../testdata/out/xds-ir/ext-proc.routes.yaml | 14 + internal/xds/translator/translator.go | 23 -- internal/xds/translator/utils.go | 7 - site/content/en/latest/api/extension_types.md | 23 +- .../envoyextensionpolicy_test.go | 48 +-- .../ext-proc-envoyextensionpolicy.yaml | 25 +- test/e2e/testdata/ext-proc-service.yaml | 113 ++++--- test/e2e/tests/ext_proc.go | 29 +- 39 files changed, 1134 insertions(+), 402 deletions(-) create mode 100644 internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml create mode 100755 internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go index ef5e409d9db..85f250c6314 100644 --- a/api/v1alpha1/ext_proc_types.go +++ b/api/v1alpha1/ext_proc_types.go @@ -45,18 +45,15 @@ type ExtProcProcessingMode struct { Response *ProcessingModeOptions `json:"response,omitempty"` } -// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.group) || self.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported" -// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.kind) || self.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported" -// // ExtProc defines the configuration for External Processing filter. type ExtProc struct { - // BackendRef defines the configuration of the external processing service - BackendRef ExtProcBackendRef `json:"backendRef"` - // BackendRefs defines the configuration of the external processing service // - // +optional - BackendRefs []BackendRef `json:"backendRefs,omitempty"` + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=1 + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="self.all(f, f.kind == 'Service')" + // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" + BackendRefs []BackendRef `json:"backendRefs"` // MessageTimeout is the timeout for a response to be returned from the external processor // Default: 200ms @@ -77,13 +74,3 @@ type ExtProc struct { // +optional ProcessingMode *ExtProcProcessingMode `json:"processingMode,omitempty"` } - -// ExtProcService defines the gRPC External Processing service using the envoy grpc client -// The processing request and response messages are defined in -// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/ext_proc/v3/external_processor.proto -type ExtProcBackendRef struct { - // BackendObjectReference references a Kubernetes object that represents the - // backend server to which the processing requests will be sent. - // Only service Kind is supported for now. - gwapiv1.BackendObjectReference `json:",inline"` -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2dac3319301..c3d53f443ba 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1641,7 +1641,6 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in - in.BackendRef.DeepCopyInto(&out.BackendRef) if in.BackendRefs != nil { in, out := &in.BackendRefs, &out.BackendRefs *out = make([]BackendRef, len(*in)) @@ -1676,22 +1675,6 @@ func (in *ExtProc) DeepCopy() *ExtProc { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtProcBackendRef) DeepCopyInto(out *ExtProcBackendRef) { - *out = *in - in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProcBackendRef. -func (in *ExtProcBackendRef) DeepCopy() *ExtProcBackendRef { - if in == nil { - return nil - } - out := new(ExtProcBackendRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtProcProcessingMode) DeepCopyInto(out *ExtProcProcessingMode) { *out = *in diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 257cc8372f8..f8c0135411b 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -54,83 +54,6 @@ spec: description: ExtProc defines the configuration for External Processing filter. properties: - backendRef: - description: BackendRef defines the configuration of the external - processing service - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - x-kubernetes-validations: - - message: Must have port for Service reference - rule: '(size(self.group) == 0 && self.kind == ''Service'') - ? has(self.port) : true' backendRefs: description: BackendRefs defines the configuration of the external processing service @@ -211,7 +134,14 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 1 + minItems: 1 type: array + x-kubernetes-validations: + - message: BackendRefs only supports Service kind. + rule: self.all(f, f.kind == 'Service') + - message: BackendRefs only supports Core group. + rule: self.all(f, f.group == '') failOpen: description: |- FailOpen defines if requests or responses that cannot be processed due to connectivity to the @@ -257,18 +187,8 @@ spec: type: object type: object required: - - backendRef + - backendRefs type: object - x-kubernetes-validations: - - message: group is invalid, only the core API group (specified - by omitting the group field or setting it to an empty string) - is supported - rule: 'has(self.backendRef) ? (!has(self.backendRef.group) || - self.backendRef.group == "") : true' - - message: kind is invalid, only Service (specified by omitting - the kind field or setting it to 'Service') is supported - rule: 'has(self.backendRef) ? (!has(self.backendRef.kind) || self.backendRef.kind - == ''Service'') : true' type: array targetRef: description: |- diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 655d4cb798b..edb0dc385a9 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -10,13 +10,13 @@ import ( "fmt" "sort" "strings" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/ptr" - gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -404,48 +404,79 @@ func (t *Translator) buildExtProc( resources *Resources, ) (*ir.ExtProc, error) { var ( - backendRef *gwapiv1.BackendObjectReference - ds *ir.DestinationSetting - authority string - err error + ds *ir.DestinationSetting + authority string + err error ) - backendRef = &extProc.BackendRef.BackendObjectReference + var dsl []*ir.DestinationSetting + for i := range extProc.BackendRefs { + if err = t.validateExtServiceBackendReference( + &extProc.BackendRefs[i].BackendObjectReference, + policyNamespacedName.Namespace, + resources); err != nil { + return nil, err + } - if err = t.validateExtServiceBackendReference( - backendRef, - policyNamespacedName.Namespace, - resources); err != nil { - return nil, err - } + ds, err = t.processExtServiceDestination( + &extProc.BackendRefs[i].BackendObjectReference, + policyNamespacedName, + egv1a1.KindEnvoyExtensionPolicy, + ir.GRPC, + resources) - authority = fmt.Sprintf( - "%s.%s:%d", - backendRef.Name, - NamespaceDerefOr(backendRef.Namespace, policyNamespacedName.Namespace), - *backendRef.Port) + if err != nil { + return nil, err + } - if ds, err = t.processExtServiceDestination( - backendRef, - policyNamespacedName, - egv1a1.KindEnvoyExtensionPolicy, - ir.GRPC, - resources); err != nil { - return nil, err + dsl = append(dsl, ds) } rd := ir.RouteDestination{ - Name: irIndexedExtServiceDestinationName(policyNamespacedName, egv1a1.KindEnvoyExtensionPolicy, - string(backendRef.Name), extProcIdx), - Settings: []*ir.DestinationSetting{ds}, + Name: irIndexedExtServiceDestinationName(policyNamespacedName, egv1a1.KindEnvoyExtensionPolicy, extProcIdx), + Settings: dsl, } + authority = fmt.Sprintf( + "%s.%s:%d", + extProc.BackendRefs[0].Name, + NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace), + *extProc.BackendRefs[0].Port) + extProcIR := &ir.ExtProc{ Name: name, Destination: rd, Authority: authority, } + if extProc.MessageTimeout != nil { + d, err := time.ParseDuration(string(*extProc.MessageTimeout)) + if err != nil { + return nil, fmt.Errorf("invalid ExtProc MessageTimeout value %v", extProc.MessageTimeout) + } + extProcIR.MessageTimeout = ptr.To(metav1.Duration{Duration: d}) + } + + if extProc.FailOpen != nil { + extProcIR.FailOpen = extProc.FailOpen + } + + if extProc.ProcessingMode != nil { + if extProc.ProcessingMode.Request != nil { + extProcIR.RequestHeaderProcessing = true + if extProc.ProcessingMode.Request.Body != nil { + extProcIR.RequestBodyProcessingMode = ptr.To(ir.ExtProcBodyProcessingMode(*extProc.ProcessingMode.Request.Body)) + } + } + + if extProc.ProcessingMode.Response != nil { + extProcIR.ResponseHeaderProcessing = true + if extProc.ProcessingMode.Response.Body != nil { + extProcIR.ResponseBodyProcessingMode = ptr.To(ir.ExtProcBodyProcessingMode(*extProc.ProcessingMode.Response.Body)) + } + } + } + return extProcIR, err } diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index 6a9a5e225dc..ec1c77063a0 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -94,12 +94,11 @@ func (t *Translator) processExtServiceDestination( } // TODO: also refer to extension type, as WASM may also introduce destinations -func irIndexedExtServiceDestinationName(policyNamespacedName types.NamespacedName, policyKind, service string, idx int) string { +func irIndexedExtServiceDestinationName(policyNamespacedName types.NamespacedName, policyKind string, idx int) string { return strings.ToLower(fmt.Sprintf( - "%s/%s/%s/%d/%s", + "%s/%s/%s/%d", policyKind, policyNamespacedName.Namespace, policyNamespacedName.Name, - idx, - service)) + idx)) } diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml index 0f6d26cf62c..6f4ed53ab78 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.in.yaml @@ -26,6 +26,6 @@ envoyExtensionPolicies: name: gateway-1 namespace: envoy-gateway extProc: - - backendRef: - name: grpc-backend-4 + - backendRefs: + - name: grpc-backend-4 port: 4000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml index 1deb8ca6b25..a545e58625b 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-invalid-cross-ns-ref.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-4 + - backendRefs: + - name: grpc-backend-4 port: 4000 targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml index ce4ecde3766..1d4c61cc7f7 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml @@ -86,8 +86,8 @@ envoyExtensionPolicies: name: gateway-1 namespace: envoy-gateway extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 9000 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy @@ -101,6 +101,6 @@ envoyExtensionPolicies: name: httproute-1 namespace: default extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 8000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml index 0fd8d36b3ca..cc9921a6bd7 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 8000 targetRef: group: gateway.networking.k8s.io @@ -38,8 +38,8 @@ envoyExtensionPolicies: namespace: envoy-gateway spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 9000 targetRef: group: gateway.networking.k8s.io @@ -231,7 +231,7 @@ xdsIR: extProc: - authority: grpc-backend-2.default:8000 destination: - name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + name: envoyextensionpolicy/default/policy-for-route-1/0 settings: - protocol: GRPC weight: 1 @@ -258,7 +258,7 @@ xdsIR: extProc: - authority: grpc-backend.envoy-gateway:9000 destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 settings: - protocol: GRPC weight: 1 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml index 78989127328..982d7da84e6 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.in.yaml @@ -55,6 +55,6 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 4000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml index 55e0b661896..740230fbf21 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-matching-port.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend port: 4000 targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml index b2420abfa9d..abb0bf36596 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.in.yaml @@ -55,5 +55,5 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml index 05db4b4438c..50c1a7371d4 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-port.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml index 6d3ec1fdd7e..71f453ec95b 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.in.yaml @@ -55,7 +55,7 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml index c4ad278a6c4..f62b31daa94 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-reference-grant.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 targetRef: diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml index eff5a17efd2..b58eeee0978 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.in.yaml @@ -46,7 +46,7 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml index 7155bfe7243..3ea2c40f4d9 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-invalid-no-service.out.yaml @@ -7,8 +7,8 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 9000 targetRef: diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml index 21c6fab4506..fb3d3cab153 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.in.yaml @@ -201,10 +201,17 @@ envoyExtensionPolicies: name: gateway-1 namespace: default extProc: - - backendRef: - Name: grpc-backend + - backendRefs: + - Name: grpc-backend Namespace: envoy-gateway Port: 8000 + processingMode: + request: + body: Buffered + response: + body: Streamed + messageTimeout: 5s + failOpen: true - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyExtensionPolicy metadata: @@ -217,6 +224,9 @@ envoyExtensionPolicies: name: httproute-1 namespace: default extProc: - - backendRef: - Name: grpc-backend-2 + - backendRefs: + - Name: grpc-backend-2 Port: 9000 + processingMode: + request: {} + response: {} diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml index c8eb952e580..e33b83f0ec4 100755 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml @@ -73,9 +73,12 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend-2 + - backendRefs: + - name: grpc-backend-2 port: 9000 + processingMode: + request: {} + response: {} targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -104,10 +107,17 @@ envoyExtensionPolicies: namespace: default spec: extProc: - - backendRef: - name: grpc-backend + - backendRefs: + - name: grpc-backend namespace: envoy-gateway port: 8000 + failOpen: true + messageTimeout: 5s + processingMode: + request: + body: Buffered + response: + body: Streamed targetRef: group: gateway.networking.k8s.io kind: Gateway @@ -298,7 +308,7 @@ xdsIR: extProc: - authority: grpc-backend-2.default:9000 destination: - name: envoyextensionpolicy/default/policy-for-http-route/0/grpc-backend-2 + name: envoyextensionpolicy/default/policy-for-http-route/0 settings: - addressType: IP endpoints: @@ -312,6 +322,8 @@ xdsIR: sni: grpc-backend-2 weight: 1 name: envoyextensionpolicy/default/policy-for-http-route/0 + requestHeaderProcessing: true + responseHeaderProcessing: true hostname: www.foo.com isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com @@ -334,7 +346,7 @@ xdsIR: extProc: - authority: grpc-backend.envoy-gateway:8000 destination: - name: envoyextensionpolicy/default/policy-for-gateway/0/grpc-backend + name: envoyextensionpolicy/default/policy-for-gateway/0 settings: - addressType: IP protocol: GRPC @@ -344,7 +356,13 @@ xdsIR: name: policy-btls-grpc/default-ca sni: grpc-backend weight: 1 + failOpen: true + messageTimeout: 5s name: envoyextensionpolicy/default/policy-for-gateway/0 + requestBodyProcessingMode: Buffered + requestHeaderProcessing: true + responseBodyProcessingMode: Streamed + responseHeaderProcessing: true hostname: www.bar.com isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/www_bar_com diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml new file mode 100644 index 00000000000..a278b45a903 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.in.yaml @@ -0,0 +1,192 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - www.bar.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /bar + backendRefs: + - name: service-1 + port: 8080 +services: +- apiVersion: v1 + kind: Service + metadata: + namespace: envoy-gateway + name: grpc-backend + spec: + ports: + - port: 8000 + name: grpc + protocol: TCP +- apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend-2 + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend + namespace: envoy-gateway + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8000 + endpoints: + - addresses: + - 7.7.7.7 + conditions: + ready: true +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend-2 + namespace: default + labels: + kubernetes.io/service-name: grpc-backend-2 + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + port: 9000 + endpoints: + - addresses: + - 8.8.8.8 + conditions: + ready: true +referenceGrants: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + namespace: envoy-gateway + name: referencegrant-1 + spec: + from: + - group: gateway.envoyproxy.io + kind: SecurityPolicy + namespace: default + - group: gateway.networking.k8s.io + kind: BackendTLSPolicy + namespace: default + to: + - group: '' + kind: Service +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: default + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-grpc + namespace: default + spec: + targetRef: + group: '' + kind: Service + name: grpc-backend + namespace: envoy-gateway + sectionName: "8000" + tls: + caCertRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: grpc-backend +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + namespace: default + name: policy-for-http-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + extProc: + - backendRefs: + - Name: grpc-backend + Namespace: envoy-gateway + Port: 8000 + - Name: grpc-backend-2 + Port: 9000 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml new file mode 100755 index 00000000000..a26a321d6e6 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml @@ -0,0 +1,277 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-grpc + namespace: default + spec: + targetRef: + group: "" + kind: Service + name: grpc-backend + namespace: envoy-gateway + sectionName: "8000" + tls: + caCertRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: grpc-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route + namespace: default + spec: + extProc: + - backendRefs: + - name: grpc-backend + namespace: envoy-gateway + port: 8000 + - name: grpc-backend-2 + port: 9000 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - www.bar.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /bar + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + extProc: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/default-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/0 + hostname: www.foo.com + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/ir/xds.go b/internal/ir/xds.go index e28df915e21..337720f7fb0 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -1909,6 +1909,17 @@ type ConnectionLimit struct { CloseDelay *metav1.Duration `json:"closeDelay,omitempty" yaml:"closeDelay,omitempty"` } +type ExtProcBodyProcessingMode egv1a1.ExtProcBodyProcessingMode + +const ( + // ExtProcBodyStreamed sets the streamed body processing mode + ExtProcBodyStreamed = ExtProcBodyProcessingMode(egv1a1.StreamedExtProcBodyProcessingMode) + // ExtProcBodyBuffered sets the buffered body processing mode + ExtProcBodyBuffered = ExtProcBodyProcessingMode(egv1a1.BufferedExtProcBodyProcessingMode) + // ExtProcBodyBufferedPartial sets the partial buffered body processing mode + ExtProcBodyBufferedPartial = ExtProcBodyProcessingMode(egv1a1.BufferedPartialExtBodyHeaderProcessingMode) +) + // ExtProc holds the information associated with the ExtProc extensions. // +k8s:deepcopy-gen=true type ExtProc struct { @@ -1917,10 +1928,29 @@ type ExtProc struct { Name string `json:"name" yaml:"name"` // Destination defines the destination for the gRPC External Processing service. - Destination RouteDestination `json:"destination"` + Destination RouteDestination `json:"destination" yaml:"destination"` // Authority is the hostname:port of the HTTP External Processing service. - Authority string `json:"authority"` + Authority string `json:"authority" yaml:"authority"` + + // MessageTimeout is the timeout for a response to be returned from the external processor + MessageTimeout *metav1.Duration `json:"messageTimeout,omitempty" yaml:"messageTimeout,omitempty"` + + // FailOpen defines if requests or responses that cannot be processed due to connectivity to the + // external processor are terminated or passed-through. + FailOpen *bool `json:"failOpen,omitempty" yaml:"failOpen,omitempty"` + + // RequestHeaderProcessing Defines if request headers are processed + RequestHeaderProcessing bool `json:"requestHeaderProcessing,omitempty" yaml:"requestHeaderProcessing,omitempty"` + + // RequestBodyProcessingMode Defines request body processing + RequestBodyProcessingMode *ExtProcBodyProcessingMode `json:"requestBodyProcessingMode,omitempty" yaml:"requestBodyProcessingMode,omitempty"` + + // ResponseHeaderProcessingMode Defines if response headers are processed + ResponseHeaderProcessing bool `json:"responseHeaderProcessing,omitempty" yaml:"responseHeaderProcessing,omitempty"` + + // ResponseBodyProcessingMode Defines response body processing + ResponseBodyProcessingMode *ExtProcBodyProcessingMode `json:"responseBodyProcessingMode,omitempty" yaml:"responseBodyProcessingMode,omitempty"` } // Wasm holds the information associated with the Wasm extensions. diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 21f6cdf87d7..5430ef9ce6b 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -532,6 +532,26 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in in.Destination.DeepCopyInto(&out.Destination) + if in.MessageTimeout != nil { + in, out := &in.MessageTimeout, &out.MessageTimeout + *out = new(v1.Duration) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } + if in.RequestBodyProcessingMode != nil { + in, out := &in.RequestBodyProcessingMode, &out.RequestBodyProcessingMode + *out = new(ExtProcBodyProcessingMode) + **out = **in + } + if in.ResponseBodyProcessingMode != nil { + in, out := &in.ResponseBodyProcessingMode, &out.ResponseBodyProcessingMode + *out = new(ExtProcBodyProcessingMode) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProc. diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index cf707f07922..93ce3fe9145 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -1476,38 +1476,40 @@ func (r *gatewayAPIReconciler) processEnvoyExtensionPolicyObjectRefs( for _, policy := range resourceTree.EnvoyExtensionPolicies { // Add the referenced BackendRefs and ReferenceGrants in ExtAuth to Maps for later processing for _, ep := range policy.Spec.ExtProc { - backendRef := ep.BackendRef.BackendObjectReference - - backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, policy.Namespace) - resourceMap.allAssociatedBackendRefs[gwapiv1.BackendObjectReference{ - Group: backendRef.Group, - Kind: backendRef.Kind, - Namespace: gatewayapi.NamespacePtrV1Alpha2(backendNamespace), - Name: backendRef.Name, - }] = struct{}{} - - if backendNamespace != policy.Namespace { - from := ObjectKindNamespacedName{ - kind: gatewayapi.KindHTTPRoute, - namespace: policy.Namespace, - name: policy.Name, - } - to := ObjectKindNamespacedName{ - kind: gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService), - namespace: backendNamespace, - name: string(backendRef.Name), - } - refGrant, err := r.findReferenceGrant(ctx, from, to) - switch { - case err != nil: - r.log.Error(err, "failed to find ReferenceGrant") - case refGrant == nil: - r.log.Info("no matching ReferenceGrants found", "from", from.kind, - "from namespace", from.namespace, "target", to.kind, "target namespace", to.namespace) - default: - resourceTree.ReferenceGrants = append(resourceTree.ReferenceGrants, refGrant) - r.log.Info("added ReferenceGrant to resource map", "namespace", refGrant.Namespace, - "name", refGrant.Name) + for _, br := range ep.BackendRefs { + backendRef := br.BackendObjectReference + + backendNamespace := gatewayapi.NamespaceDerefOr(backendRef.Namespace, policy.Namespace) + resourceMap.allAssociatedBackendRefs[gwapiv1.BackendObjectReference{ + Group: backendRef.Group, + Kind: backendRef.Kind, + Namespace: gatewayapi.NamespacePtrV1Alpha2(backendNamespace), + Name: backendRef.Name, + }] = struct{}{} + + if backendNamespace != policy.Namespace { + from := ObjectKindNamespacedName{ + kind: gatewayapi.KindHTTPRoute, + namespace: policy.Namespace, + name: policy.Name, + } + to := ObjectKindNamespacedName{ + kind: gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService), + namespace: backendNamespace, + name: string(backendRef.Name), + } + refGrant, err := r.findReferenceGrant(ctx, from, to) + switch { + case err != nil: + r.log.Error(err, "failed to find ReferenceGrant") + case refGrant == nil: + r.log.Info("no matching ReferenceGrants found", "from", from.kind, + "from namespace", from.namespace, "target", to.kind, "target namespace", to.namespace) + default: + resourceTree.ReferenceGrants = append(resourceTree.ReferenceGrants, refGrant) + r.log.Info("added ReferenceGrant to resource map", "namespace", refGrant.Namespace, + "name", refGrant.Name) + } } } } diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index ac1132b31d5..44526e1e9f7 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -38,7 +38,7 @@ const ( configMapCtpIndex = "configMapCtpIndex" secretCtpIndex = "secretCtpIndex" configMapBtlsIndex = "configMapBtlsIndex" - backendEnvoyExtensionPolicyIndex = "backendSecurityPolicyIndex" + backendEnvoyExtensionPolicyIndex = "backendEnvoyExtensionPolicyIndex" ) func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { @@ -535,12 +535,16 @@ func backendEnvoyExtensionPolicyIndexFunc(rawObj client.Object) []string { var ret []string for _, ep := range envoyExtensionPolicy.Spec.ExtProc { - backendRef := ep.BackendRef.BackendObjectReference - ret = append(ret, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(backendRef.Namespace, envoyExtensionPolicy.Namespace), - Name: string(backendRef.Name), - }.String()) + + for _, br := range ep.BackendRefs { + backendRef := br.BackendObjectReference + ret = append(ret, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(backendRef.Namespace, envoyExtensionPolicy.Namespace), + Name: string(backendRef.Name), + }.String()) + } + } return ret diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index e9f24d6e51f..b23ebb41d86 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -530,9 +530,11 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []v1alpha1.ExtProc{ { - BackendRef: v1alpha1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendRefs: []v1alpha1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, @@ -559,9 +561,11 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []v1alpha1.ExtProc{ { - BackendRef: v1alpha1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendRefs: []v1alpha1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index 7ed060824ce..c31185211d4 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -12,11 +12,13 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" extprocv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/golang/protobuf/ptypes/duration" - "google.golang.org/protobuf/types/known/anypb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" + + "github.com/golang/protobuf/ptypes/duration" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" ) const ( @@ -106,6 +108,38 @@ func extProcConfig(extProc ir.ExtProc) *extprocv3.ExternalProcessor { Seconds: defaultExtServiceRequestTimeout, }, }, + ProcessingMode: &extprocv3.ProcessingMode{ + RequestHeaderMode: extprocv3.ProcessingMode_SKIP, + ResponseHeaderMode: extprocv3.ProcessingMode_SKIP, + RequestBodyMode: extprocv3.ProcessingMode_NONE, + ResponseBodyMode: extprocv3.ProcessingMode_NONE, + RequestTrailerMode: extprocv3.ProcessingMode_SKIP, + ResponseTrailerMode: extprocv3.ProcessingMode_SKIP, + }, + } + + if extProc.FailOpen != nil { + config.FailureModeAllow = *extProc.FailOpen + } + + if extProc.MessageTimeout != nil { + config.MessageTimeout = durationpb.New(extProc.MessageTimeout.Duration) + } + + if extProc.RequestBodyProcessingMode != nil { + config.ProcessingMode.RequestBodyMode = buildExtProcBodyProcessingMode(extProc.RequestBodyProcessingMode) + } + + if extProc.RequestHeaderProcessing { + config.ProcessingMode.RequestHeaderMode = extprocv3.ProcessingMode_SEND + } + + if extProc.ResponseBodyProcessingMode != nil { + config.ProcessingMode.ResponseBodyMode = buildExtProcBodyProcessingMode(extProc.ResponseBodyProcessingMode) + } + + if extProc.ResponseHeaderProcessing { + config.ProcessingMode.ResponseHeaderMode = extprocv3.ProcessingMode_SEND } return config @@ -173,3 +207,15 @@ func (*extProc) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { } return nil } + +func buildExtProcBodyProcessingMode(mode *ir.ExtProcBodyProcessingMode) extprocv3.ProcessingMode_BodySendMode { + lookup := map[ir.ExtProcBodyProcessingMode]extprocv3.ProcessingMode_BodySendMode{ + ir.ExtProcBodyBuffered: extprocv3.ProcessingMode_BUFFERED, + ir.ExtProcBodyBufferedPartial: extprocv3.ProcessingMode_BUFFERED_PARTIAL, + ir.ExtProcBodyStreamed: extprocv3.ProcessingMode_STREAMED, + } + if r, found := lookup[*mode]; found { + return r + } + return extprocv3.ProcessingMode_NONE +} diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml index 170f1a3f2ea..90fd067480b 100644 --- a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml @@ -21,22 +21,30 @@ http: port: 8080 protocol: HTTP weight: 1 - envoyExtensionFeatures: - extProc: - - name: envoyextensionpolicy/default/policy-for-route-2/0 - authority: grpc-backend-4.default:4000 - destination: - name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 - settings: - - protocol: GRPC - weight: 1 - - name: envoyextensionpolicy/default/policy-for-route-1/0 - authority: grpc-backend-2.default:8000 - destination: - name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 - settings: - - protocol: GRPC - weight: 1 + extProc: + - name: envoyextensionpolicy/default/policy-for-route-2/0 + failOpen: true + messageTimeout: 5s + requestHeaderProcessing: true + requestBodyProcessingMode: Buffered + responseBodyProcessingMode: Streamed + authority: grpc-backend-4.default:4000 + destination: + name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + settings: + - protocol: GRPC + weight: 1 + - name: envoyextensionpolicy/default/policy-for-route-1/0 + failOpen: true + messageTimeout: 5s + responseHeaderProcessing: true + requestBodyProcessingMode: BufferedPartial + authority: grpc-backend-2.default:8000 + destination: + name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + settings: + - protocol: GRPC + weight: 1 hostname: gateway.envoyproxy.io isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io @@ -56,22 +64,23 @@ http: port: 8080 protocol: HTTP weight: 1 - envoyExtensionFeatures: - extProc: - - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 - authority: grpc-backend-3.envoy-gateway:3000 - destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 - settings: - - protocol: GRPC - weight: 1 - - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 - authority: grpc-backend.envoy-gateway:9000 - destination: - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend - settings: - - protocol: GRPC - weight: 1 + extProc: + - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 + authority: grpc-backend-3.envoy-gateway:3000 + destination: + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + settings: + - protocol: GRPC + weight: 1 + - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 + failOpen: false + messageTimeout: 15s + authority: grpc-backend.envoy-gateway:9000 + destination: + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + settings: + - protocol: GRPC + weight: 1 hostname: gateway.envoyproxy.io isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml index 6a277bb94f6..08b38495e69 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.clusters.yaml @@ -32,3 +32,91 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml index 05442a9a15b..4ec680ce7fd 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.endpoints.yaml @@ -22,3 +22,23 @@ loadBalancingWeight: 1 locality: region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2/backend/0 +- clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3/backend/0 +- clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml index a593a50af36..f822447967e 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.listeners.yaml @@ -14,6 +14,70 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-2/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + failureModeAllow: true + grpcService: + envoyGrpc: + authority: grpc-backend-4.default:4000 + clusterName: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4 + timeout: 10s + messageTimeout: 5s + processingMode: + requestBodyMode: BUFFERED + requestHeaderMode: SEND + requestTrailerMode: SKIP + responseBodyMode: STREAMED + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-1/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + failureModeAllow: true + grpcService: + envoyGrpc: + authority: grpc-backend-2.default:8000 + clusterName: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2 + timeout: 10s + messageTimeout: 5s + processingMode: + requestBodyMode: BUFFERED_PARTIAL + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SEND + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend-3.envoy-gateway:3000 + clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3 + timeout: 10s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - disabled: true + name: envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend.envoy-gateway:9000 + clusterName: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend + timeout: 10s + messageTimeout: 15s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP - name: envoy.filters.http.router typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml index a7002b63f87..0daf1919cb2 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc.routes.yaml @@ -12,6 +12,13 @@ cluster: httproute/default/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-1/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-route-2/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} - match: pathSeparatedPrefix: /bar name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io @@ -19,3 +26,10 @@ cluster: httproute/default/httproute-2/rule/0 upgradeConfigs: - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + envoy.filters.http.ext_proc/envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 19ab59f853c..eaef03e97b5 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -661,29 +661,6 @@ func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute return nil } -// processTLSSocket generates a xDS TransportSocket for a given TLS config. -// It also adds the necessary secrets to the resource version table. -func processTLSSocket(tlsConfig *ir.TLSUpstreamConfig, tCtx *types.ResourceVersionTable) (*corev3.TransportSocket, error) { - if tlsConfig == nil { - return nil, nil - } - // Create a secret for the CA certificate only if it's not using the system trust store - if !tlsConfig.UseSystemTrustStore { - CaSecret := buildXdsUpstreamTLSCASecret(tlsConfig) - if err := tCtx.AddXdsResource(resourcev3.SecretType, CaSecret); err != nil { - return nil, err - } - } - - // for upstreamTLS , a fixed sni can be used. use auto_sni otherwise - // https://www.envoyproxy.io/docs/envoy/latest/faq/configuration/sni#faq-how-to-setup-sni:~:text=For%20clusters%2C%20a,for%20trust%20anchor. - tlsSocket, err := buildXdsUpstreamTLSSocketWthCert(tlsConfig) - if err != nil { - return nil, err - } - return tlsSocket, nil -} - // findXdsSecret finds a xds secret with the same name, and returns nil if there is no match. func findXdsSecret(tCtx *types.ResourceVersionTable, name string) *tlsv3.Secret { if tCtx == nil || tCtx.XdsResources == nil || tCtx.XdsResources[resourcev3.SecretType] == nil { diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go index dbcb005ef32..b4f60b1ae30 100644 --- a/internal/xds/translator/utils.go +++ b/internal/xds/translator/utils.go @@ -144,13 +144,6 @@ func createExtServiceXDSCluster(rd *ir.RouteDestination, tCtx *types.ResourceVer endpointType = EndpointTypeStatic } - if rd.Settings[0].TLS != nil { - tSocket, err = processTLSSocket(rd.Settings[0].TLS, tCtx) - if err != nil { - return err - } - } - if err = addXdsCluster(tCtx, &xdsClusterArgs{ name: rd.Name, settings: rd.Settings, diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 72dbebba440..d485100eab3 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1210,33 +1210,12 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[ExtProcBackendRef](#extprocbackendref)_ | true | BackendRef defines the configuration of the external processing service | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs defines the configuration of the external processing service | +| `backendRefs` | _[BackendRef](#backendref) array_ | true | BackendRefs defines the configuration of the external processing service | | `messageTimeout` | _[Duration](#duration)_ | false | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms | | `failOpen` | _boolean_ | false | FailOpen defines if requests or responses that cannot be processed due to connectivity to the
external processor are terminated or passed-through.
Default: false | | `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor | -#### ExtProcBackendRef - - - -ExtProcService defines the gRPC External Processing service using the envoy grpc client -The processing request and response messages are defined in -https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/ext_proc/v3/external_processor.proto - -_Appears in:_ -- [ExtProc](#extproc) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `group` | _[Group](#group)_ | false | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | -| `kind` | _[Kind](#kind)_ | false | Kind is the Kubernetes resource kind of the referent. For example
"Service".

Defaults to "Service" when not specified.

ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.

Support: Core (Services with a type other than ExternalName)

Support: Implementation-specific (Services with type ExternalName) | -| `name` | _[ObjectName](#objectname)_ | true | Name is the name of the referent. | -| `namespace` | _[Namespace](#namespace)_ | false | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.

Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.

Support: Core | -| `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | - - #### ExtProcBodyProcessingMode _Underlying type:_ _string_ diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index 67200306a34..efad71d74f8 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -162,10 +162,12 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -187,11 +189,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: ptr.To(gwapiv1.Group("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -205,7 +209,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported"}, + wantErrors: []string{" spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Core group."}, }, { desc: "ExtProc with invalid BackendRef Kind", @@ -213,11 +217,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Kind: ptr.To(gwapiv1.Kind("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -231,7 +237,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported"}, + wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Service kind."}, }, { desc: "ExtProc with invalid fields", @@ -239,10 +245,12 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRef: egv1a1.ExtProcBackendRef{ - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, ProcessingMode: &egv1a1.ExtProcProcessingMode{ diff --git a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml index 5119ac22c1f..e88657fee1b 100644 --- a/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml +++ b/test/e2e/testdata/ext-proc-envoyextensionpolicy.yaml @@ -20,7 +20,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: http-without-ext-proc + name: http-without-procmode namespace: gateway-conformance-infra spec: parentRefs: @@ -46,8 +46,27 @@ spec: kind: HTTPRoute name: http-with-ext-proc extProc: - - backendRef: - name: grpc-ext-proc + - backendRefs: + - name: grpc-ext-proc + namespace: gateway-conformance-infra + port: 9002 + processingMode: + request: {} + response: {} +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyExtensionPolicy +metadata: + name: ext-proc-no-procmode-test + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-without-procmode + extProc: + - backendRefs: + - name: grpc-ext-proc namespace: gateway-conformance-infra port: 9002 --- diff --git a/test/e2e/testdata/ext-proc-service.yaml b/test/e2e/testdata/ext-proc-service.yaml index 594cf14edef..665779e96e4 100644 --- a/test/e2e/testdata/ext-proc-service.yaml +++ b/test/e2e/testdata/ext-proc-service.yaml @@ -8,74 +8,73 @@ data: go.mod: | module github.com/envoyproxy/gateway - go 1.21 + go 1.22 require ( - github.com/envoyproxy/go-control-plane v0.12.0 + github.com/envoyproxy/go-control-plane v0.12.1-0.20240322155512-db0b36a50fa8 google.golang.org/grpc v1.62.1 ) require ( - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect - github.com/golang/protobuf v1.5.3 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/protobuf v1.32.0 // indirect + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.33.0 // indirect ) go.sum: | 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/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.20240322155512-db0b36a50fa8 h1:Zghtu+wdlGvrmutCyhU9Ew5ozU18PVpxP+zGSgyUpFs= + github.com/envoyproxy/go-control-plane v0.12.1-0.20240322155512-db0b36a50fa8/go.mod h1:YtsM9q/kVkKyvmemY+BF/ZK7I93OWsx4uk4Do2Mr/OA= 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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= - github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= - github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= - github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= + 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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795 h1:pH+U6pJP0BhxqQ4njBUjOg0++WMMvv3eByWzB+oATBY= + github.com/planetscale/vtprotobuf v0.5.1-0.20231212170721-e7d721933795/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= - 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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= - google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= + google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= + google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= main.go: | package main import ( - "context" - "crypto/tls" - "crypto/x509" - "flag" - "fmt" - "google.golang.org/grpc/credentials" - "io" - "log" - "net" - "net/http" - "os" - "strings" - - envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" - envoy_service_proc_v3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "context" + "crypto/tls" + "crypto/x509" + "flag" + "fmt" + "io" + "log" + "net" + "net/http" + "os" + "strings" + + "google.golang.org/grpc/credentials" + + envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + envoy_service_proc_v3 "github.com/envoyproxy/go-control-plane/envoy/service/ext_proc/v3" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type extProcServer struct{} @@ -103,7 +102,6 @@ data: envoy_service_proc_v3.RegisterExternalProcessorServer(gs, &extProcServer{}) - go func() { err = gs.Serve(lis) if err != nil { @@ -227,13 +225,23 @@ data: resp := &envoy_service_proc_v3.ProcessingResponse{} switch v := req.Request.(type) { case *envoy_service_proc_v3.ProcessingRequest_RequestHeaders: + xrch := "" + if v.RequestHeaders != nil { + hdrs := v.RequestHeaders.Headers.GetHeaders() + for _, hdr := range hdrs { + if hdr.Key == "x-request-client-header" { + xrch = string(hdr.RawValue) + } + } + } + rhq := &envoy_service_proc_v3.HeadersResponse{ Response: &envoy_service_proc_v3.CommonResponse{ HeaderMutation: &envoy_service_proc_v3.HeaderMutation{ SetHeaders: []*envoy_api_v3_core.HeaderValueOption{ { Header: &envoy_api_v3_core.HeaderValue{ - Key: "x-request-ext-processed", + Key: "x-request-ext-processed", RawValue: []byte("true"), }, }, @@ -242,6 +250,23 @@ data: }, } + if xrch != "" { + rhq.Response.HeaderMutation.SetHeaders = append(rhq.Response.HeaderMutation.SetHeaders, + &envoy_api_v3_core.HeaderValueOption{ + Header: &envoy_api_v3_core.HeaderValue{ + Key: "x-request-client-header", + RawValue: []byte("mutated"), + }, + }) + rhq.Response.HeaderMutation.SetHeaders = append(rhq.Response.HeaderMutation.SetHeaders, + &envoy_api_v3_core.HeaderValueOption{ + Header: &envoy_api_v3_core.HeaderValue{ + Key: "x-request-client-header-received", + RawValue: []byte(xrch), + }, + }) + } + resp = &envoy_service_proc_v3.ProcessingResponse{ Response: &envoy_service_proc_v3.ProcessingResponse_RequestHeaders{ RequestHeaders: rhq, @@ -255,7 +280,7 @@ data: SetHeaders: []*envoy_api_v3_core.HeaderValueOption{ { Header: &envoy_api_v3_core.HeaderValue{ - Key: "x-response-ext-processed", + Key: "x-response-ext-processed", RawValue: []byte("true"), }, }, @@ -352,7 +377,7 @@ spec: - sh - "-c" - "cp -a /app /app-live && cd /app-live && go run . --certPath=/app-live/certs/ " - image: golang:1.21.3-alpine + image: golang:1.22.1-alpine ports: - containerPort: 8000 volumeMounts: diff --git a/test/e2e/tests/ext_proc.go b/test/e2e/tests/ext_proc.go index aa9978e92ea..eb069380b7b 100644 --- a/test/e2e/tests/ext_proc.go +++ b/test/e2e/tests/ext_proc.go @@ -26,10 +26,10 @@ func init() { ConformanceTests = append(ConformanceTests, ExtProcTest) } -// ExtProcTest tests ExtProcs authentication for an http route with ExtProcs configured. +// ExtProcTest tests ExtProc authentication for an http route with ExtProc configured. var ExtProcTest = suite.ConformanceTest{ - ShortName: "ExtProcs", - Description: "Test ExtProcs service that adds request and response headers", + ShortName: "ExtProc", + Description: "Test ExtProc service that adds request and response headers", Manifests: []string{"testdata/ext-proc-service.yaml", "testdata/ext-proc-envoyextensionpolicy.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { t.Run("http route with ext proc", func(t *testing.T) { @@ -56,19 +56,25 @@ var ExtProcTest = suite.ConformanceTest{ Host: "www.example.com", Path: "/processor", Headers: map[string]string{ - "x-request-ext-processed": "true", // header added by ext-processor to request + "x-request-ext-processed": "true", // header added by ext-processor to backend-bound request + "x-request-client-header-received": "original", // this is the original client header preserved by ext-proc in a new header + "x-request-client-header": "mutated", // this is the mutated value expected to reach upstream }, }, Response: http.Response{ StatusCode: 200, Headers: map[string]string{ - "x-response-ext-processed": "true", // header added by ext-processor to request + "x-response-ext-processed": "true", // header added by ext-processor to client-bound response }, }, Namespace: ns, } req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + + // add a request header that will be mutated by ext-proc + req.Headers["x-request-client-header"] = []string{"original"} + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) if err != nil { t.Errorf("failed to get expected response: %v", err) @@ -79,9 +85,9 @@ var ExtProcTest = suite.ConformanceTest{ } }) - t.Run("http route without ext proc", func(t *testing.T) { + t.Run("http route without proc mode", func(t *testing.T) { ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "http-with-ext-proc", Namespace: ns} + routeNN := types.NamespacedName{Name: "http-without-procmode", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) @@ -91,7 +97,7 @@ var ExtProcTest = suite.ConformanceTest{ Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), Name: gwv1.ObjectName(gwNN.Name), } - EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-proc-test", Namespace: ns}, suite.ControllerName, ancestorRef) + EnvoyExtensionPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-proc-no-procmode-test", Namespace: ns}, suite.ControllerName, ancestorRef) podReady := corev1.PodCondition{Type: corev1.PodReady, Status: corev1.ConditionTrue} @@ -102,6 +108,9 @@ var ExtProcTest = suite.ConformanceTest{ Request: http.Request{ Host: "www.example.com", Path: "/no-processor", + Headers: map[string]string{ + "x-request-client-header": "original", + }, }, Response: http.Response{ StatusCode: 200, @@ -111,6 +120,10 @@ var ExtProcTest = suite.ConformanceTest{ } req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + + // add a request header that will be mutated by ext-proc if the request headers are sent + req.Headers["x-request-client-header"] = []string{"original"} + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) if err != nil { t.Errorf("failed to get expected response: %v", err) From 75f46278af46aa7fdac7a54d6ccc4ab9a9cf11d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 07:19:17 -0500 Subject: [PATCH 13/29] build(deps): bump actions/upload-artifact from 4.3.2 to 4.3.3 (#3300) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.2 to 4.3.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/1746f4ab65b179e0ea60a494b83293b640dd5bba...65462800fd760344b1a7b4382951275a0abb4808) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yaml | 2 +- .github/workflows/experimental_conformance.yaml | 2 +- .github/workflows/scorecard.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index f6030a45325..6fcf91ca44f 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -70,7 +70,7 @@ jobs: run: make build-multiarch PLATFORMS="linux_amd64 linux_arm64" - name: Upload EG Binaries - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: envoy-gateway path: bin/ diff --git a/.github/workflows/experimental_conformance.yaml b/.github/workflows/experimental_conformance.yaml index 508f7b5898e..bebb228237a 100644 --- a/.github/workflows/experimental_conformance.yaml +++ b/.github/workflows/experimental_conformance.yaml @@ -32,7 +32,7 @@ jobs: run: make experimental-conformance - name: Upload Conformance Report - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: conformance-report-k8s-${{ matrix.version }} path: ./test/conformance/conformance-report-k8s-${{ matrix.version }}.yaml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index dad78e90189..dbd2e1b5414 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -33,7 +33,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@1746f4ab65b179e0ea60a494b83293b640dd5bba # v4.3.2 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: SARIF file path: results.sarif From 88858232ee998d9bf44c7049807db96c6b910a7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 07:19:36 -0500 Subject: [PATCH 14/29] build(deps): bump actions/download-artifact from 4.1.5 to 4.1.7 (#3299) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.5 to 4.1.7. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/8caf195ad4b1dee92908e23f56eeb0696f1dd42d...65a9edc5881444af0b9093a5e628f2fe47ea3b2e) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 6fcf91ca44f..94d081ed4da 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -86,7 +86,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ @@ -114,7 +114,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ @@ -139,7 +139,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@8caf195ad4b1dee92908e23f56eeb0696f1dd42d # v4.1.5 + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 with: name: envoy-gateway path: bin/ From 46a4ce0682cc65bbefd1d162c9a54ee6bcf83048 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 07:19:58 -0500 Subject: [PATCH 15/29] build(deps): bump github/codeql-action from 3.25.1 to 3.25.3 (#3297) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.1 to 3.25.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c7f9125735019aa87cfc361530512d50ea439c71...d39d31e687223d841ef683f52467bd88e9b21c14) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zirain --- .github/workflows/codeql.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 340072d7949..78b0ad99e60 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,14 +36,14 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Initialize CodeQL - uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index dbd2e1b5414..20473358d7c 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -40,6 +40,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif From f569571ba621c3416d7518e643eaa1c7c8f83332 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 07:20:24 -0500 Subject: [PATCH 16/29] build(deps): bump the go-opentelemetry-io group with 8 updates (#3295) Bumps the go-opentelemetry-io group with 8 updates: | Package | From | To | | --- | --- | --- | | [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/exporters/prometheus](https://github.com/open-telemetry/opentelemetry-go) | `0.47.0` | `0.48.0` | | [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/sdk/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | | [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` | Updates `go.opentelemetry.io/otel` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/exporters/prometheus` from 0.47.0 to 0.48.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/example/prometheus/v0.47.0...example/prometheus/v0.48.0) Updates `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/metric` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/sdk/metric` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) Updates `go.opentelemetry.io/otel/sdk` from 1.25.0 to 1.26.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.25.0...v1.26.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/exporters/prometheus dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdoutmetric dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/metric dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/sdk/metric dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io - dependency-name: go.opentelemetry.io/otel/sdk dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-opentelemetry-io ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 36 ++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 697c2a1452b..036642b6491 100644 --- a/go.mod +++ b/go.mod @@ -27,13 +27,13 @@ require ( github.com/stretchr/testify v1.9.0 github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 github.com/tsaarni/certyaml v0.9.3 - go.opentelemetry.io/otel v1.25.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0 - go.opentelemetry.io/otel/exporters/prometheus v0.47.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0 - go.opentelemetry.io/otel/metric v1.25.0 - go.opentelemetry.io/otel/sdk/metric v1.25.0 + go.opentelemetry.io/otel v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 + go.opentelemetry.io/otel/exporters/prometheus v0.48.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 + go.opentelemetry.io/otel/metric v1.26.0 + go.opentelemetry.io/otel/sdk/metric v1.26.0 go.opentelemetry.io/proto/otlp v1.2.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 @@ -166,8 +166,8 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/tsaarni/x500dn v1.0.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.opentelemetry.io/otel/sdk v1.25.0 - go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.opentelemetry.io/otel/sdk v1.26.0 + go.opentelemetry.io/otel/trace v1.26.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.16.0 // indirect diff --git a/go.sum b/go.sum index ee2b0823437..e0a9392cf1f 100644 --- a/go.sum +++ b/go.sum @@ -685,24 +685,24 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0 h1:Wc4hZuYXhVqq+TfRXLXlmNIL/awOanGx8ssq3ciDQxc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.25.0/go.mod h1:BydOvapRqVEc0DVz27qWBX2jq45Ca5TI9mhZBDIdweY= -go.opentelemetry.io/otel/exporters/prometheus v0.47.0 h1:OL6yk1Z/pEGdDnrBbxSsH+t4FY1zXfBRGd7bjwhlMLU= -go.opentelemetry.io/otel/exporters/prometheus v0.47.0/go.mod h1:xF3N4OSICZDVbbYZydz9MHFro1RjmkPUKEvar2utG+Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0 h1:d7nHbdzU84STOiszaOxQ3kw5IwkSmHsU5Muol5/vL4I= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.25.0/go.mod h1:yiPA1iZbb/EHYnODXOxvtKuB0I2hV8ehfLTEWpl7BJU= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= -go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= +go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0 h1:+hm+I+KigBy3M24/h1p/NHkUx/evbLH0PNcjpMyCHc4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.26.0/go.mod h1:NjC8142mLvvNT6biDpaMjyz78kyEHIwAJlSX0N9P5KI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0 h1:HGZWGmCVRCVyAs2GQaiHQPbDHo+ObFWeUEOd+zDnp64= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.26.0/go.mod h1:SaH+v38LSCHddyk7RGlU9uZyQoRrKao6IBnJw6Kbn+c= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s= +go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0 h1:5fnmgteaar1VcAA69huatudPduNFz7guRtCmfZCooZI= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.26.0/go.mod h1:lsPccfZiz1cb1AhBPmicWM2E4F1VynFXEvD8SEBS4TM= +go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= +go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= +go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8= +go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs= +go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y= +go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE= +go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= +go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= From 2b2dbb72227b69d9ecdb2236c3579f4c5502a4fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 08:02:36 -0500 Subject: [PATCH 17/29] build(deps): bump myst-parser from 2.0.0 to 3.0.1 in /tools/src/sphinx-build (#3294) build(deps): bump myst-parser in /tools/src/sphinx-build Bumps [myst-parser](https://github.com/executablebooks/MyST-Parser) from 2.0.0 to 3.0.1. - [Release notes](https://github.com/executablebooks/MyST-Parser/releases) - [Changelog](https://github.com/executablebooks/MyST-Parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/executablebooks/MyST-Parser/compare/v2.0.0...v3.0.1) --- updated-dependencies: - dependency-name: myst-parser dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zirain --- tools/src/sphinx-build/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/src/sphinx-build/requirements.txt b/tools/src/sphinx-build/requirements.txt index 9434d0ace8d..16fc53701bf 100644 --- a/tools/src/sphinx-build/requirements.txt +++ b/tools/src/sphinx-build/requirements.txt @@ -1,2 +1,2 @@ Sphinx==7.3.7 -myst-parser==2.0.0 +myst-parser==3.0.1 From d6a36af4810672edf72d6d4ed93d24fb3a84fddd Mon Sep 17 00:00:00 2001 From: Shyunn <1147212064@qq.com> Date: Tue, 30 Apr 2024 21:35:51 +0800 Subject: [PATCH 18/29] e2e: fix connectionLimit e2e test (#3292) * e2e: fix connectionLimit e2e test Signed-off-by: ShyunnY <1147212064@qq.com> * fix: use stats Signed-off-by: ShyunnY <1147212064@qq.com> * fix Signed-off-by: ShyunnY <1147212064@qq.com> --------- Signed-off-by: ShyunnY <1147212064@qq.com> Co-authored-by: Guy Daich --- test/e2e/testdata/connection-limit.yaml | 2 +- test/e2e/tests/connection_limit.go | 75 ++++++++++++++----------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/test/e2e/testdata/connection-limit.yaml b/test/e2e/testdata/connection-limit.yaml index 998a26191fd..3edb268aad8 100644 --- a/test/e2e/testdata/connection-limit.yaml +++ b/test/e2e/testdata/connection-limit.yaml @@ -11,7 +11,7 @@ spec: namespace: gateway-conformance-infra connection: connectionLimit: - value: 5 + value: 3 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute diff --git a/test/e2e/tests/connection_limit.go b/test/e2e/tests/connection_limit.go index 62f8f0011da..952a6086da6 100644 --- a/test/e2e/tests/connection_limit.go +++ b/test/e2e/tests/connection_limit.go @@ -9,21 +9,21 @@ package tests import ( - "errors" + "fmt" "net" - "net/url" "testing" "time" - "github.com/envoyproxy/gateway/internal/gatewayapi" - + "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/types" - gwv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "sigs.k8s.io/gateway-api/conformance/utils/http" "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/test/e2e/utils/prometheus" ) func init() { @@ -49,39 +49,50 @@ var ConnectionLimitTest = suite.ConformanceTest{ } ClientTrafficPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "connection-limit-ctp", Namespace: ns}, suite.ControllerName, ancestorRef) - // open some connections - for i := 0; i < 10; i++ { - conn, err := net.DialTimeout("tcp", gwAddr, 100*time.Millisecond) - if err == nil { - defer conn.Close() - } else { + promAddr, err := prometheus.Address(suite.Client, + types.NamespacedName{Name: "prometheus", Namespace: "monitoring"}, + ) + require.NoError(t, err) + + // we make the number of connections equal to the number of connectionLimit connections + 3 + // avoid partial connection errors or interruptions + for i := 0; i < 6; i++ { + conn, err := net.Dial("tcp", gwAddr) + if err != nil { t.Errorf("failed to open connection: %v", err) + } else { + defer conn.Close() } } - // make a request, expect a failure - expectedResponse := http.ExpectedResponse{ - Request: http.Request{ - Path: "/", - }, - Response: http.Response{ - StatusCode: 200, - }, - Namespace: ns, - } + prefix := "http" + gtwName := "connection-limit-gateway" + promQL := fmt.Sprintf(`envoy_connection_limit_limited_connections{envoy_connection_limit_prefix="%s",gateway_envoyproxy_io_owning_gateway_name="%s"}`, prefix, gtwName) - req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") - _, _, err := suite.RoundTripper.CaptureRoundTrip(req) + http.AwaitConvergence( + t, + suite.TimeoutConfig.RequiredConsecutiveSuccesses, + suite.TimeoutConfig.MaxTimeToConsistency, + func(_ time.Duration) bool { + // check connection_limit stats from Prometheus + v, err := prometheus.QuerySum(promAddr, promQL) + if err != nil { + // wait until Prometheus sync stats + return false + } + t.Logf("connection_limit stats query count: %v", v) - // expect error - if err != nil { - urlError := &url.Error{} - if !errors.As(err, &urlError) { - t.Errorf("expected net/url error when connection limit is reached") - } - } else { - t.Errorf("expected error when connection limit is reached") - } + // connection interruptions or other connection errors may occur + // we just need to determine whether there is a connection limit stats + if v == 0 { + t.Error("connection is not limited as expected") + } else { + t.Log("connection is limited as expected") + } + + return true + }, + ) }) }, } From d32256c3febf2469dc6b5f70ac30bb7ee61bc579 Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 30 Apr 2024 22:07:10 +0800 Subject: [PATCH 19/29] chore: fix lint (#3309) Signed-off-by: zirain --- internal/gatewayapi/envoyextensionpolicy.go | 1 - internal/provider/kubernetes/indexers.go | 2 -- 2 files changed, 3 deletions(-) diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index edb0dc385a9..2e1fe34ffde 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -424,7 +424,6 @@ func (t *Translator) buildExtProc( egv1a1.KindEnvoyExtensionPolicy, ir.GRPC, resources) - if err != nil { return nil, err } diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index 44526e1e9f7..511802e2e38 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -535,7 +535,6 @@ func backendEnvoyExtensionPolicyIndexFunc(rawObj client.Object) []string { var ret []string for _, ep := range envoyExtensionPolicy.Spec.ExtProc { - for _, br := range ep.BackendRefs { backendRef := br.BackendObjectReference ret = append(ret, @@ -544,7 +543,6 @@ func backendEnvoyExtensionPolicyIndexFunc(rawObj client.Object) []string { Name: string(backendRef.Name), }.String()) } - } return ret From ec0a84bafe4fcfe5c77d29fe92cf3633a990322b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:41:53 -0500 Subject: [PATCH 20/29] build(deps): bump distroless/static from `f41b84c` to `e9ac71e` in /tools/docker/envoy-gateway (#3301) build(deps): bump distroless/static in /tools/docker/envoy-gateway Bumps distroless/static from `f41b84c` to `e9ac71e`. --- updated-dependencies: - dependency-name: distroless/static dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zirain --- tools/docker/envoy-gateway/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/docker/envoy-gateway/Dockerfile b/tools/docker/envoy-gateway/Dockerfile index 9109a33e7ea..074320308eb 100644 --- a/tools/docker/envoy-gateway/Dockerfile +++ b/tools/docker/envoy-gateway/Dockerfile @@ -1,6 +1,6 @@ # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot@sha256:f41b84cda410b05cc690c2e33d1973a31c6165a2721e2b5343aab50fecb63441 +FROM gcr.io/distroless/static:nonroot@sha256:e9ac71e2b8e279a8372741b7a0293afda17650d926900233ec3a7b2b7c22a246 ARG TARGETPLATFORM COPY $TARGETPLATFORM/envoy-gateway /usr/local/bin/ From 3418b691030b5deeb76175d1dd36605cd525cf39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:42:15 -0500 Subject: [PATCH 21/29] build(deps): bump actions/checkout from 4.1.3 to 4.1.4 (#3298) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/1d96c772d19495a3b5c517cd2bc0cb401ea0529f...0ad4b8fadaa221de15dcec353f45205ec38ea70b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zirain Co-authored-by: Guy Daich --- .github/workflows/build_and_test.yaml | 16 ++++++++-------- .github/workflows/cherrypick.yaml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/docs.yaml | 4 ++-- .github/workflows/experimental_conformance.yaml | 2 +- .github/workflows/latest_release.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/trivy.yml | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 94d081ed4da..e34f76cf676 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -20,7 +20,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps # Generate the install manifests first so it can checked # for errors while running `make -k lint` @@ -31,21 +31,21 @@ jobs: gen-check: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - run: make -k gen-check license-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - run: make -k licensecheck coverage-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps # test @@ -63,7 +63,7 @@ jobs: runs-on: ubuntu-latest needs: [lint, gen-check, license-check, coverage-test] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Build EG Multiarch Binaries @@ -82,7 +82,7 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries @@ -110,7 +110,7 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries @@ -135,7 +135,7 @@ jobs: runs-on: ubuntu-latest needs: [conformance-test, e2e-test] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries diff --git a/.github/workflows/cherrypick.yaml b/.github/workflows/cherrypick.yaml index d2e84d765ae..bda95da1b33 100644 --- a/.github/workflows/cherrypick.yaml +++ b/.github/workflows/cherrypick.yaml @@ -18,7 +18,7 @@ jobs: if: ${{ contains(github.event.pull_request.labels.*.name, 'cherrypick/release-v1.0') && github.event.pull_request.merged == true }} steps: - name: Checkout - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Cherry pick into release/v1.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 78b0ad99e60..bc69c913007 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Initialize CodeQL diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index fa5fbb46597..28ec10e0b6b 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check out code - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: ref: ${{ github.event.pull_request.head.sha }} @@ -48,7 +48,7 @@ jobs: contents: write steps: - name: Git checkout - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: submodules: true ref: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/experimental_conformance.yaml b/.github/workflows/experimental_conformance.yaml index bebb228237a..c7f00139f2c 100644 --- a/.github/workflows/experimental_conformance.yaml +++ b/.github/workflows/experimental_conformance.yaml @@ -20,7 +20,7 @@ jobs: matrix: version: [ v1.26.14, v1.27.11, v1.28.7, v1.29.2 ] steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps # gateway api experimental conformance diff --git a/.github/workflows/latest_release.yaml b/.github/workflows/latest_release.yaml index aba8b07712f..de577267da3 100644 --- a/.github/workflows/latest_release.yaml +++ b/.github/workflows/latest_release.yaml @@ -22,7 +22,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - name: Generate Release Manifests diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4f22eedb8ee..a104b0f1daf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Extract Release Tag and Commit SHA id: vars diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 20473358d7c..77c1a3dcb03 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -21,7 +21,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: persist-credentials: false diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index d8e8c9eeebe..87a7483f6d5 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout code - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f # v4.1.3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Build an image from Dockerfile run: | From e14b29d605e82446e65b6fabbb6c95d5aca30ee8 Mon Sep 17 00:00:00 2001 From: Eitan Suez Date: Tue, 30 Apr 2024 11:29:28 -0500 Subject: [PATCH 22/29] docs: updates task testing instructions to use tabs for with|without external load balancer (#3284) docs: updates task testing instructions to use tabs for with|without external load balancer (fixes #3259) Signed-off-by: Eitan Suez --- site/content/en/latest/tasks/quickstart.md | 33 +++++++------ .../en/latest/tasks/security/backend-tls.md | 37 +++++++------- .../en/latest/tasks/security/mutual-tls.md | 43 +++++++++-------- .../latest/tasks/security/secure-gateways.md | 48 ++++++++++++------- .../latest/tasks/security/tls-passthrough.md | 35 ++++++++------ .../latest/tasks/security/tls-termination.md | 35 ++++++++------ site/content/en/latest/tasks/traffic/http3.md | 21 ++++---- 7 files changed, 144 insertions(+), 108 deletions(-) diff --git a/site/content/en/latest/tasks/quickstart.md b/site/content/en/latest/tasks/quickstart.md index 3d857e53dd5..4f345fa289a 100644 --- a/site/content/en/latest/tasks/quickstart.md +++ b/site/content/en/latest/tasks/quickstart.md @@ -48,44 +48,43 @@ consideration when debugging. ## Testing the Configuration {{< tabpane text=true >}} -{{% tab header="Without LoadBalancer Support" %}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +You can also test the same functionality by sending traffic to the External IP. To get the external IP of the +Envoy service, run: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get svc/${ENVOY_SERVICE} -n envoy-gateway-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ``` -Port forward to the Envoy service: - -```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 & -``` +In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace +`ip` in the above command with `hostname`. Curl the example app through Envoy proxy: ```shell -curl --verbose --header "Host: www.example.com" http://localhost:8888/get +curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get ``` {{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -{{% tab header="External LoadBalancer Support" %}} - -You can also test the same functionality by sending traffic to the External IP. To get the external IP of the -Envoy service, run: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get svc/${ENVOY_SERVICE} -n envoy-gateway-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -In certain environments, the load balancer may be exposed using a hostname, instead of an IP address. If so, replace -`ip` in the above command with `hostname`. +Port forward to the Envoy service: + +```shell +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 & +``` Curl the example app through Envoy proxy: ```shell -curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/get +curl --verbose --header "Host: www.example.com" http://localhost:8888/get ``` {{% /tab %}} diff --git a/site/content/en/latest/tasks/security/backend-tls.md b/site/content/en/latest/tasks/security/backend-tls.md index 706d25ae60d..aeedcd503d4 100644 --- a/site/content/en/latest/tasks/security/backend-tls.md +++ b/site/content/en/latest/tasks/security/backend-tls.md @@ -208,24 +208,19 @@ kubectl get HTTPRoute backend -o yaml ## Testing -### Clusters without External LoadBalancer Support - -Get the name of the Envoy service created the by the example Gateway: - -```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') -``` +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Port forward to the Envoy service: +Get the External IP of the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 80:80 & +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Query the TLS-enabled backend through Envoy proxy: +Query the example app through the Gateway: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:80:127.0.0.1" \ +curl -v -HHost:www.example.com --resolve "www.example.com:80:${GATEWAY_HOST}" \ http://www.example.com:80/get ``` @@ -242,18 +237,25 @@ Inspect the output and see that the response contains the details of the TLS han } ``` -### Clusters with External LoadBalancer Support +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -Get the External IP of the Gateway: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -Query the example app through the Gateway: +Port forward to the Envoy service: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:80:${GATEWAY_HOST}" \ +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 80:80 & +``` + +Query the TLS-enabled backend through Envoy proxy: + +```shell +curl -v -HHost:www.example.com --resolve "www.example.com:80:127.0.0.1" \ http://www.example.com:80/get ``` @@ -270,4 +272,7 @@ Inspect the output and see that the response contains the details of the TLS han } ``` +{{% /tab %}} +{{< /tabpane >}} + [BackendTLSPolicy]: https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/ diff --git a/site/content/en/latest/tasks/security/mutual-tls.md b/site/content/en/latest/tasks/security/mutual-tls.md index a848d8334cf..64f471ba19d 100644 --- a/site/content/en/latest/tasks/security/mutual-tls.md +++ b/site/content/en/latest/tasks/security/mutual-tls.md @@ -133,49 +133,54 @@ spec: ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +Get the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Query the example app through the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cert client.example.com.crt --key client.example.com.key \ +--cacert example.com.crt https://www.example.com/get ``` -Query the example app through Envoy proxy: +Don't specify the client key and certificate in the above command, and ensure that the connection fails: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ ---cert client.example.com.crt --key client.example.com.key \ ---cacert example.com.crt https://www.example.com:8443/get +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get ``` -### Clusters with External LoadBalancer Support +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} -Get the External IP of the Gateway: +Get the name of the Envoy service created the by the example Gateway: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -Query the example app through the Gateway: +Port forward to the Envoy service: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cert client.example.com.crt --key client.example.com.key \ ---cacert example.com.crt https://www.example.com/get +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & ``` -Dont specify the client key and certificate in the above command, and ensure that the connection fails +Query the example app through Envoy proxy: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get +curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ +--cert client.example.com.crt --key client.example.com.key \ +--cacert example.com.crt https://www.example.com:8443/get ``` +{{% /tab %}} +{{< /tabpane >}} + [ClientTrafficPolicy]: ../../../api/extension_types#clienttrafficpolicy diff --git a/site/content/en/latest/tasks/security/secure-gateways.md b/site/content/en/latest/tasks/security/secure-gateways.md index 92f685705a4..af5e922412d 100644 --- a/site/content/en/latest/tasks/security/secure-gateways.md +++ b/site/content/en/latest/tasks/security/secure-gateways.md @@ -65,7 +65,24 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} + +Get the External IP of the Gateway: + +```shell +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +``` + +Query the example app through the Gateway: + +```shell +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get +``` + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} Get the name of the Envoy service created the by the example Gateway: @@ -86,20 +103,9 @@ curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ --cacert example.com.crt https://www.example.com:8443/get ``` -### Clusters with External LoadBalancer Support - -Get the External IP of the Gateway: - -```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') -``` - -Query the example app through the Gateway: +{{% /tab %}} +{{< /tabpane >}} -```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get -``` ## Multiple HTTPS Listeners @@ -467,7 +473,14 @@ kubectl patch httproute backend --type=json --patch ' ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} + +Refer to the steps mentioned earlier under [Testing in clusters with External LoadBalancer Support](#testing) + + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} Get the name of the Envoy service created the by the example Gateway: @@ -497,9 +510,8 @@ curl -v -HHost:www.sample.com --resolve "www.sample.com:8443:127.0.0.1" \ Since the multiple certificates are configured on the same Gateway listener, Envoy was able to provide the client with appropriate certificate based on the SNI in the client request. -### Clusters with External LoadBalancer Support - -Refer to the steps mentioned earlier under [Testing in clusters with External LoadBalancer Support](#clusters-with-external-loadbalancer-support) +{{% /tab %}} +{{< /tabpane >}} ## Next Steps diff --git a/site/content/en/latest/tasks/security/tls-passthrough.md b/site/content/en/latest/tasks/security/tls-passthrough.md index 2683f568332..4f9665d6763 100644 --- a/site/content/en/latest/tasks/security/tls-passthrough.md +++ b/site/content/en/latest/tasks/security/tls-passthrough.md @@ -68,42 +68,47 @@ kubectl patch gateway eg --type=json --patch ' ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +You can also test the same functionality by sending traffic to the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Curl the example app through the Gateway, e.g. Envoy proxy: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 6043:6443 & +curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://passthrough.example.com:6443/get ``` -Curl the example app through Envoy proxy: +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +Get the name of the Envoy service created the by the example Gateway: ```shell -curl -v --resolve "passthrough.example.com:6043:127.0.0.1" https://passthrough.example.com:6043 \ ---cacert passthrough.example.com.crt +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -### Clusters with External LoadBalancer Support - -You can also test the same functionality by sending traffic to the External IP of the Gateway: +Port forward to the Envoy service: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 6043:6443 & ``` -Curl the example app through the Gateway, e.g. Envoy proxy: +Curl the example app through Envoy proxy: ```shell -curl -v -HHost:passthrough.example.com --resolve "passthrough.example.com:6443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://passthrough.example.com:6443/get +curl -v --resolve "passthrough.example.com:6043:127.0.0.1" https://passthrough.example.com:6043 \ +--cacert passthrough.example.com.crt ``` +{{% /tab %}} +{{< /tabpane >}} + ## Clean-Up Follow the steps from the [Quickstart](../../quickstart) to uninstall Envoy Gateway and the example manifest. diff --git a/site/content/en/latest/tasks/security/tls-termination.md b/site/content/en/latest/tasks/security/tls-termination.md index 77a701a443a..e4534dd57e1 100644 --- a/site/content/en/latest/tasks/security/tls-termination.md +++ b/site/content/en/latest/tasks/security/tls-termination.md @@ -49,38 +49,43 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} -Get the name of the Envoy service created the by the example Gateway: +Get the External IP of the Gateway: ```shell -export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') +export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') ``` -Port forward to the Envoy service: +Query the example app through the Gateway: ```shell -kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & +curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ +--cacert example.com.crt https://www.example.com/get ``` -Query the example app through Envoy proxy: +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +Get the name of the Envoy service created the by the example Gateway: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ ---cacert example.com.crt https://www.example.com:8443/get +export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}') ``` -### Clusters with External LoadBalancer Support - -Get the External IP of the Gateway: +Port forward to the Envoy service: ```shell -export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}') +kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8443:443 & ``` -Query the example app through the Gateway: +Query the example app through Envoy proxy: ```shell -curl -v -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ ---cacert example.com.crt https://www.example.com/get +curl -v -HHost:www.example.com --resolve "www.example.com:8443:127.0.0.1" \ +--cacert example.com.crt https://www.example.com:8443/get ``` + +{{% /tab %}} +{{< /tabpane >}} diff --git a/site/content/en/latest/tasks/traffic/http3.md b/site/content/en/latest/tasks/traffic/http3.md index 502c37496b6..af95ab8ba57 100644 --- a/site/content/en/latest/tasks/traffic/http3.md +++ b/site/content/en/latest/tasks/traffic/http3.md @@ -108,13 +108,8 @@ kubectl get gateway/eg -o yaml ## Testing -### Clusters without External LoadBalancer Support - -It is not possible at the moment to port-forward UDP protocol in kubernetes service -check out https://github.com/kubernetes/kubernetes/issues/47862. -Hence we need external loadbalancer to test this feature out. - -### Clusters with External LoadBalancer Support +{{< tabpane text=true >}} +{{% tab header="With External LoadBalancer Support" %}} Get the External IP of the Gateway: @@ -124,8 +119,18 @@ export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0]. Query the example app through the Gateway: -Below example uses a custom docker image with custom curl binary with built-in http3. +The below example uses a custom docker image with custom `curl` binary with built-in http3. ```shell docker run --net=host --rm ghcr.io/macbre/curl-http3 curl -kv --http3 -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" https://www.example.com/get ``` + +{{% /tab %}} +{{% tab header="Without LoadBalancer Support" %}} + +It is not possible at the moment to port-forward UDP protocol in kubernetes service +check out https://github.com/kubernetes/kubernetes/issues/47862. +Hence we need external loadbalancer to test this feature out. + +{{% /tab %}} +{{< /tabpane >}} From 6b9bd19901dddbaa8419199397d467e5e7a4a3ca Mon Sep 17 00:00:00 2001 From: zirain Date: Wed, 1 May 2024 05:23:59 +0800 Subject: [PATCH 23/29] e2e: disable EGUpgradeTest (#3310) * chore: add ClientTimeoutTest Signed-off-by: zirain * e2e: disable EGUpgradeTest Signed-off-by: zirain --------- Signed-off-by: zirain --- test/e2e/tests/client_timeout.go | 5 +---- test/e2e/upgrade/eg_upgrade_test.go | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/e2e/tests/client_timeout.go b/test/e2e/tests/client_timeout.go index c3edf9cf1cc..5ae5f00d106 100644 --- a/test/e2e/tests/client_timeout.go +++ b/test/e2e/tests/client_timeout.go @@ -22,9 +22,7 @@ import ( ) func init() { - // This test cause too much flakiness, so we disable it for now. - // TODO: find a better way to test client timeout. - // ConformanceTests = append(ConformanceTests, ClientTimeoutTest) + ConformanceTests = append(ConformanceTests, ClientTimeoutTest) } var largeSizeHeader = func() string { @@ -35,7 +33,6 @@ var largeSizeHeader = func() string { return b.String() } -// nolint var ClientTimeoutTest = suite.ConformanceTest{ ShortName: "ClientTimeout", Description: "Test that the ClientTrafficPolicy API implementation supports client timeout", diff --git a/test/e2e/upgrade/eg_upgrade_test.go b/test/e2e/upgrade/eg_upgrade_test.go index 6ad83b14bd4..999a85ccc53 100644 --- a/test/e2e/upgrade/eg_upgrade_test.go +++ b/test/e2e/upgrade/eg_upgrade_test.go @@ -54,6 +54,7 @@ func TestEGUpgrade(t *testing.T) { RunTest: *flags.RunTest, SkipTests: []string{ tests.EnvoyShutdownTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3262 + tests.EGUpgradeTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3311 }, }) From 8b5f0315e20069ab88aeb43298f6d9a871f677d0 Mon Sep 17 00:00:00 2001 From: zirain Date: Wed, 1 May 2024 05:26:03 +0800 Subject: [PATCH 24/29] chore: Bump k8s.io (#3281) * build(deps): bump the k8s-io group with 6 updates Bumps the k8s-io group with 6 updates: | Package | From | To | | --- | --- | --- | | [k8s.io/api](https://github.com/kubernetes/api) | `0.29.3` | `0.30.0` | | [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.29.3` | `0.30.0` | | [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.29.3` | `0.30.0` | | [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) | `0.29.3` | `0.30.0` | | [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.29.3` | `0.30.0` | | [k8s.io/kubectl](https://github.com/kubernetes/kubectl) | `0.29.3` | `0.30.0` | Updates `k8s.io/api` from 0.29.3 to 0.30.0 - [Commits](https://github.com/kubernetes/api/compare/v0.29.3...v0.30.0) Updates `k8s.io/apiextensions-apiserver` from 0.29.3 to 0.30.0 - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.29.3...v0.30.0) Updates `k8s.io/apimachinery` from 0.29.3 to 0.30.0 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.3...v0.30.0) Updates `k8s.io/cli-runtime` from 0.29.3 to 0.30.0 - [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.29.3...v0.30.0) Updates `k8s.io/client-go` from 0.29.3 to 0.30.0 - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.29.3...v0.30.0) Updates `k8s.io/kubectl` from 0.29.3 to 0.30.0 - [Commits](https://github.com/kubernetes/kubectl/compare/v0.29.3...v0.30.0) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/apiextensions-apiserver dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/apimachinery dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/cli-runtime dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/client-go dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io - dependency-name: k8s.io/kubectl dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-io ... Signed-off-by: dependabot[bot] * make gen Signed-off-by: zirain * bump controller-runtime to 0.18.0 Signed-off-by: zirain * fix test Signed-off-by: zirain --------- Signed-off-by: dependabot[bot] Signed-off-by: zirain Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../gateway.envoyproxy.io_envoyproxies.yaml | 457 +++++++++++++++--- go.mod | 22 +- go.sum | 53 +- internal/provider/kubernetes/controller.go | 424 ++++++++++------ .../provider/kubernetes/controller_test.go | 2 +- internal/provider/kubernetes/predicates.go | 8 +- .../provider/kubernetes/predicates_test.go | 8 +- internal/provider/kubernetes/sources.go | 14 +- internal/provider/kubernetes/sources_test.go | 4 +- 9 files changed, 711 insertions(+), 281 deletions(-) diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 64ff525cad2..79328d5b80d 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -568,6 +568,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -581,6 +605,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -588,6 +613,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -741,6 +767,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -750,6 +778,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -845,11 +896,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -878,11 +931,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -896,6 +951,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -941,11 +997,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -974,14 +1032,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -1047,11 +1108,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1066,12 +1129,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1081,12 +1144,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1129,11 +1192,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1153,6 +1218,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1175,6 +1241,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -1226,11 +1293,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1245,12 +1314,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1260,12 +1329,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1307,11 +1376,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1331,6 +1402,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1343,6 +1415,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling @@ -1404,11 +1477,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1423,12 +1498,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1438,12 +1513,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1486,11 +1561,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1510,6 +1587,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1532,6 +1610,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -1583,11 +1662,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1602,12 +1683,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1617,12 +1698,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -1664,11 +1745,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1688,6 +1771,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1700,6 +1784,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object annotations: @@ -1749,6 +1834,29 @@ spec: SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object fsGroup: description: |- A special supplemental group that applies to all containers in a pod. @@ -1868,6 +1976,7 @@ spec: format: int64 type: integer type: array + x-kubernetes-list-type: atomic sysctls: description: |- Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported @@ -1888,6 +1997,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic windowsOptions: description: |- The Windows specific settings applied to all containers. @@ -2002,11 +2112,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2077,9 +2189,6 @@ spec: In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). format: int32 type: integer nodeAffinityPolicy: @@ -2262,6 +2371,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full @@ -2391,6 +2501,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -2478,7 +2589,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the schema @@ -2544,6 +2656,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -2649,6 +2762,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -2796,11 +2910,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2828,7 +2944,7 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. type: string volumeMode: @@ -2874,6 +2990,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -2881,6 +2998,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -3105,6 +3223,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -3301,11 +3420,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -3386,6 +3507,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -3416,8 +3538,8 @@ spec: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace - are supported.' + labels, name, namespace + and uid are supported.' properties: apiVersion: description: Version @@ -3491,6 +3613,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about @@ -3535,6 +3658,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -3580,6 +3704,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount @@ -3650,6 +3775,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: description: |- pool is the rados pool name. @@ -3809,6 +3935,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -4166,6 +4293,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -4179,6 +4330,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -4186,6 +4338,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -4339,6 +4492,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -4348,6 +4503,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -4387,6 +4565,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic command: description: |- Entrypoint array. Not executed within a shell. @@ -4400,6 +4579,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic env: description: |- List of environment variables to set in the container. @@ -4520,6 +4700,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map envFrom: description: |- List of sources to populate environment variables in the container. @@ -4569,6 +4752,7 @@ spec: x-kubernetes-map-type: atomic type: object type: array + x-kubernetes-list-type: atomic image: description: |- Container image name. @@ -4610,6 +4794,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http @@ -4643,6 +4828,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4726,6 +4912,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http @@ -4759,6 +4946,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4837,6 +5025,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -4893,6 +5082,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -5051,6 +5241,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -5107,6 +5298,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -5303,6 +5495,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -5316,6 +5532,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -5323,6 +5540,7 @@ spec: capabilities type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -5480,6 +5698,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -5536,6 +5755,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -5679,6 +5899,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map volumeMounts: description: |- Pod volumes to mount into the container's filesystem. @@ -5698,6 +5921,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a @@ -5708,6 +5933,29 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + + If ReadOnly is false, this field has no meaning and must be unspecified. + + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -5725,6 +5973,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map workingDir: description: |- Container's working directory. @@ -5813,11 +6064,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -5846,11 +6099,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -5864,6 +6119,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -5909,11 +6165,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -5942,14 +6200,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -6015,11 +6276,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6034,12 +6297,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6049,12 +6312,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6097,11 +6360,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6121,6 +6386,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6143,6 +6409,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -6194,11 +6461,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6213,12 +6482,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6228,12 +6497,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6275,11 +6544,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6299,6 +6570,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6311,6 +6583,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling @@ -6372,11 +6645,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6391,12 +6666,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6406,12 +6681,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6454,11 +6729,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6478,6 +6755,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6500,6 +6778,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -6551,11 +6830,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6570,12 +6851,12 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6585,12 +6866,12 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. items: type: string @@ -6632,11 +6913,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6656,6 +6939,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -6668,6 +6952,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object annotations: @@ -6717,6 +7002,29 @@ spec: SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object fsGroup: description: |- A special supplemental group that applies to all containers in a pod. @@ -6836,6 +7144,7 @@ spec: format: int64 type: integer type: array + x-kubernetes-list-type: atomic sysctls: description: |- Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported @@ -6856,6 +7165,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic windowsOptions: description: |- The Windows specific settings applied to all containers. @@ -6970,11 +7280,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -7045,9 +7357,6 @@ spec: In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). format: int32 type: integer nodeAffinityPolicy: @@ -7230,6 +7539,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full @@ -7359,6 +7669,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -7446,7 +7757,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the schema @@ -7512,6 +7824,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -7617,6 +7930,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -7764,11 +8078,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -7796,7 +8112,7 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. type: string volumeMode: @@ -7842,6 +8158,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -7849,6 +8166,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -8073,6 +8391,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -8269,11 +8588,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8354,6 +8675,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -8384,8 +8706,8 @@ spec: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace - are supported.' + labels, name, namespace + and uid are supported.' properties: apiVersion: description: Version @@ -8459,6 +8781,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about @@ -8503,6 +8826,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: description: |- Name of the referent. @@ -8548,6 +8872,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount @@ -8618,6 +8943,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: description: |- pool is the rados pool name. @@ -8777,6 +9103,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -9174,11 +9501,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9300,11 +9629,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9408,11 +9739,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string diff --git a/go.mod b/go.mod index 036642b6491..ba3e100d73a 100644 --- a/go.mod +++ b/go.mod @@ -42,14 +42,14 @@ require ( google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.14.4 - k8s.io/api v0.29.3 - k8s.io/apiextensions-apiserver v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/cli-runtime v0.29.3 - k8s.io/client-go v0.29.3 - k8s.io/kubectl v0.29.3 + k8s.io/api v0.30.0 + k8s.io/apiextensions-apiserver v0.30.0 + k8s.io/apimachinery v0.30.0 + k8s.io/cli-runtime v0.30.0 + k8s.io/client-go v0.30.0 + k8s.io/kubectl v0.30.0 k8s.io/utils v0.0.0-20230726121419-3b25d923346b - sigs.k8s.io/controller-runtime v0.17.3 + sigs.k8s.io/controller-runtime v0.18.0 sigs.k8s.io/gateway-api v1.0.0 sigs.k8s.io/mcs-api v0.1.0 sigs.k8s.io/yaml v1.4.0 @@ -109,7 +109,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect golang.org/x/crypto v0.22.0 // indirect - k8s.io/apiserver v0.29.3 // indirect + k8s.io/apiserver v0.30.0 // indirect oras.land/oras-go v1.2.4 // indirect ) @@ -185,9 +185,9 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.29.3 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/component-base v0.30.0 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect diff --git a/go.sum b/go.sum index e0a9392cf1f..0d42859e767 100644 --- a/go.sum +++ b/go.sum @@ -213,7 +213,6 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -522,15 +521,15 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 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/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= @@ -943,46 +942,46 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= +k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= -k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= -k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= +k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs= +k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -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.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= +k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= -k8s.io/apiserver v0.29.3 h1:xR7ELlJ/BZSr2n4CnD3lfA4gzFivh0wwfNfz9L0WZcE= -k8s.io/apiserver v0.29.3/go.mod h1:hrvXlwfRulbMbBgmWRQlFru2b/JySDpmzvQwwk4GUOs= -k8s.io/cli-runtime v0.29.3 h1:r68rephmmytoywkw2MyJ+CxjpasJDQY7AGc3XY2iv1k= -k8s.io/cli-runtime v0.29.3/go.mod h1:aqVUsk86/RhaGJwDhHXH0jcdqBrgdF3bZWk4Z9D4mkM= +k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M= +k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY= +k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48= +k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= +k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk= -k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= -k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= +k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o= +k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us= -k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4= +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/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk= +k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= @@ -991,8 +990,8 @@ oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY= oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A= -sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9oYYYk= -sigs.k8s.io/controller-runtime v0.17.3/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= +sigs.k8s.io/controller-runtime v0.18.0 h1:Z7jKuX784TQSUL1TIyeuF7j8KXZ4RtSX0YgtjKcSTME= +sigs.k8s.io/controller-runtime v0.18.0/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 93ce3fe9145..0cdbe5c8f7f 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -913,51 +913,57 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Upon leader election, we retrigger the reconciliation process to allow the elected leader to // process status updates and infrastructure changes. This step is crucial for synchronizing resources // that may have been altered or introduced while there was no elected leader. - if err := c.Watch( - NewWatchAndReconcileSource(mgr.Elected(), &gwapiv1.GatewayClass{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass)); err != nil { + if err := c.Watch(NewWatchAndReconcileSource(mgr.Elected(), &gwapiv1.GatewayClass{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass))); err != nil { return err } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.GatewayClass{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.hasMatchingController), - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.GatewayClass{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, gc *gwapiv1.GatewayClass) []reconcile.Request { + return r.enqueueClass(ctx, gc) + }), + &predicate.TypedGenerationChangedPredicate[*gwapiv1.GatewayClass]{}, + predicate.NewTypedPredicateFuncs[*gwapiv1.GatewayClass](r.hasMatchingController))); err != nil { return err } // Only enqueue EnvoyProxy objects that match this Envoy Gateway's GatewayClass. - epPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.ResourceVersionChangedPredicate{}, - predicate.NewPredicateFuncs(r.hasManagedClass), + epPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyProxy]{ + &predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyProxy]{}, + predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyProxy](r.hasManagedClass), } if r.namespaceLabel != nil { - epPredicates = append(epPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + epPredicates = append(epPredicates, predicate.NewTypedPredicateFuncs(func(ep *egv1a1.EnvoyProxy) bool { + return r.hasMatchingNamespaceLabels(ep) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - epPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *egv1a1.EnvoyProxy) []reconcile.Request { + return r.enqueueClass(ctx, t) + }), + epPredicates...)); err != nil { return err } // Watch Gateway CRUDs and reconcile affected GatewayClass. - gPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateGatewayForReconcile), + gPredicates := []predicate.TypedPredicate[*gwapiv1.Gateway]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1.Gateway]{}, + predicate.NewTypedPredicateFuncs(func(gtw *gwapiv1.Gateway) bool { + return r.validateGatewayForReconcile(gtw) + }), } if r.namespaceLabel != nil { - gPredicates = append(gPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + gPredicates = append(gPredicates, predicate.NewTypedPredicateFuncs(func(gtw *gwapiv1.Gateway) bool { + return r.hasMatchingNamespaceLabels(gtw) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.Gateway{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - gPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.Gateway{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, gtw *gwapiv1.Gateway) []reconcile.Request { + return r.enqueueClass(ctx, gtw) + }), + gPredicates...)); err != nil { return err } if err := addGatewayIndexers(ctx, mgr); err != nil { @@ -965,15 +971,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch HTTPRoute CRUDs and process affected Gateways. - httprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + httprPredicates := []predicate.TypedPredicate[*gwapiv1.HTTPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1.HTTPRoute]{}, + } if r.namespaceLabel != nil { - httprPredicates = append(httprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + httprPredicates = append(httprPredicates, predicate.NewTypedPredicateFuncs(func(hr *gwapiv1.HTTPRoute) bool { + return r.hasMatchingNamespaceLabels(hr) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1.HTTPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - httprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1.HTTPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *gwapiv1.HTTPRoute) []reconcile.Request { + return r.enqueueClass(ctx, t) + }), + httprPredicates...)); err != nil { return err } if err := addHTTPRouteIndexers(ctx, mgr); err != nil { @@ -981,15 +992,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch GRPCRoute CRUDs and process affected Gateways. - grpcrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + grpcrPredicates := []predicate.TypedPredicate[*gwapiv1a2.GRPCRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.GRPCRoute]{}, + } if r.namespaceLabel != nil { - grpcrPredicates = append(grpcrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + grpcrPredicates = append(grpcrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.GRPCRoute](func(grpc *gwapiv1a2.GRPCRoute) bool { + return r.hasMatchingNamespaceLabels(grpc) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.GRPCRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - grpcrPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.GRPCRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.GRPCRoute](func(ctx context.Context, route *gwapiv1a2.GRPCRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + grpcrPredicates...)); err != nil { return err } if err := addGRPCRouteIndexers(ctx, mgr); err != nil { @@ -997,15 +1013,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch TLSRoute CRUDs and process affected Gateways. - tlsrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + tlsrPredicates := []predicate.TypedPredicate[*gwapiv1a2.TLSRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, + } if r.namespaceLabel != nil { - tlsrPredicates = append(tlsrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + tlsrPredicates = append(tlsrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TLSRoute](func(route *gwapiv1a2.TLSRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - tlsrPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.TLSRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TLSRoute](func(ctx context.Context, route *gwapiv1a2.TLSRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tlsrPredicates...)); err != nil { return err } if err := addTLSRouteIndexers(ctx, mgr); err != nil { @@ -1013,15 +1034,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch UDPRoute CRUDs and process affected Gateways. - udprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + udprPredicates := []predicate.TypedPredicate[*gwapiv1a2.UDPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, + } if r.namespaceLabel != nil { - udprPredicates = append(udprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + udprPredicates = append(udprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.UDPRoute](func(route *gwapiv1a2.UDPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - udprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.UDPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.UDPRoute](func(ctx context.Context, route *gwapiv1a2.UDPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + udprPredicates...)); err != nil { return err } if err := addUDPRouteIndexers(ctx, mgr); err != nil { @@ -1029,15 +1055,20 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch TCPRoute CRUDs and process affected Gateways. - tcprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + tcprPredicates := []predicate.TypedPredicate[*gwapiv1a2.TCPRoute]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, + } if r.namespaceLabel != nil { - tcprPredicates = append(tcprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + tcprPredicates = append(tcprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TCPRoute](func(route *gwapiv1a2.TCPRoute) bool { + return r.hasMatchingNamespaceLabels(route) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - tcprPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.TCPRoute{}, + handler.TypedEnqueueRequestsFromMapFunc[*gwapiv1a2.TCPRoute](func(ctx context.Context, route *gwapiv1a2.TCPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) + }), + tcprPredicates...)); err != nil { return err } if err := addTCPRouteIndexers(ctx, mgr); err != nil { @@ -1045,15 +1076,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch Service CRUDs and process affected *Route objects. - servicePredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateServiceForReconcile)} + servicePredicates := []predicate.TypedPredicate[*corev1.Service]{ + predicate.NewTypedPredicateFuncs[*corev1.Service](func(svc *corev1.Service) bool { + return r.validateServiceForReconcile(svc) + }), + } if r.namespaceLabel != nil { - servicePredicates = append(servicePredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + servicePredicates = append(servicePredicates, predicate.NewTypedPredicateFuncs[*corev1.Service](func(svc *corev1.Service) bool { + return r.hasMatchingNamespaceLabels(svc) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Service{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - servicePredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Service{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, svc *corev1.Service) []reconcile.Request { + return r.enqueueClass(ctx, svc) + }), + servicePredicates...)); err != nil { return err } @@ -1065,91 +1103,120 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch ServiceImport CRUDs and process affected *Route objects. if serviceImportCRDExists { if err := c.Watch( - source.Kind(mgr.GetCache(), &mcsapi.ServiceImport{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateServiceImportForReconcile)); err != nil { + source.Kind(mgr.GetCache(), &mcsapi.ServiceImport{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *mcsapi.ServiceImport) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + predicate.TypedGenerationChangedPredicate[*mcsapi.ServiceImport]{}, + predicate.NewTypedPredicateFuncs[*mcsapi.ServiceImport](func(si *mcsapi.ServiceImport) bool { + return r.validateServiceImportForReconcile(si) + }))); err != nil { // ServiceImport is not available in the cluster, skip the watch and not throw error. r.log.Info("unable to watch ServiceImport: %s", err.Error()) } } // Watch EndpointSlice CRUDs and process affected *Route objects. - esPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateEndpointSliceForReconcile), + esPredicates := []predicate.TypedPredicate[*discoveryv1.EndpointSlice]{ + predicate.TypedGenerationChangedPredicate[*discoveryv1.EndpointSlice]{}, + predicate.NewTypedPredicateFuncs[*discoveryv1.EndpointSlice](func(eps *discoveryv1.EndpointSlice) bool { + return r.validateEndpointSliceForReconcile(eps) + }), } if r.namespaceLabel != nil { - esPredicates = append(esPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + esPredicates = append(esPredicates, predicate.NewTypedPredicateFuncs[*discoveryv1.EndpointSlice](func(eps *discoveryv1.EndpointSlice) bool { + return r.hasMatchingNamespaceLabels(eps) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &discoveryv1.EndpointSlice{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - esPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &discoveryv1.EndpointSlice{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *discoveryv1.EndpointSlice) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + esPredicates...)); err != nil { return err } // Watch Node CRUDs to update Gateway Address exposed by Service of type NodePort. // Node creation/deletion and ExternalIP updates would require update in the Gateway - nPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.handleNode), + nPredicates := []predicate.TypedPredicate[*corev1.Node]{ + predicate.TypedGenerationChangedPredicate[*corev1.Node]{}, + predicate.NewTypedPredicateFuncs[*corev1.Node](func(node *corev1.Node) bool { + return r.handleNode(node) + }), } if r.namespaceLabel != nil { - nPredicates = append(nPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + nPredicates = append(nPredicates, predicate.NewTypedPredicateFuncs[*corev1.Node](func(node *corev1.Node) bool { + return r.hasMatchingNamespaceLabels(node) + })) } // resource address. if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Node{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - nPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Node{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *corev1.Node) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + nPredicates...)); err != nil { return err } // Watch Secret CRUDs and process affected EG CRs (Gateway, SecurityPolicy, more in the future). - secretPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateSecretForReconcile), + secretPredicates := []predicate.TypedPredicate[*corev1.Secret]{ + predicate.TypedGenerationChangedPredicate[*corev1.Secret]{}, + predicate.NewTypedPredicateFuncs(func(s *corev1.Secret) bool { + return r.validateSecretForReconcile(s) + }), } if r.namespaceLabel != nil { - secretPredicates = append(secretPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + secretPredicates = append(secretPredicates, predicate.NewTypedPredicateFuncs(func(s *corev1.Secret) bool { + return r.hasMatchingNamespaceLabels(s) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.Secret{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - secretPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.Secret{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, s *corev1.Secret) []reconcile.Request { + return r.enqueueClass(ctx, s) + }), + secretPredicates...)); err != nil { return err } // Watch ConfigMap CRUDs and process affected ClienTraffiPolicies and BackendTLSPolicies. - configMapPredicates := []predicate.Predicate{ - predicate.GenerationChangedPredicate{}, - predicate.NewPredicateFuncs(r.validateConfigMapForReconcile), + configMapPredicates := []predicate.TypedPredicate[*corev1.ConfigMap]{ + predicate.TypedGenerationChangedPredicate[*corev1.ConfigMap]{}, + predicate.NewTypedPredicateFuncs[*corev1.ConfigMap](func(cm *corev1.ConfigMap) bool { + return r.validateConfigMapForReconcile(cm) + }), } if r.namespaceLabel != nil { - configMapPredicates = append(configMapPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + configMapPredicates = append(configMapPredicates, predicate.NewTypedPredicateFuncs[*corev1.ConfigMap](func(cm *corev1.ConfigMap) bool { + return r.hasMatchingNamespaceLabels(cm) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &corev1.ConfigMap{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - configMapPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &corev1.ConfigMap{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, cm *corev1.ConfigMap) []reconcile.Request { + return r.enqueueClass(ctx, cm) + }), + configMapPredicates...)); err != nil { return err } // Watch ReferenceGrant CRUDs and process affected Gateways. - rgPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + rgPredicates := []predicate.TypedPredicate[*gwapiv1b1.ReferenceGrant]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1b1.ReferenceGrant]{}, + } if r.namespaceLabel != nil { - rgPredicates = append(rgPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + rgPredicates = append(rgPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1b1.ReferenceGrant](func(rg *gwapiv1b1.ReferenceGrant) bool { + return r.hasMatchingNamespaceLabels(rg) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1b1.ReferenceGrant{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - rgPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1b1.ReferenceGrant{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, rg *gwapiv1b1.ReferenceGrant) []reconcile.Request { + return r.enqueueClass(ctx, rg) + }), + rgPredicates...)); err != nil { return err } if err := addReferenceGrantIndexers(ctx, mgr); err != nil { @@ -1157,45 +1224,62 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch Deployment CRUDs and process affected Gateways. - dPredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateDeploymentForReconcile)} + dPredicates := []predicate.TypedPredicate[*appsv1.Deployment]{ + predicate.NewTypedPredicateFuncs[*appsv1.Deployment](func(deploy *appsv1.Deployment) bool { + return r.validateDeploymentForReconcile(deploy) + }), + } if r.namespaceLabel != nil { - dPredicates = append(dPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + dPredicates = append(dPredicates, predicate.NewTypedPredicateFuncs[*appsv1.Deployment](func(deploy *appsv1.Deployment) bool { + return r.hasMatchingNamespaceLabels(deploy) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &appsv1.Deployment{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - dPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &appsv1.Deployment{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, deploy *appsv1.Deployment) []reconcile.Request { + return r.enqueueClass(ctx, deploy) + }), + dPredicates...)); err != nil { return err } - // Watch EnvoyPatchPolicy if enabled in config - eppPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if r.namespaceLabel != nil { - eppPredicates = append(eppPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) - } if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { + // Watch EnvoyPatchPolicy if enabled in config + eppPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyPatchPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyPatchPolicy]{}, + } + if r.namespaceLabel != nil { + eppPredicates = append(eppPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyPatchPolicy](func(epp *egv1a1.EnvoyPatchPolicy) bool { + return r.hasMatchingNamespaceLabels(epp) + })) + } // Watch EnvoyPatchPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - eppPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, epp *egv1a1.EnvoyPatchPolicy) []reconcile.Request { + return r.enqueueClass(ctx, epp) + }), + eppPredicates...)); err != nil { return err } } // Watch ClientTrafficPolicy - ctpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + ctpPredicates := []predicate.TypedPredicate[*egv1a1.ClientTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.ClientTrafficPolicy]{}, + } if r.namespaceLabel != nil { - ctpPredicates = append(ctpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + ctpPredicates = append(ctpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.ClientTrafficPolicy](func(ctp *egv1a1.ClientTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(ctp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - ctpPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, ctp *egv1a1.ClientTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, ctp) + }), + ctpPredicates...)); err != nil { return err } @@ -1204,30 +1288,40 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch BackendTrafficPolicy - btpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + btpPredicates := []predicate.TypedPredicate[*egv1a1.BackendTrafficPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.BackendTrafficPolicy]{}, + } if r.namespaceLabel != nil { - btpPredicates = append(btpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + btpPredicates = append(btpPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.BackendTrafficPolicy](func(btp *egv1a1.BackendTrafficPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - btpPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *egv1a1.BackendTrafficPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btpPredicates...)); err != nil { return err } // Watch SecurityPolicy - spPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + spPredicates := []predicate.TypedPredicate[*egv1a1.SecurityPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.SecurityPolicy]{}, + } if r.namespaceLabel != nil { - spPredicates = append(spPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + spPredicates = append(spPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.SecurityPolicy](func(sp *egv1a1.SecurityPolicy) bool { + return r.hasMatchingNamespaceLabels(sp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - spPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, sp *egv1a1.SecurityPolicy) []reconcile.Request { + return r.enqueueClass(ctx, sp) + }), + spPredicates...)); err != nil { return err } if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { @@ -1235,16 +1329,21 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch BackendTLSPolicy - btlsPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + btlsPredicates := []predicate.TypedPredicate[*gwapiv1a2.BackendTLSPolicy]{ + predicate.TypedGenerationChangedPredicate[*gwapiv1a2.BackendTLSPolicy]{}, + } if r.namespaceLabel != nil { - btlsPredicates = append(btlsPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + btlsPredicates = append(btlsPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.BackendTLSPolicy](func(btp *gwapiv1a2.BackendTLSPolicy) bool { + return r.hasMatchingNamespaceLabels(btp) + })) } if err := c.Watch( - source.Kind(mgr.GetCache(), &gwapiv1a2.BackendTLSPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - btlsPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &gwapiv1a2.BackendTLSPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, btp *gwapiv1a2.BackendTLSPolicy) []reconcile.Request { + return r.enqueueClass(ctx, btp) + }), + btlsPredicates...)); err != nil { return err } @@ -1253,17 +1352,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } // Watch EnvoyExtensionPolicy - eepPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + eepPredicates := []predicate.TypedPredicate[*egv1a1.EnvoyExtensionPolicy]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.EnvoyExtensionPolicy]{}, + } if r.namespaceLabel != nil { - eepPredicates = append(eepPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + eepPredicates = append(eepPredicates, predicate.NewTypedPredicateFuncs[*egv1a1.EnvoyExtensionPolicy](func(eep *egv1a1.EnvoyExtensionPolicy) bool { + return r.hasMatchingNamespaceLabels(eep) + })) } // Watch EnvoyExtensionPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - eepPredicates..., - ); err != nil { + source.Kind(mgr.GetCache(), &egv1a1.EnvoyExtensionPolicy{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, eep *egv1a1.EnvoyExtensionPolicy) []reconcile.Request { + return r.enqueueClass(ctx, eep) + }), + eepPredicates...)); err != nil { return err } if err := addEnvoyExtensionPolicyIndexers(ctx, mgr); err != nil { @@ -1273,17 +1377,22 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M r.log.Info("Watching gatewayAPI related objects") // Watch any additional GVKs from the registered extension. - uPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} + uPredicates := []predicate.TypedPredicate[*unstructured.Unstructured]{ + predicate.TypedGenerationChangedPredicate[*unstructured.Unstructured]{}, + } if r.namespaceLabel != nil { - uPredicates = append(uPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + uPredicates = append(uPredicates, predicate.NewTypedPredicateFuncs[*unstructured.Unstructured](func(obj *unstructured.Unstructured) bool { + return r.hasMatchingNamespaceLabels(obj) + })) } for _, gvk := range r.extGVKs { u := &unstructured.Unstructured{} u.SetGroupVersionKind(gvk) - if err := c.Watch(source.Kind(mgr.GetCache(), u), - handler.EnqueueRequestsFromMapFunc(r.enqueueClass), - uPredicates..., - ); err != nil { + if err := c.Watch(source.Kind(mgr.GetCache(), u, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, si *unstructured.Unstructured) []reconcile.Request { + return r.enqueueClass(ctx, si) + }), + uPredicates...)); err != nil { return err } r.log.Info("Watching additional resource", "resource", gvk.String()) @@ -1297,12 +1406,7 @@ func (r *gatewayAPIReconciler) enqueueClass(_ context.Context, _ client.Object) }}} } -func (r *gatewayAPIReconciler) hasManagedClass(obj client.Object) bool { - ep, ok := obj.(*egv1a1.EnvoyProxy) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) - } - +func (r *gatewayAPIReconciler) hasManagedClass(ep *egv1a1.EnvoyProxy) bool { // The EnvoyProxy must be in the same namespace as EG. if ep.Namespace != r.namespace { r.log.Info("envoyproxy namespace does not match Envoy Gateway's namespace", diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go index 1aa58a1d533..8e3a5f9b56f 100644 --- a/internal/provider/kubernetes/controller_test.go +++ b/internal/provider/kubernetes/controller_test.go @@ -156,7 +156,7 @@ func TestHasManagedClass(t *testing.T) { testCases := []struct { name string - ep client.Object + ep *egv1a1.EnvoyProxy classes []*gwapiv1.GatewayClass expected bool }{ diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 4faf3d0d5e7..1c0668f1a9b 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -33,13 +33,7 @@ const oidcHMACSecretName = "envoy-oidc-hmac" // hasMatchingController returns true if the provided object is a GatewayClass // with a Spec.Controller string matching this Envoy Gateway's controller string, // or false otherwise. -func (r *gatewayAPIReconciler) hasMatchingController(obj client.Object) bool { - gc, ok := obj.(*gwapiv1.GatewayClass) - if !ok { - r.log.Info("bypassing reconciliation due to unexpected object type", "type", obj) - return false - } - +func (r *gatewayAPIReconciler) hasMatchingController(gc *gwapiv1.GatewayClass) bool { if gc.Spec.ControllerName == r.classController { r.log.Info("gatewayclass has matching controller name, processing", "name", gc.Name) return true diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index b23ebb41d86..6f327b0c23a 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -33,18 +33,18 @@ import ( func TestGatewayClassHasMatchingController(t *testing.T) { testCases := []struct { name string - obj client.Object + gc *gwapiv1.GatewayClass client client.Client expect bool }{ { name: "matching controller name", - obj: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), + gc: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), expect: true, }, { name: "non-matching controller name", - obj: test.GetGatewayClass("test-gc", "not.configured/controller", nil), + gc: test.GetGatewayClass("test-gc", "not.configured/controller", nil), expect: false, }, } @@ -60,7 +60,7 @@ func TestGatewayClassHasMatchingController(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - res := r.hasMatchingController(tc.obj) + res := r.hasMatchingController(tc.gc) require.Equal(t, tc.expect, res) }) } diff --git a/internal/provider/kubernetes/sources.go b/internal/provider/kubernetes/sources.go index 66d93acb0d5..e19259f77ca 100644 --- a/internal/provider/kubernetes/sources.go +++ b/internal/provider/kubernetes/sources.go @@ -13,22 +13,22 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/source" ) // watchAndReconcileSource is a concrete implementation of the Source interface. type watchAndReconcileSource struct { - condition <-chan struct{} - object client.Object + condition <-chan struct{} + object client.Object + eventHandler handler.EventHandler } -func NewWatchAndReconcileSource(cond <-chan struct{}, obj client.Object) source.Source { - return &watchAndReconcileSource{condition: cond, object: obj} +func NewWatchAndReconcileSource(cond <-chan struct{}, obj client.Object, eh handler.EventHandler) source.Source { + return &watchAndReconcileSource{condition: cond, object: obj, eventHandler: eh} } // Start implements the Source interface. It registers the EventHandler with the Informer. -func (s *watchAndReconcileSource) Start(ctx context.Context, eh handler.EventHandler, queue workqueue.RateLimitingInterface, _ ...predicate.Predicate) error { +func (s *watchAndReconcileSource) Start(ctx context.Context, queue workqueue.RateLimitingInterface) error { if s.object == nil { return errors.New("object to queue is required") } @@ -39,7 +39,7 @@ func (s *watchAndReconcileSource) Start(ctx context.Context, eh handler.EventHan return case <-s.condition: // Triggers a reconcile - eh.Generic(ctx, event.GenericEvent{Object: s.object}, queue) + s.eventHandler.Generic(ctx, event.GenericEvent{Object: s.object}, queue) } }() return nil diff --git a/internal/provider/kubernetes/sources_test.go b/internal/provider/kubernetes/sources_test.go index adae9f8f854..aafc74bd2b6 100644 --- a/internal/provider/kubernetes/sources_test.go +++ b/internal/provider/kubernetes/sources_test.go @@ -59,8 +59,8 @@ func TestSources(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { cond := make(chan struct{}) - store := NewWatchAndReconcileSource(cond, tc.obj) - err := store.Start(tc.ctx, tc.handler, tc.queue) + store := NewWatchAndReconcileSource(cond, tc.obj, tc.handler) + err := store.Start(tc.ctx, tc.queue) if !tc.expected { require.Error(t, err) } else { From 2e0971b288097e9c4d03b1d7d7300d6659ed4c39 Mon Sep 17 00:00:00 2001 From: zirain Date: Wed, 1 May 2024 05:28:03 +0800 Subject: [PATCH 25/29] helm: use IfNotPresent for versioned helm chart release (#3289) Signed-off-by: zirain Co-authored-by: Guy Daich --- .github/workflows/build_and_test.yaml | 2 +- charts/gateway-helm/values.tmpl.yaml | 2 +- site/content/en/latest/install/api.md | 2 +- test/helm/default.yaml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index e34f76cf676..a03fe40a02a 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -174,4 +174,4 @@ jobs: - name: Build and Push EG Latest Helm Chart if: github.event_name == 'push' && github.ref == 'refs/heads/main' # use `0.0.0` as the default latest version. - run: OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push + run: IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index d7d43391039..5ebcd1f3438 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -3,7 +3,7 @@ deployment: image: repository: ${ImageRepository} tag: '${ImageTag}' - imagePullPolicy: Always + imagePullPolicy: IfNotPresent imagePullSecrets: [] resources: limits: diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index 944a31f1e2e..b156702164a 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -35,7 +35,7 @@ The Helm chart for Envoy Gateway | createNamespace | bool | `false` | | | deployment.envoyGateway.image.repository | string | `"${ImageRepository}"` | | | deployment.envoyGateway.image.tag | string | `"${ImageTag}"` | | -| deployment.envoyGateway.imagePullPolicy | string | `"Always"` | | +| deployment.envoyGateway.imagePullPolicy | string | `"IfNotPresent"` | | | deployment.envoyGateway.imagePullSecrets | list | `[]` | | | deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | | deployment.envoyGateway.resources.limits.memory | string | `"1024Mi"` | | diff --git a/test/helm/default.yaml b/test/helm/default.yaml index 2feb28c1373..5bebac04aad 100644 --- a/test/helm/default.yaml +++ b/test/helm/default.yaml @@ -369,7 +369,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: Always + imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz @@ -517,7 +517,7 @@ spec: - name: KUBERNETES_CLUSTER_DOMAIN value: cluster.local image: docker.io/envoyproxy/gateway-dev:latest - imagePullPolicy: Always + imagePullPolicy: IfNotPresent name: envoy-gateway-certgen restartPolicy: Never securityContext: From 9a626f262317b90946219d7f85069221cce2c4b6 Mon Sep 17 00:00:00 2001 From: Lior Okman Date: Wed, 1 May 2024 19:40:09 +0300 Subject: [PATCH 26/29] e2e: Add an e2e test for useClientProtocol (#3314) * Added an e2e test for useClientProtocol Signed-off-by: Lior Okman * make linter happy Signed-off-by: Lior Okman --------- Signed-off-by: Lior Okman --- test/e2e/base/manifests.yaml | 5 + test/e2e/testdata/use-client-protocol.yaml | 36 ++++++ test/e2e/tests/use_client_protocol.go | 129 +++++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 test/e2e/testdata/use-client-protocol.yaml create mode 100644 test/e2e/tests/use_client_protocol.go diff --git a/test/e2e/base/manifests.yaml b/test/e2e/base/manifests.yaml index 1f456581e47..92a1c6e0a9d 100644 --- a/test/e2e/base/manifests.yaml +++ b/test/e2e/base/manifests.yaml @@ -94,7 +94,12 @@ spec: ports: - protocol: TCP port: 8080 + name: http11 targetPort: 3000 + - protocol: TCP + port: 8081 + name: http2 + targetPort: 3001 --- apiVersion: apps/v1 kind: Deployment diff --git a/test/e2e/testdata/use-client-protocol.yaml b/test/e2e/testdata/use-client-protocol.yaml new file mode 100644 index 00000000000..c624da1bc17 --- /dev/null +++ b/test/e2e/testdata/use-client-protocol.yaml @@ -0,0 +1,36 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: use-client-protocol-btp + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: use-client-protocol + namespace: gateway-conformance-infra + useClientProtocol: true +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: use-client-protocol + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /http11 + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /http2 + backendRefs: + - name: infra-backend-v1 + port: 8081 diff --git a/test/e2e/tests/use_client_protocol.go b/test/e2e/tests/use_client_protocol.go new file mode 100644 index 00000000000..1ea6029bf4f --- /dev/null +++ b/test/e2e/tests/use_client_protocol.go @@ -0,0 +1,129 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e +// +build e2e + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, UseClientProtocolTest) +} + +var UseClientProtocolTest = suite.ConformanceTest{ + ShortName: "UseClientProtocol", + Description: "Test that the UseClientProtocol knob does what it's supposed to", + Manifests: []string{"testdata/use-client-protocol.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("use client protocol", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "use-client-protocol", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + // Send an http/1.1 request to the /http11 path + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/http11/headers", + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + if cReq.Protocol != "HTTP/1.1" { + t.Errorf("expected http/1.1 protocol, got %s", cReq.Protocol) + } + + // Send an http/1.1 request to the http/2 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http2/headers", + }, + Response: http.Response{ + StatusCode: 400, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + + // Send an http/2 request to the /http2 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http2/headers", + Protocol: roundtripper.H2CPriorKnowledgeProtocol, + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + if cReq.Protocol != "HTTP/2.0" { + t.Errorf("expected http/2.0 protocol, got %s", cReq.Protocol) + } + + // Send an http/2 request to the http/1.1 path + expectedResponse = http.ExpectedResponse{ + Request: http.Request{ + Path: "/http11/headers", + Protocol: roundtripper.H2CPriorKnowledgeProtocol, + }, + Response: http.Response{ + StatusCode: 502, + }, + Namespace: ns, + } + + req = http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err = suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + }) + }, +} From 1e4640a189b8c179282536266649d984db559ce2 Mon Sep 17 00:00:00 2001 From: zirain Date: Fri, 3 May 2024 00:42:15 +0800 Subject: [PATCH 27/29] fix helm IfNotPresent (#3320) * fix helm IfNotPresent Signed-off-by: zirain * fix gen Signed-off-by: zirain --------- Signed-off-by: zirain --- .github/workflows/build_and_test.yaml | 5 +++-- .github/workflows/latest_release.yaml | 3 ++- .github/workflows/release.yaml | 4 ++-- charts/gateway-helm/values.tmpl.yaml | 2 +- site/content/en/latest/install/api.md | 4 ++-- tools/make/common.mk | 2 +- tools/make/docs.mk | 3 ++- tools/make/helm.mk | 4 +++- tools/make/kube.mk | 4 +--- 9 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index a03fe40a02a..66bf96ebd77 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -22,9 +22,9 @@ jobs: steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: ./tools/github-actions/setup-deps - # Generate the install manifests first so it can checked + # Generate the installation manifests first, so it can check # for errors while running `make -k lint` - - run: make generate-manifests + - run: IMAGE_PULL_POLICY=Always make generate-manifests - run: make lint-deps - run: make -k lint @@ -174,4 +174,5 @@ jobs: - name: Build and Push EG Latest Helm Chart if: github.event_name == 'push' && github.ref == 'refs/heads/main' # use `0.0.0` as the default latest version. + # use `Always` image pull policy for latest version. run: IMAGE_PULL_POLICY=Always OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=v0.0.0-latest TAG=latest make helm-package helm-push diff --git a/.github/workflows/latest_release.yaml b/.github/workflows/latest_release.yaml index de577267da3..9a3f8b46803 100644 --- a/.github/workflows/latest_release.yaml +++ b/.github/workflows/latest_release.yaml @@ -26,7 +26,8 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Generate Release Manifests - run: make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts + # Use `Always` image pull policy for latest version. + run: IMAGE_PULL_POLICY=Always make generate-manifests IMAGE=envoyproxy/gateway-dev TAG=latest OUTPUT_DIR=release-artifacts - name: Build egctl latest multiarch binaries run: | diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a104b0f1daf..f69ef41648e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -34,10 +34,10 @@ jobs: skopeo copy --all docker://docker.io/envoyproxy/gateway-dev:${{ env.sha_short }} docker://docker.io/envoyproxy/gateway:${{ env.release_tag }} - name: Generate Release Artifacts - run: make generate-artifacts IMAGE=envoyproxy/gateway TAG=${{ env.release_tag }} OUTPUT_DIR=release-artifacts + run: IMAGE_PULL_POLICY=IfNotPresent make generate-artifacts IMAGE=envoyproxy/gateway TAG=${{ env.release_tag }} OUTPUT_DIR=release-artifacts - name: Build and Push EG Release Helm Chart - run: OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=${{ env.release_tag }} IMAGE=docker.io/envoyproxy/gateway TAG=${{ env.release_tag }} make helm-package helm-push + run: IMAGE_PULL_POLICY=IfNotPresent OCI_REGISTRY=oci://docker.io/envoyproxy CHART_VERSION=${{ env.release_tag }} IMAGE=docker.io/envoyproxy/gateway TAG=${{ env.release_tag }} make helm-package helm-push - name: Upload Release Manifests uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v0.1.15 diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index 5ebcd1f3438..c0dbfaa762a 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -3,7 +3,7 @@ deployment: image: repository: ${ImageRepository} tag: '${ImageTag}' - imagePullPolicy: IfNotPresent + imagePullPolicy: ${ImagePullPolicy} imagePullSecrets: [] resources: limits: diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index b156702164a..36fe24f6e5b 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -33,8 +33,8 @@ The Helm chart for Envoy Gateway | config.envoyGateway.logging.level.default | string | `"info"` | | | config.envoyGateway.provider.type | string | `"Kubernetes"` | | | createNamespace | bool | `false` | | -| deployment.envoyGateway.image.repository | string | `"${ImageRepository}"` | | -| deployment.envoyGateway.image.tag | string | `"${ImageTag}"` | | +| deployment.envoyGateway.image.repository | string | `"docker.io/envoyproxy/gateway"` | | +| deployment.envoyGateway.image.tag | string | `"latest"` | | | deployment.envoyGateway.imagePullPolicy | string | `"IfNotPresent"` | | | deployment.envoyGateway.imagePullSecrets | list | `[]` | | | deployment.envoyGateway.resources.limits.cpu | string | `"500m"` | | diff --git a/tools/make/common.mk b/tools/make/common.mk index 7c5ffa85cda..d5cc1914911 100644 --- a/tools/make/common.mk +++ b/tools/make/common.mk @@ -119,7 +119,7 @@ export USAGE_OPTIONS .PHONY: generate generate: ## Generate go code from templates and tags -generate: kube-generate helm-generate helm-template go.generate docs-api +generate: kube-generate docs-api helm-generate helm-template go.generate ## help: Show this help info. .PHONY: help diff --git a/tools/make/docs.mk b/tools/make/docs.mk index d280c2c1410..4cec8e458bd 100644 --- a/tools/make/docs.mk +++ b/tools/make/docs.mk @@ -37,7 +37,8 @@ docs-api: docs-api-gen helm-readme-gen docs-api-headings .PHONY: helm-readme-gen helm-readme-gen: $(tools/helm-docs) @$(LOG_TARGET) - $(tools/helm-docs) charts/gateway-helm/ -f values.tmpl.yaml -o api.md + @ImageRepository=docker.io/envoyproxy/gateway ImageTag=latest ImagePullPolicy=IfNotPresent envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml # use production ENV to generate helm api doc + $(tools/helm-docs) charts/gateway-helm/ -f values.yaml -o api.md mv charts/gateway-helm/api.md site/content/en/latest/install/api.md .PHONY: docs-api-gen diff --git a/tools/make/helm.mk b/tools/make/helm.mk index 6687e0fccc3..5ca7d1c8612 100644 --- a/tools/make/helm.mk +++ b/tools/make/helm.mk @@ -4,6 +4,7 @@ include tools/make/env.mk +IMAGE_PULL_POLICY ?= IfNotPresent OCI_REGISTRY ?= oci://docker.io/envoyproxy CHART_NAME ?= gateway-helm CHART_VERSION ?= ${RELEASE_VERSION} @@ -25,8 +26,9 @@ helm-install: helm-generate ## Install envoy gateway helm chart from OCI registr @$(LOG_TARGET) helm install eg ${OCI_REGISTRY}/${CHART_NAME} --version ${CHART_VERSION} -n envoy-gateway-system --create-namespace +.PHONY: helm-generate helm-generate: - ImageRepository=${IMAGE} ImageTag=${TAG} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml + ImageRepository=${IMAGE} ImageTag=${TAG} ImagePullPolicy=${IMAGE_PULL_POLICY} envsubst < charts/gateway-helm/values.tmpl.yaml > ./charts/gateway-helm/values.yaml helm lint charts/gateway-helm helm-template: ## Template envoy gateway helm chart. diff --git a/tools/make/kube.mk b/tools/make/kube.mk index 8d8c96a76d2..eec42ea2395 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -62,8 +62,6 @@ ifndef ignore-not-found ignore-not-found = true endif -IMAGE_PULL_POLICY ?= Always - .PHONY: kube-deploy kube-deploy: manifests helm-generate ## Install Envoy Gateway into the Kubernetes cluster specified in ~/.kube/config. @$(LOG_TARGET) @@ -225,7 +223,7 @@ generate-manifests: helm-generate ## Generate Kubernetes release manifests. @$(LOG_TARGET) @$(call log, "Generating kubernetes manifests") mkdir -p $(OUTPUT_DIR)/ - helm template --set createNamespace=true eg charts/gateway-helm --include-crds --set deployment.envoyGateway.imagePullPolicy=$(IMAGE_PULL_POLICY) --namespace envoy-gateway-system > $(OUTPUT_DIR)/install.yaml + helm template --set createNamespace=true eg charts/gateway-helm --include-crds --namespace envoy-gateway-system > $(OUTPUT_DIR)/install.yaml @$(call log, "Added: $(OUTPUT_DIR)/install.yaml") cp examples/kubernetes/quickstart.yaml $(OUTPUT_DIR)/quickstart.yaml @$(call log, "Added: $(OUTPUT_DIR)/quickstart.yaml") From 59fdb840c78b87e5e77744aa12d2361b4d1bb7a0 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Thu, 2 May 2024 23:15:08 +0200 Subject: [PATCH 28/29] bump github.com/envoyproxy/go-control-plane (#3286) * bump github.com/envoyproxy/go-control-plane Signed-off-by: Matthieu MOREL * Update extproc.go Signed-off-by: Matthieu MOREL --------- Signed-off-by: Matthieu MOREL --- go.mod | 5 +++-- go.sum | 10 ++++++---- internal/xds/translator/cors.go | 8 ++++---- internal/xds/translator/extauth.go | 6 +++--- internal/xds/translator/extproc.go | 3 +-- internal/xds/translator/listener.go | 13 ++++++------- internal/xds/translator/local_ratelimit.go | 9 ++++----- internal/xds/translator/oidc.go | 4 ++-- internal/xds/translator/wasm.go | 4 ++-- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index ba3e100d73a..bd953f83fe5 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( fortio.org/fortio v1.63.7 fortio.org/log v1.12.2 github.com/Masterminds/semver/v3 v3.2.1 - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa + github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b github.com/davecgh/go-spew v1.1.1 - github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc + github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 github.com/evanphx/json-patch/v5 v5.9.0 github.com/fatih/color v1.16.0 @@ -56,6 +56,7 @@ require ( ) require ( + cel.dev/expr v0.15.0 // indirect fortio.org/dflag v1.7.1 // indirect fortio.org/sets v1.0.4 // indirect fortio.org/struct2env v0.4.0 // indirect diff --git a/go.sum b/go.sum index 0d42859e767..e831080cc91 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= +cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -96,8 +98,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -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-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -167,8 +169,8 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc h1:FJoupBhZkbUXmzGxgAic3rEHeZf8jgvREB7uMfBI23w= -github.com/envoyproxy/go-control-plane v0.12.1-0.20240410145647-bdba4bba15fc/go.mod h1:Dj0RQ153G7gNYzcQCihXUreYTQbuJNuL7IT7v9+jTr4= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a h1:OmSlDWdXUzNgoMWOtrcEAmiO9BxTt6cGotwz7cZwIyw= +github.com/envoyproxy/go-control-plane v0.12.1-0.20240425230418-212e93054f1a/go.mod h1:5Wkq+JduFtdAXihLmeTJf+tRYIT4KBc2vPXDhwVo1pA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 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= diff --git a/internal/xds/translator/cors.go b/internal/xds/translator/cors.go index 6090bc21689..f5a83308722 100644 --- a/internal/xds/translator/cors.go +++ b/internal/xds/translator/cors.go @@ -16,8 +16,8 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/wrapperspb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" @@ -125,7 +125,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { allowHeaders string exposeHeaders string maxAge string - allowCredentials *wrappers.BoolValue + allowCredentials *wrapperspb.BoolValue c = irRoute.Security.CORS ) @@ -141,7 +141,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { if c.MaxAge != nil { maxAge = strconv.Itoa(int(c.MaxAge.Seconds())) } - allowCredentials = &wrappers.BoolValue{Value: c.AllowCredentials} + allowCredentials = &wrapperspb.BoolValue{Value: c.AllowCredentials} routeCfgProto := &corsv3.CorsPolicy{ AllowOriginStringMatch: allowOrigins, @@ -150,7 +150,7 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { ExposeHeaders: exposeHeaders, MaxAge: maxAge, AllowCredentials: allowCredentials, - ForwardNotMatchingPreflights: &wrappers.BoolValue{Value: false}, + ForwardNotMatchingPreflights: &wrapperspb.BoolValue{Value: false}, } routeCfgAny, err := anypb.New(routeCfgProto) diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index ead7ceccdf9..0d8edfce242 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -14,8 +14,8 @@ import ( extauthv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" @@ -132,7 +132,7 @@ func extAuthConfig(extAuth *ir.ExtAuth) *extauthv3.ExtAuthz { TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ EnvoyGrpc: grpcService(extAuth.GRPC), }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, @@ -168,7 +168,7 @@ func httpService(http *ir.HTTPExtAuthService) *extauthv3.HttpService { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: http.Destination.Name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, } diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index c31185211d4..9a397484ed9 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -16,7 +16,6 @@ import ( "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" ) @@ -104,7 +103,7 @@ func extProcConfig(extProc ir.ExtProc) *extprocv3.ExternalProcessor { TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ EnvoyGrpc: grpcExtProcService(extProc), }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index af81f20aa89..64004c9460b 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -24,7 +24,6 @@ import ( typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" @@ -85,13 +84,13 @@ func http2ProtocolOptions(opts *ir.HTTP2Settings) *corev3.Http2ProtocolOptions { } return &corev3.Http2ProtocolOptions{ - MaxConcurrentStreams: &wrappers.UInt32Value{ + MaxConcurrentStreams: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.MaxConcurrentStreams, http2MaxConcurrentStreamsLimit), }, - InitialStreamWindowSize: &wrappers.UInt32Value{ + InitialStreamWindowSize: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.InitialStreamWindowSize, http2InitialStreamWindowSize), }, - InitialConnectionWindowSize: &wrappers.UInt32Value{ + InitialConnectionWindowSize: &wrapperspb.UInt32Value{ Value: ptr.Deref(opts.InitialConnectionWindowSize, http2InitialConnectionWindowSize), }, } @@ -251,7 +250,7 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis // Set it by default to also support HTTP1.1 to HTTP2 Upgrades Http2ProtocolOptions: http2ProtocolOptions(irListener.HTTP2), // https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for - UseRemoteAddress: &wrappers.BoolValue{Value: useRemoteAddress}, + UseRemoteAddress: &wrapperspb.BoolValue{Value: useRemoteAddress}, XffNumTrustedHops: xffNumTrustedHops(irListener.ClientIPDetection), OriginalIpDetectionExtensions: originalIPDetectionExtensions, // normalize paths according to RFC 3986 @@ -508,7 +507,7 @@ func buildDownstreamQUICTransportSocket(tlsConfig *ir.TLSConfig) (*corev3.Transp } if tlsConfig.CACertificate != nil { - tlsCtx.DownstreamTlsContext.RequireClientCertificate = &wrappers.BoolValue{Value: true} + tlsCtx.DownstreamTlsContext.RequireClientCertificate = &wrapperspb.BoolValue{Value: true} tlsCtx.DownstreamTlsContext.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ Name: tlsConfig.CACertificate.Name, @@ -548,7 +547,7 @@ func buildXdsDownstreamTLSSocket(tlsConfig *ir.TLSConfig) (*corev3.TransportSock } if tlsConfig.CACertificate != nil { - tlsCtx.RequireClientCertificate = &wrappers.BoolValue{Value: tlsConfig.RequireClientCertificate} + tlsCtx.RequireClientCertificate = &wrapperspb.BoolValue{Value: tlsConfig.RequireClientCertificate} tlsCtx.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ Name: tlsConfig.CACertificate.Name, diff --git a/internal/xds/translator/local_ratelimit.go b/internal/xds/translator/local_ratelimit.go index adbcca6e749..688461e9fa2 100644 --- a/internal/xds/translator/local_ratelimit.go +++ b/internal/xds/translator/local_ratelimit.go @@ -15,9 +15,8 @@ import ( localrlv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/local_ratelimit/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" - "github.com/golang/protobuf/ptypes/duration" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -169,7 +168,7 @@ func (*localRateLimit) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) e // won't consume the default token bucket. This means that a request only // counts towards the default token bucket if it does not match any of the // descriptors. - AlwaysConsumeDefaultTokenBucket: &wrappers.BoolValue{ + AlwaysConsumeDefaultTokenBucket: &wrapperspb.BoolValue{ Value: false, }, } @@ -285,7 +284,7 @@ func buildRouteLocalRateLimits(local *ir.LocalRateLimit) ( return rateLimits, descriptors, nil } -func ratelimitUnitToDuration(unit ir.RateLimitUnit) *duration.Duration { +func ratelimitUnitToDuration(unit ir.RateLimitUnit) *durationpb.Duration { var seconds int64 switch egv1a1.RateLimitUnit(unit) { @@ -298,7 +297,7 @@ func ratelimitUnitToDuration(unit ir.RateLimitUnit) *duration.Duration { case egv1a1.RateLimitUnitDay: seconds = 60 * 60 * 24 } - return &duration.Duration{ + return &durationpb.Duration{ Seconds: seconds, } } diff --git a/internal/xds/translator/oidc.go b/internal/xds/translator/oidc.go index d005f4b4914..183fb7944aa 100644 --- a/internal/xds/translator/oidc.go +++ b/internal/xds/translator/oidc.go @@ -15,8 +15,8 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/ir" @@ -121,7 +121,7 @@ func oauth2Config(oidc *ir.OIDC) (*oauth2v3.OAuth2, error) { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: cluster.name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, diff --git a/internal/xds/translator/wasm.go b/internal/xds/translator/wasm.go index 4d358d707f7..1e096318df8 100644 --- a/internal/xds/translator/wasm.go +++ b/internal/xds/translator/wasm.go @@ -13,8 +13,8 @@ import ( wasmfilterv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" wasmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" - "github.com/golang/protobuf/ptypes/duration" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" "github.com/envoyproxy/gateway/internal/ir" @@ -138,7 +138,7 @@ func wasmConfig(wasm ir.Wasm) (*wasmfilterv3.Wasm, error) { HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: uc.name, }, - Timeout: &duration.Duration{ + Timeout: &durationpb.Duration{ Seconds: defaultExtServiceRequestTimeout, }, }, From 2f916e5490c8f362c2824a2d98c85ef3031ab5ef Mon Sep 17 00:00:00 2001 From: YuLuo Date: Fri, 3 May 2024 10:48:00 +0800 Subject: [PATCH 29/29] chore: remove redundant spaces (#3319) Signed-off-by: yuluo-yx --- tools/make/common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/make/common.mk b/tools/make/common.mk index d5cc1914911..84865267e6c 100644 --- a/tools/make/common.mk +++ b/tools/make/common.mk @@ -26,7 +26,7 @@ RELEASE_VERSION=$(shell cat VERSION) # Set Root Directory Path ifeq ($(origin ROOT_DIR),undefined) -ROOT_DIR := $(abspath $(shell pwd -P)) +ROOT_DIR := $(abspath $(shell pwd -P)) endif # Set Output Directory Path