diff --git a/infrastructure/istio-config/yc-k8s-test/istio-config.yaml b/infrastructure/istio-config/yc-k8s-test/istio-config.yaml index 5bf9fc8..93971b2 100644 --- a/infrastructure/istio-config/yc-k8s-test/istio-config.yaml +++ b/infrastructure/istio-config/yc-k8s-test/istio-config.yaml @@ -102,6 +102,28 @@ spec: istio: requestAuthentications: api-jwt: + namespace: istio-system + selector: + matchLabels: + istio: ingressgateway + jwtRules: + - issuer: django + jwks: | + { + "keys": [{ + "kty": "RSA", + "kid": "tiSFtZhCeHtAmHjjY3cG55ZYRgpTnIbAdmX1DsD8GOk=", + "use": "sig", + "alg": "RS512", + "n": "iJxequyGx7cS2MKqYBlyFXsrN5mhvKKyMeYFYW2XbvCiVRXVs0OK7gwvmhMRR-spCTxJLrG2rxzvs0CBXEFIrvmVRpXSLAau_aRAoTxmfCTqsZWb9ZT7u2i3_itUgFZmQg9UsuKoSodLJ16mf29XLE6VRqlu9oIxTB61FN5WtJ8ML7-lS00UBNYbemD8iVVFTHdn_v-uJ9blhg-2l-SPaJmwFlYlr8Zll99NXhw0-SNRzYTKJ04B1SIlebkuyTpvKbeGwnA6sPainH26MQ88DJIueRpJy_zgDWYoQBO7JAxbxJnF5A5RWeWDqodZU0FPkuNyQM8RI20j83GPI-X4FvTJNXKoBVgWNpq0yvxbwcFo0GdXDkXu8FPxBjCmh0yQnz-C_3SWcQ6gM1e9ryypoi4IJzR9KIlo7c39VTK4K70lx6piEtR_Cl3LldnHVhztAPEQr58e9cIrStax3EzwMijS6eFPf21vZNIpgs96XoZGBXvbtRJJx8uqbYSjO4uofgJWkIrjleO-ygD1MpTe7Opr_5h7-DfywrgBNbstskCecSbEgCv0Hblx55JCZcb_lL6hT5cJRXOybFEmIGRpGZTR-eUELrI1cqP62Tf3qvUyNeOPi9WE2lDCJtsF1gya64xWTi1nxSXdCJEZGjKyGFHg_Majf2RzyzsYuX90P5c", + "e": "AQAB" + }] + } + forwardOriginalToken: true + outputClaims: + user_id: x-user-id + company_ids: x-company-ids + zitadel-jwks: namespace: istio-system selector: matchLabels: @@ -153,6 +175,427 @@ spec: - system-log - transmittal - workspaces + envoyFilters: + http-header-count-size-control: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: NETWORK_FILTER + match: + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + patch: + operation: MERGE + value: + typed_config: + '@type': >- + type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + common_http_protocol_options: + max_headers_count: 200 + max_request_headers_kb: 96 + header-size-sidecar: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_INBOUND + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + patch: + operation: MERGE + value: + typed_config: + '@type': >- + type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + common_http_protocol_options: + max_headers_kb: 96 + max_request_headers_kb: 96 + - applyTo: NETWORK_FILTER + match: + context: SIDECAR_OUTBOUND + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + patch: + operation: MERGE + value: + typed_config: + '@type': >- + type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + common_http_protocol_options: + max_headers_kb: 96 + max_request_headers_kb: 96 + sarex-agents-upload-body-50mb: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + sni: sarex.contour.infra.sarex.tech + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.router + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.buffer + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer + max_request_bytes: 2147483648 + x-robots-tag-noindex: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: VIRTUAL_HOST + match: + context: GATEWAY + routeConfiguration: + vhost: + name: sarex.contour.infra.sarex.tech:443 + patch: + operation: MERGE + value: + response_headers_to_add: + - append: false + header: + key: X-Robots-Tag + value: noindex, nofollow + - applyTo: VIRTUAL_HOST + match: + context: GATEWAY + routeConfiguration: + vhost: + name: dashboard.contour.infra.sarex.tech:443 + patch: + operation: MERGE + value: + response_headers_to_add: + - append: false + header: + key: X-Robots-Tag + value: noindex, nofollow + - applyTo: VIRTUAL_HOST + match: + context: GATEWAY + routeConfiguration: + vhost: + name: sarex.contour.infra.sarex.tech:80 + patch: + operation: MERGE + value: + response_headers_to_add: + - append: false + header: + key: X-Robots-Tag + value: noindex, nofollow + - applyTo: VIRTUAL_HOST + match: + context: GATEWAY + routeConfiguration: + vhost: + name: dashboard.contour.infra.sarex.tech:80 + patch: + operation: MERGE + value: + response_headers_to_add: + - append: false + header: + key: X-Robots-Tag + value: noindex, nofollow + strip-jwt-on-public-hosts: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.jwt_authn + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.lua + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + inlineCode: | + local public_hosts = { + ["camunda-keycloak.contour.infra.sarex.tech"] = true, + ["keycloak.contour.infra.sarex.tech"] = true, + ["zitadel.contour.infra.sarex.tech"] = true, + ["dashboard.contour.infra.sarex.tech"] = true, + ["openobserve.contour.infra.sarex.tech"] = true, + } + + local public_paths = { + "^/documentations/api/v1/public/qr", + "^/documentations/api/v1/public/documents/public_link", + } + + local function is_public(host, path) + if not host then return false end + host = string.gsub(host, ":%d+$", "") + if public_hosts[host] then + return true + end + if path then + for _,pref in ipairs(public_paths) do + if string.find(path, pref) == 1 then + return true + end + end + end + return false + end + + function envoy_on_request(handle) + local h = handle:headers() + local host = h:get(":authority") + local path = h:get(":path") + if is_public(host, path) then + local auth = h:get("authorization") + if auth then + h:replace("x-orig-authorization", auth) + h:remove("authorization") + end + end + end + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.jwt_authn + patch: + operation: INSERT_AFTER + value: + name: envoy.filters.http.lua + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + inlineCode: | + function envoy_on_request(handle) + local h = handle:headers() + local xauth = h:get("x-orig-authorization") + if xauth and not h:get("authorization") then + h:replace("authorization", xauth) + h:remove("x-orig-authorization") + end + end + strip-jwt-on-public-paths: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.jwt_authn + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.lua + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + inlineCode: | + local public_prefixes = { + "^/documentations/api/v1/public/qr", + "^/documentations/api/v1/public/documents/public_link" + } + + local download_prefixes = { + "^/files/api/v1/documents/folders", + "^/files/api/v1/documents", + "^/files/api/v1/bundles" + } + + local function starts_with_any(path, prefixes) + for _, pref in ipairs(prefixes) do + if string.find(path, pref) == 1 then + return true + end + end + return false + end + + local function has_download_type(path) + if not path or path == "" then + return false + end + return string.match(path, "[%?&]download_type=") ~= nil + end + + local function should_strip(path) + if not path then + return false + end + + if starts_with_any(path, public_prefixes) then + return true + end + + if starts_with_any(path, download_prefixes) and has_download_type(path) then + return true + end + + return false + end + + function envoy_on_request(handle) + local h = handle:headers() + local p = h:get(":path") or "" + + if should_strip(p) then + local auth = h:get("authorization") + if auth then + h:replace("x-orig-authorization-public-paths", auth) + h:remove("authorization") + end + + local identity = h:get("identity") + if identity then + h:replace("x-orig-identity-public-paths", identity) + h:remove("identity") + end + + h:replace("x-jwt-stripped-public-paths", "1") + end + end + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + subFilter: + name: envoy.filters.http.jwt_authn + patch: + operation: INSERT_AFTER + value: + name: envoy.filters.http.lua + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua + inlineCode: | + function envoy_on_request(handle) + local h = handle:headers() + local stripped = h:get("x-jwt-stripped-public-paths") + + if stripped == "1" then + local xauth = h:get("x-orig-authorization-public-paths") + if xauth and not h:get("authorization") then + h:replace("authorization", xauth) + end + h:remove("x-orig-authorization-public-paths") + + local xidentity = h:get("x-orig-identity-public-paths") + if xidentity and not h:get("identity") then + h:replace("identity", xidentity) + end + h:remove("x-orig-identity-public-paths") + + h:remove("x-jwt-stripped-public-paths") + end + end + cors-json-401: + namespace: istio-system + workloadSelector: + labels: + istio: ingressgateway + configPatches: + - applyTo: HTTP_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.http.jwt_authn + patch: + operation: INSERT_BEFORE + value: + name: envoy.filters.http.cors + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors + cors: + allow_credentials: true + allow_headers: "Authorization,Content-Type" + allow_methods: "GET,POST,PUT,PATCH,DELETE,OPTIONS" + allow_origin_string_match: + - safe_regex: + regex: https://.*\.sarex\.io + - safe_regex: + regex: https://.*\.contour\.infra\.sarex\.tech + - safe_regex: + regex: https://localhost:.* + max_age: "86400" + - applyTo: NETWORK_FILTER + match: + context: GATEWAY + listener: + filterChain: + filter: + name: envoy.filters.network.http_connection_manager + patch: + operation: MERGE + value: + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + local_reply_config: + mappers: + - body: + inline_string: | + {"error":"unauthorized","detail":"Invalid or expired token"} + filter: + status_code_filter: + comparison: + op: EQ + value: + default_value: 401 + runtime_key: default + headers_to_add: + - append_action: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: Content-Type + value: application/json + - append_action: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: Access-Control-Allow-Origin + value: '%REQ(Origin)%' + - append_action: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: Access-Control-Allow-Credentials + value: 'true' gateways: platform: name: platform-gateway