Run Lua scripts in Envoy proxy
The Lua Envoy extension enables the HTTP Lua filter in your Consul Envoy proxies, letting you run Lua scripts when requests and responses pass through Consul-generated Envoy resources.
Envoy filters support setting and getting dynamic metadata, allowing a filter to share state information with subsequent filters. To set dynamic metadata, configure the HTTP Lua filter. Users can call streamInfo:dynamicMetadata()
from Lua scripts to get the request’s dynamic metadata.
Configuration specifications
To use the Lua Envoy extension, configure the following arguments in the EnvoyExtensions
block:
- ProxyType: string |
connect-proxy
- Determines the proxy type the extension applies to. The only supported value isconnect-proxy
. - ListenerType: string | required - Specifies if the extension is applied to the
inbound
oroutbound
listener. - Script: string | required - The Lua script that is configured to run by the HTTP Lua filter.
Workflow
There are two steps to configure the Lua Envoy extension:
- Configure EnvoyExtensions through
service-defaults
orproxy-defaults
. - Apply the configuration entry.
Configure EnvoyExtensions
To use Envoy extensions, you must configure and apply a proxy-defaults
or service-defaults
configuration entry with the Envoy extension.
- When you configure Envoy extensions on
proxy-defaults
, they apply to every service. - When you configure Envoy extensions on
service-defaults
, they apply to a specific service.
Consul applies Envoy extensions configured in proxy-defaults
before it applies extensions in service-defaults
. As a result, the Envoy extension configuration in service-defaults
may override configurations in proxy-defaults
.
The following example configures the Lua Envoy extension on every service by using the proxy-defaults
.
lua-envoy-extension-proxy-defaults.hcl
Kind = "proxy-defaults"
Name = "global"
Protocol = "http"
EnvoyExtensions {
Name = "builtin/lua"
Arguments = {
ProxyType = "connect-proxy"
Listener = "inbound"
Script = <<-EOS
function envoy_on_request(request_handle)
meta = request_handle:streamInfo():dynamicMetadata()
m = meta:get("consul")
request_handle:headers():add("x-consul-service", m["service"])
request_handle:headers():add("x-consul-namespace", m["namespace"])
request_handle:headers():add("x-consul-datacenter", m["datacenter"])
request_handle:headers():add("x-consul-trust-domain", m["trust-domain"])
end
EOS
}
}
lua-envoy-extension-proxy-defaults.json
{
"kind": "proxy-defaults",
"name": "global",
"protocol": "http",
"envoy_extensions": [{
"name": "builtin/lua",
"arguments": {
"proxy_type": "connect-proxy",
"listener": "inbound",
"script": "function envoy_on_request(request_handle)\nmeta = request_handle:streamInfo():dynamicMetadata()\nm = \nmeta:get("consul")\nrequest_handle:headers():add("x-consul-service", m["service"])\nrequest_handle:headers():add("x-consul-namespace", m["namespace"])\nrequest_handle:headers():add("x-consul-datacenter", m["datacenter"])\nrequest_handle:headers():add("x-consul-trust-domain", m["trust-domain"])\nend"
}
}]
}
lua-envoy-extension-proxy-defaults.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ProxyDefaults
metadata:
name: global
spec:
protocol: http
envoyExtensions:
name = "builtin/lua"
arguments:
proxyType: "connect-proxy"
listener: "inbound"
script: |-
function envoy_on_request(request_handle)
meta = request_handle:streamInfo():dynamicMetadata()
m = meta:get("consul")
request_handle:headers():add("x-consul-service", m["service"])
request_handle:headers():add("x-consul-namespace", m["namespace"])
request_handle:headers():add("x-consul-datacenter", m["datacenter"])
request_handle:headers():add("x-consul-trust-domain", m["trust-domain"])
end
For a full list of parameters for EnvoyExtensions
, refer to the service-defaults and proxy-defaults configuration entries reference documentation.
Warning: Applying EnvoyExtensions
to ProxyDefaults
may produce unintended consequences. We recommend enabling EnvoyExtensions
with ServiceDefaults
in most cases.
Refer to Configuration specification section to find a full list of arguments for the Lua Envoy extension.
Apply the configuration entry
Apply the proxy-defaults
or service-defaults
configuration entry.
$ consul config write lua-envoy-extension-proxy-defaults.hcl
$ consul config write lua-envoy-extension-proxy-defaults.json
$ kubectl apply lua-envoy-extension-proxy-defaults.yaml
Examples
In the following example, the service-defaults
configure the Lua Envoy extension to insert the HTTP Lua filter for service myservice
and add the Consul service name to thex-consul-service
header for all inbound requests. The ListenerType
makes it so that the extension applies only on the inbound listener of the service’s connect proxy.
lua-envoy-extension.hcl
Kind = "service-defaults"
Name = "myservice"
EnvoyExtensions = [
{
Name = "builtin/lua"
Arguments = {
ProxyType = "connect-proxy"
Listener = "inbound"
Script = <<EOF
function envoy_on_request(request_handle)
local service = request_handle:streamInfo():dynamicMetadata():get("consul")["service"]
request_handle:headers():add("x-consul-service", service)
end
EOF
}
}
]
Alternatively, you can apply the same extension configuration to proxy-defaults configuration entries.
You can also specify multiple Lua filters through the Envoy extensions. They will not override each other.
lua-envoy-extension.hcl
Kind = "service-defaults"
Name = "myservice"
EnvoyExtensions = [
{
Name = "builtin/lua",
Arguments = {
ProxyType = "connect-proxy"
Listener = "inbound"
Script = <<-EOF
function envoy_on_request(request_handle)
meta = request_handle:streamInfo():dynamicMetadata()
m = meta:get("consul")
request_handle:headers():add("x-consul-datacenter", m["datacenter1"])
end
EOF
}
},
{
Name = "builtin/lua",
Arguments = {
ProxyType = "connect-proxy"
Listener = "inbound"
Script = <<-EOF
function envoy_on_request(request_handle)
meta = request_handle:streamInfo():dynamicMetadata()
m = meta:get("consul")
request_handle:headers():add("x-consul-datacenter", m["datacenter2"])
end
EOF
}
}
]