Skip to content

Instantly share code, notes, and snippets.

@juicemia
Created January 7, 2022 22:12
Show Gist options
  • Save juicemia/7c18b20e73d679350ad12d378a645130 to your computer and use it in GitHub Desktop.
Save juicemia/7c18b20e73d679350ad12d378a645130 to your computer and use it in GitHub Desktop.
{
"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