Created
January 7, 2022 22:12
-
-
Save juicemia/7c18b20e73d679350ad12d378a645130 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "0.0.0.0_8443", | |
"error_state": { | |
"failed_configuration": { | |
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener", | |
"name": "0.0.0.0_8443", | |
"address": { | |
"socket_address": { | |
"address": "0.0.0.0", | |
"port_value": 8443 | |
} | |
}, | |
"filter_chains": [ | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5552.worklayer.io", | |
"*.services.dev-5552.worklayer.io", | |
"api.dev-5552.worklayer.io", | |
"dev-5552.worklayer.io", | |
"go.dev-5552.worklayer.io", | |
"hq.dev-5552.worklayer.io", | |
"portal.dev-5552.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-bvul9anifs-gateway.sb-bvul9anifs" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-bvul9anifs-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5552.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-bvul9anifs-gateway.sb-bvul9anifs" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-bvul9anifs-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-bvul9anifs-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5433.worklayer.io", | |
"*.services.dev-5433.worklayer.io", | |
"api.dev-5433.worklayer.io", | |
"dev-5433.worklayer.io", | |
"go.dev-5433.worklayer.io", | |
"hq.dev-5433.worklayer.io", | |
"portal.dev-5433.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-hrpk4tpsrj-gateway.sb-hrpk4tpsrj" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-hrpk4tpsrj-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5433.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-hrpk4tpsrj-gateway.sb-hrpk4tpsrj" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-hrpk4tpsrj-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-hrpk4tpsrj-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5429.worklayer.io", | |
"*.services.dev-5429.worklayer.io", | |
"api.dev-5429.worklayer.io", | |
"dev-5429.worklayer.io", | |
"go.dev-5429.worklayer.io", | |
"hq.dev-5429.worklayer.io", | |
"portal.dev-5429.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-anwids5nlf-gateway.sb-anwids5nlf" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-anwids5nlf-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5429.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-anwids5nlf-gateway.sb-anwids5nlf" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-anwids5nlf-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-anwids5nlf-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5420.worklayer.io", | |
"*.services.dev-5420.worklayer.io", | |
"api.dev-5420.worklayer.io", | |
"dev-5420.worklayer.io", | |
"go.dev-5420.worklayer.io", | |
"hq.dev-5420.worklayer.io", | |
"portal.dev-5420.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-1yyvnmt0it-gateway.sb-1yyvnmt0it" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-1yyvnmt0it-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5420.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-1yyvnmt0it-gateway.sb-1yyvnmt0it" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-1yyvnmt0it-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-1yyvnmt0it-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5579.worklayer.io", | |
"*.services.dev-5579.worklayer.io", | |
"api.dev-5579.worklayer.io", | |
"dev-5579.worklayer.io", | |
"go.dev-5579.worklayer.io", | |
"hq.dev-5579.worklayer.io", | |
"portal.dev-5579.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-4sd0d3atx8-gateway.sb-4sd0d3atx8" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-4sd0d3atx8-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5579.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-4sd0d3atx8-gateway.sb-4sd0d3atx8" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-4sd0d3atx8-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-4sd0d3atx8-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5433.worklayer.io", | |
"*.services.dev-5433.worklayer.io", | |
"api.dev-5433.worklayer.io", | |
"dev-5433.worklayer.io", | |
"go.dev-5433.worklayer.io", | |
"hq.dev-5433.worklayer.io", | |
"portal.dev-5433.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-oa34yzkjlu-gateway.sb-oa34yzkjlu" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-oa34yzkjlu-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5433.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-oa34yzkjlu-gateway.sb-oa34yzkjlu" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-oa34yzkjlu-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-oa34yzkjlu-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.sb-test-1.worklayer.io", | |
"*.services.sb-test-1.worklayer.io", | |
"api.sb-test-1.worklayer.io", | |
"go.sb-test-1.worklayer.io", | |
"hq.sb-test-1.worklayer.io", | |
"portal.sb-test-1.worklayer.io", | |
"sb-test-1.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-rqfrxkopi9-gateway.sb-rqfrxkopi9" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-rqfrxkopi9-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.sb-test-1.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-rqfrxkopi9-gateway.sb-rqfrxkopi9" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-rqfrxkopi9-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-rqfrxkopi9-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5587.worklayer.io", | |
"*.services.dev-5587.worklayer.io", | |
"api.dev-5587.worklayer.io", | |
"dev-5587.worklayer.io", | |
"go.dev-5587.worklayer.io", | |
"hq.dev-5587.worklayer.io", | |
"portal.dev-5587.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-5z7ij325v2-gateway.sb-5z7ij325v2" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-5z7ij325v2-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5587.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-5z7ij325v2-gateway.sb-5z7ij325v2" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-5z7ij325v2-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-5z7ij325v2-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.dev-5570.worklayer.io", | |
"*.services.dev-5570.worklayer.io", | |
"api.dev-5570.worklayer.io", | |
"dev-5570.worklayer.io", | |
"go.dev-5570.worklayer.io", | |
"hq.dev-5570.worklayer.io", | |
"portal.dev-5570.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-q8byj56kcq-gateway.sb-q8byj56kcq" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-q8byj56kcq-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.dev-5570.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-q8byj56kcq-gateway.sb-q8byj56kcq" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-q8byj56kcq-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-q8byj56kcq-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.fix-milestone-calc.worklayer.io", | |
"*.services.fix-milestone-calc.worklayer.io", | |
"api.fix-milestone-calc.worklayer.io", | |
"fix-milestone-calc.worklayer.io", | |
"go.fix-milestone-calc.worklayer.io", | |
"hq.fix-milestone-calc.worklayer.io", | |
"portal.fix-milestone-calc.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-zs6p7zkmac-gateway.sb-zs6p7zkmac" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-zs6p7zkmac-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.fix-milestone-calc.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-zs6p7zkmac-gateway.sb-zs6p7zkmac" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-zs6p7zkmac-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-zs6p7zkmac-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"*.sb-2ollanl9l5.worklayer.io", | |
"*.services.sb-2ollanl9l5.worklayer.io", | |
"api.sb-2ollanl9l5.worklayer.io", | |
"go.sb-2ollanl9l5.worklayer.io", | |
"hq.sb-2ollanl9l5.worklayer.io", | |
"portal.sb-2ollanl9l5.worklayer.io", | |
"sb-2ollanl9l5.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-443.sb-2ollanl9l5-gateway.sb-2ollanl9l5" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-2ollanl9l5-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
] | |
}, | |
"require_client_certificate": false | |
} | |
} | |
}, | |
{ | |
"filter_chain_match": { | |
"server_names": [ | |
"api.mtls.sb-2ollanl9l5.worklayer.io" | |
] | |
}, | |
"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": "outbound_0.0.0.0_8443", | |
"rds": { | |
"config_source": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
}, | |
"route_config_name": "https.443.https-mtls-443.sb-2ollanl9l5-gateway.sb-2ollanl9l5" | |
}, | |
"http_filters": [ | |
{ | |
"name": "istio.metadata_exchange", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"vm_config": { | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.metadata_exchange" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.cors", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors" | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.fault", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Called on the request path.\nfunction envoy_on_request(request_handle)\n headers = request_handle:headers()\n headers:remove(\"X-Worklayer-Internal\")\nend" | |
} | |
}, | |
{ | |
"name": "envoy.lua", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", | |
"inline_code": "-- Json Parsing based on https://gist.github.com/tylerneylon/59f4bcf316be525b30ab\n-- Base64 decoding based on wikipedia description of 8/6bit encoding.\n-- base64 char array.. note final 2 chars are for RFC4648-URL encoding\n-- as per JWT spec section 2 terminology 'Base64url Encoding'\nlocal alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'\n-- convert to 6 char long binary string. (max int 64!)\nfunction toBinaryString(int)\n if int \u003e 64 then\n error(\"Bad number \" .. int .. \" to convert to binary\")\n end\n local remaining = tonumber(int)\n local bits = ''\n for i = 5, 0, -1 do\n local pow = 2 ^ i\n if remaining \u003e= pow then\n bits = bits .. '1'\n remaining = remaining - pow\n else\n bits = bits .. '0'\n end\n end\n return bits\nend\nfunction fromBinaryString(bits)\n return tonumber(bits, 2)\nend\nfunction decodeBase64(encoded)\n local bitstr = ''\n local decoded = ''\n -- decode chars into bitstring\n for i = 1, string.len(encoded) do\n local offset, _ = string.find(alpha, string.sub(encoded, i, i))\n if offset == nil then\n error(\"Bad base64 character \" .. string.sub(encoded, i, i))\n end\n bitstr = bitstr .. toBinaryString(offset - 1)\n end\n -- decode bitstring back to chars\n for i = 1, string.len(bitstr), 8 do\n decoded = decoded .. string.char(fromBinaryString(string.sub(bitstr, i, i + 7)))\n end\n return decoded\nend\n-- json handling \nlocal json = {}\n-- Returns pos, did_find; there are two cases:\n-- 1. Delimiter found: pos = pos after leading space + delim; did_find = true.\n-- 2. Delimiter not found: pos = pos after leading space; did_find = false.\n-- This throws an error if err_if_missing is true and the delim is not found.\nlocal function skip_delim(str, pos, delim, err_if_missing)\n pos = pos + #str:match('^%s*', pos)\n if str:sub(pos, pos) ~= delim then\n if err_if_missing then\n error('Expected ' .. delim .. ' near position ' .. pos)\n end\n return pos, false\n end\n return pos + 1, true\nend\n-- Expects the given pos to be the first character after the opening quote.\n-- Returns val, pos; the returned pos is after the closing quote character.\nlocal function parse_str_val(str, pos, val)\n val = val or ''\n local early_end_error = 'End of input found while parsing string.'\n if pos \u003e #str then\n error(early_end_error)\n end\n local c = str:sub(pos, pos)\n if c == '\"' then\n return val, pos + 1\n end\n if c ~= '\\\\' then\n return parse_str_val(str, pos + 1, val .. c)\n end\n -- We must have a \\ character.\n local esc_map = {\n b = '\\b',\n f = '\\f',\n n = '\\n',\n r = '\\r',\n t = '\\t'\n }\n local nextc = str:sub(pos + 1, pos + 1)\n if not nextc then\n error(early_end_error)\n end\n return parse_str_val(str, pos + 2, val .. (esc_map[nextc] or nextc))\nend\n-- Returns val, pos; the returned pos is after the number's final character.\nlocal function parse_num_val(str, pos)\n local num_str = str:match('^-?%d+%.?%d*[eE]?[+-]?%d*', pos)\n local val = tonumber(num_str)\n if not val then\n error('Error parsing number at position ' .. pos .. '.')\n end\n return val, pos + #num_str\nend\njson.null = {} -- one-off table to represent the null value.\nfunction json.parse(str, pos, end_delim)\n pos = pos or 1\n if pos \u003e #str then\n error('Reached unexpected end of input.')\n end\n local pos = pos + #str:match('^%s*', pos) -- Skip whitespace.\n local first = str:sub(pos, pos)\n if first == '{' then -- Parse an object.\n local obj, key, delim_found = {}, true, true\n pos = pos + 1\n while true do\n key, pos = json.parse(str, pos, '}')\n if key == nil then\n return obj, pos\n end\n if not delim_found then\n error('Comma missing between object items.')\n end\n pos = skip_delim(str, pos, ':', true) -- true -\u003e error if missing.\n obj[key], pos = json.parse(str, pos)\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '[' then -- Parse an array.\n local arr, val, delim_found = {}, true, true\n pos = pos + 1\n while true do\n val, pos = json.parse(str, pos, ']')\n if val == nil then\n return arr, pos\n end\n if not delim_found then\n error('Comma missing between array items.')\n end\n arr[#arr + 1] = val\n pos, delim_found = skip_delim(str, pos, ',')\n end\n elseif first == '\"' then -- Parse a string.\n return parse_str_val(str, pos + 1)\n elseif first == '-' or first:match('%d') then -- Parse a number.\n return parse_num_val(str, pos)\n elseif first == end_delim then -- End of an object or array.\n return nil, pos + 1\n else -- Parse true, false, or null.\n local literals = {\n ['true'] = true,\n ['false'] = false,\n ['null'] = json.null\n }\n for lit_str, lit_val in pairs(literals) do\n local lit_end = pos + #lit_str - 1\n if str:sub(pos, lit_end) == lit_str then\n return lit_val, lit_end + 1\n end\n end\n local pos_info_str = 'position ' .. pos .. ': ' .. str:sub(pos, pos + 10)\n error('Invalid json syntax starting at ' .. pos_info_str)\n end\nend\nfunction decode_jwt(jwt)\n i = 0\n result = {}\n for match in (jwt .. '.'):gmatch(\"(.-)%.\") do\n result[i] = decodeBase64(match)\n i = i + 1\n end\n -- header\n head = json.parse(result[0])\n -- claims\n claims = json.parse(result[1])\n return {\n head = head,\n claims = claims\n }\nend\nfunction decode_url(s)\n s = s:gsub('+', ' '):gsub('%%(%x%x)', function(h)\n return string.char(tonumber(h, 16))\n end)\n return s\nend\nfunction parse_url(s)\n local ans = {}\n for k, v in s:gmatch('([^&=?]-)=([^&=?]+)') do\n ans[k] = decode_url(v)\n end\n return ans\nend\nfunction envoy_on_request(request_handle)\n local jwtHeaderName = \"Authorization\"\n headers = request_handle:headers()\n jwt = headers:get(jwtHeaderName)\n aud = nil\n if jwt ~= nil then\n content = decode_jwt(jwt.gsub(jwt, \"Bearer \", \"\"))\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n else\n local path = headers:get(\":path\")\n local query_params = parse_url(path)\n if query_params ~= nil and query_params[\"__authorization\"] ~= nil then\n content = decode_jwt(query_params[\"__authorization\"])\n claims = content[\"claims\"]\n aud = claims[\"aud\"]\n end\n end\n if aud == \"https://internal.worklayer.com\" then\n request_handle:respond({\n [\":status\"] = \"403\"\n }, \"{\\\"message\\\": \\\"Bad token audience.\\\"}\")\n end\nend\n" | |
} | |
}, | |
{ | |
"name": "istio.stats", | |
"typed_config": { | |
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct", | |
"type_url": "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm", | |
"value": { | |
"config": { | |
"root_id": "stats_outbound", | |
"vm_config": { | |
"vm_id": "stats_outbound", | |
"runtime": "envoy.wasm.runtime.null", | |
"code": { | |
"local": { | |
"inline_string": "envoy.wasm.stats" | |
} | |
} | |
}, | |
"configuration": { | |
"@type": "type.googleapis.com/google.protobuf.StringValue", | |
"value": "{\n \"debug\": \"false\",\n \"stat_prefix\": \"istio\",\n \"disable_host_header_fallback\": true,\n \"metrics\": [\n {\n \"dimensions\": {\n \"source_cluster\": \"node.metadata['CLUSTER_ID']\",\n \"destination_cluster\": \"upstream_peer.cluster_id\"\n }\n }\n ]\n}\n" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"name": "envoy.filters.http.router", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" | |
} | |
} | |
], | |
"tracing": { | |
"client_sampling": { | |
"value": 100 | |
}, | |
"random_sampling": { | |
"value": 1 | |
}, | |
"overall_sampling": { | |
"value": 100 | |
}, | |
"custom_tags": [ | |
{ | |
"tag": "istio.canonical_revision", | |
"environment": { | |
"name": "CANONICAL_REVISION", | |
"default_value": "latest" | |
} | |
}, | |
{ | |
"tag": "istio.canonical_service", | |
"environment": { | |
"name": "CANONICAL_SERVICE", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.mesh_id", | |
"environment": { | |
"name": "ISTIO_META_MESH_ID", | |
"default_value": "unknown" | |
} | |
}, | |
{ | |
"tag": "istio.namespace", | |
"environment": { | |
"name": "POD_NAMESPACE", | |
"default_value": "default" | |
} | |
} | |
] | |
}, | |
"http_protocol_options": {}, | |
"server_name": "nunya business", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
], | |
"use_remote_address": true, | |
"forward_client_cert_details": "SANITIZE_SET", | |
"set_current_client_cert_details": { | |
"subject": true, | |
"cert": true, | |
"dns": true, | |
"uri": true | |
}, | |
"upgrade_configs": [ | |
{ | |
"upgrade_type": "websocket" | |
} | |
], | |
"stream_idle_timeout": "0s", | |
"normalize_path": true, | |
"path_with_escaped_slashes_action": "KEEP_UNCHANGED" | |
} | |
} | |
], | |
"transport_socket": { | |
"name": "envoy.transport_sockets.tls", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", | |
"common_tls_context": { | |
"tls_params": { | |
"tls_minimum_protocol_version": "TLSv1_2", | |
"cipher_suites": [ | |
"ECDHE-ECDSA-AES128-GCM-SHA256", | |
"ECDHE-ECDSA-AES256-GCM-SHA384", | |
"ECDHE-ECDSA-CHACHA20-POLY1305", | |
"ECDHE-RSA-AES128-GCM-SHA256", | |
"ECDHE-RSA-AES256-GCM-SHA384", | |
"ECDHE-RSA-CHACHA20-POLY1305" | |
] | |
}, | |
"alpn_protocols": [ | |
"h2", | |
"http/1.1" | |
], | |
"tls_certificate_sds_secret_configs": [ | |
{ | |
"name": "kubernetes://sb-2ollanl9l5-gateway-cert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
], | |
"combined_validation_context": { | |
"default_validation_context": {}, | |
"validation_context_sds_secret_config": { | |
"name": "kubernetes://sb-2ollanl9l5-gateway-cert-cacert", | |
"sds_config": { | |
"ads": {}, | |
"resource_api_version": "V3" | |
} | |
} | |
} | |
}, | |
"require_client_certificate": true | |
} | |
} | |
} | |
], | |
"listener_filters": [ | |
{ | |
"name": "envoy.filters.listener.tls_inspector", | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector" | |
} | |
} | |
], | |
"traffic_direction": "OUTBOUND", | |
"access_log": [ | |
{ | |
"name": "envoy.access_loggers.file", | |
"filter": { | |
"response_flag_filter": { | |
"flags": [ | |
"NR" | |
] | |
} | |
}, | |
"typed_config": { | |
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog", | |
"path": "/dev/stdout", | |
"log_format": { | |
"json_format": { | |
"authority": "%REQ(:AUTHORITY)%", | |
"grpc_status": "%GRPC_STATUS%", | |
"hostname": "%HOSTNAME%", | |
"message": "%RESPONSE_CODE% %REQ(:METHOD)% %REQ(:AUTHORITY)%%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"method": "%REQ(:METHOD)%", | |
"path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", | |
"protocol": "%PROTOCOL%", | |
"requested_server_name": "%REQUESTED_SERVER_NAME%", | |
"response_code": "%RESPONSE_CODE%", | |
"response_flags": "%RESPONSE_FLAGS%", | |
"severity": "INFO", | |
"start_time": "%START_TIME%", | |
"upstream_host": "%UPSTREAM_HOST%", | |
"upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%", | |
"user_agent": "%REQ(USER-AGENT)%" | |
} | |
} | |
} | |
} | |
] | |
}, | |
"last_update_attempt": "2022-01-07T22:04:20.807Z", | |
"details": "error adding listener '0.0.0.0:8443': filter chain '' has the same matching rules defined as ''" | |
} | |
}, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment