Skip to content

Instantly share code, notes, and snippets.

@terrancesnyder
Created August 8, 2024 15:20
Show Gist options
  • Save terrancesnyder/636060bb222f5caefd6c9969b4fc319e to your computer and use it in GitHub Desktop.
Save terrancesnyder/636060bb222f5caefd6c9969b4fc319e to your computer and use it in GitHub Desktop.
Enable envoyfilter to inject a common workload id sourced from env, jwt and mtls with a priority of (1) jwt, (2) mtls and (3) env.
kubectl apply -n gateways -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: lua-filter-example
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: ANY # Adjust if needed for your use case
patch:
operation: INSERT_BEFORE
value: # lua filter specification
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
inlineCode: |
JSON = (loadfile "/var/lib/lua/JSON.lua")() -- one-time load of the routines
-- Custom base64 decoding function
local function base64_decode(input)
local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
input = input:gsub('[^'..b..'=]', '')
return (input:gsub('.', function(x)
if (x == '=') then return '' end
local r, f = '', (b:find(x) - 1)
for i = 6, 1, -1 do r = r .. (f % 2 ^ i - f % 2 ^ (i - 1) > 0 and '1' or '0') end
return r;
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
if (#x ~= 8) then return '' end
local c = 0
for i = 1, 8 do c = c + (x:sub(i, i) == '1' and 2 ^ (8 - i) or 0) end
return string.char(c)
end))
end
function envoy_on_request(request_handle)
function isempty(s)
return s == nil or s == ''
end
local WORKLOAD_ID = ""
local WORKLOAD_ID_SOURCE = ""
-- grab workload identifier from environment by default
local request_headers = request_handle:headers()
WORKLOAD_ID = os.getenv("ISTIO_META_WORKLOAD_NAME")
WORKLOAD_ID_SOURCE = "ISTIO_META_WORKLOAD_NAME"
if isempty(WORKLOAD_ID) then
WORKLOAD_ID = os.getenv("CANONICAL_SERVICE")
WORKLOAD_ID_SOURCE = "CANONICAL_SERVICE"
end
if isempty(WORKLOAD_ID) then
WORKLOAD_ID = os.getenv("POD_NAMESPACE")
WORKLOAD_ID_SOURCE = "POD_NAMESPACE"
end
request_headers:add("x-envoy-filter-version", "v9.0.2")
-- see if JWT token was used if so default to that for workload ID
local auth_header = request_headers:get("Authorization")
if auth_header then
local token = auth_header:match("Bearer%s+(.+)")
if token then
local header, payload, signature = token:match("([^%.]+)%.([^%.]+)%.([^%.]+)")
if payload then
local json_raw_text = base64_decode(payload)
local json_value = JSON:decode(json_raw_text)
if json_value["azp"] ~= nil then
WORKLOAD_ID = json_value["azp"]
WORKLOAD_ID_SOURCE = "JWT"
end
end
end
end
if not isempty(WORKLOAD_ID) then
request_headers:replace("x-workload-name", WORKLOAD_ID)
request_headers:replace("x-workload-source", WORKLOAD_ID_SOURCE)
end
end
EOF
@terrancesnyder
Copy link
Author

Note that you need to add the config map to enable this.

https://gist.github.com/terrancesnyder/cdc5c4e533a33b13ba0a1801bace7740

Grab this and run kubectl apply -f lua.yaml

Then modify your namespace to include this configmap and attach to your volume. For example

Ref: https://github.com/ibm-cloud-architecture/tutorial-istio-envoy-lua-filters/tree/master

Edit the gate config and add the volumes. Note you need to regenerate this everytime files or things change.

kubectl edit deployment httpbin-8080-gateway-istio -n gateways

Add the volumenMounts in the corresponding section in the container proxy

        volumeMounts:
        - mountPath: /var/lib/lua
          name: config-volume-lua

Add the volume in the corresponding section in the container proxy

      volumes:
      - name: config-volume-lua
        configMap:
          name: lua-libs
          items:
          - key: JSON.lua
            path: JSON.lua
          - key: uuid.lua
            path: uuid.lua
          - key: base64.lua
            path: base64.lua

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment