apiVersion: v1 kind: ConfigMap metadata: name: envoy-config namespace: juwan data: envoy.yaml: | static_resources: listeners: - name: http_listener address: socket_address: address: 0.0.0.0 port_value: 8080 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: gozero_services domains: ["*"] routes: - match: prefix: "/" route: cluster: user-api http_filters: - name: envoy.filters.http.lua typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua inline_code: | math.randomseed(os.time()) local function is_safe(method) return method == "GET" or method == "HEAD" or method == "OPTIONS" end local function parse_cookie(cookie_header) if not cookie_header then return nil end for cookie in string.gmatch(cookie_header, "([^;]+)") do local k, v = cookie:match("^%s*([^=]+)=?(.*)$") if k == "csrf_token" then return v end end return nil end local function random_token() local t = {} for i = 1, 32 do t[i] = string.format("%x", math.random(0, 15)) end return table.concat(t) end function envoy_on_request(request_handle) local headers = request_handle:headers() local method = headers:get(":method") or "" local cookie = parse_cookie(headers:get("cookie")) local csrf_header = headers:get("x-csrf-token") if is_safe(method) then if not cookie then local token = random_token() request_handle:streamInfo():dynamicMetadata():set("csrf", "token", token) end return end if not cookie or not csrf_header or cookie ~= csrf_header then request_handle:respond({[":status"] = "403"}, "CSRF validation failed") return end end function envoy_on_response(response_handle) local md = response_handle:streamInfo():dynamicMetadata():get("csrf") or {} local token = md["token"] if token then response_handle:headers():add("set-cookie", "csrf_token=" .. token .. "; Path=/; SameSite=Strict") end end - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: user-api connect_timeout: 2s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: user-api endpoints: - lb_endpoints: - endpoint: address: socket_address: address: user-api-svc.juwan.svc.cluster.local port_value: 8888 --- apiVersion: apps/v1 kind: Deployment metadata: name: envoy-gateway namespace: juwan labels: app: envoy-gateway spec: replicas: 1 selector: matchLabels: app: envoy-gateway template: metadata: labels: app: envoy-gateway spec: containers: - name: envoy image: envoyproxy/envoy:v1.32.2 args: - "-c" - "/etc/envoy/envoy.yaml" - "--log-level" - "info" ports: - name: http containerPort: 8080 volumeMounts: - name: config mountPath: /etc/envoy volumes: - name: config configMap: name: envoy-config --- apiVersion: v1 kind: Service metadata: name: envoy-gateway namespace: juwan spec: type: ClusterIP selector: app: envoy-gateway ports: - name: http port: 80 targetPort: 8080