Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kabute/ef8e7198031c8a99212a629a139ac83f to your computer and use it in GitHub Desktop.
Save kabute/ef8e7198031c8a99212a629a139ac83f to your computer and use it in GitHub Desktop.
This (Istio) Envoy filter will automatically add the recommended HTTP Security headers to all the responses
# This (Istio) Envoy filter will automatically add the
# recommended HTTP Security headers - https://securityheaders.com/
#
# Just: kubectl apply -f istio-security-by-default-header-filter.yaml
#
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: security-by-default-header-filter
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.lua
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
inlineCode: |
function envoy_on_response(response_handle)
function hasFrameAncestors(rh)
s = rh:headers():get("Content-Security-Policy");
delimiter = ";";
defined = false;
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
match = match:gsub("%s+", "");
if match:sub(1, 15)=="frame-ancestors" then
return true;
end
end
return false;
end
if not response_handle:headers():get("Content-Security-Policy") then
csp = "frame-ancestors none;";
response_handle:headers():add("Content-Security-Policy", csp);
elseif response_handle:headers():get("Content-Security-Policy") then
if not hasFrameAncestors(response_handle) then
csp = response_handle:headers():get("Content-Security-Policy");
csp = csp .. ";frame-ancestors none;";
response_handle:headers():replace("Content-Security-Policy", csp);
end
end
if not response_handle:headers():get("Strict-Transport-Security") then
response_handle:headers():add("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
end
if not response_handle:headers():get("X-Frame-Options") then
response_handle:headers():add("X-Frame-Options", "deny");
end
if not response_handle:headers():get("X-XSS-Protection") then
response_handle:headers():add("X-XSS-Protection", "1; mode=block");
end
if not response_handle:headers():get("X-Content-Type-Options") then
response_handle:headers():add("X-Content-Type-Options", "nosniff");
end
if not response_handle:headers():get("Referrer-Policy") then
response_handle:headers():add("Referrer-Policy", "no-referrer");
end
if not response_handle:headers():get("X-Download-Options") then
response_handle:headers():add("X-Download-Options", "noopen");
end
if not response_handle:headers():get("X-DNS-Prefetch-Control") then
response_handle:headers():add("X-DNS-Prefetch-Control", "off");
end
if not response_handle:headers():get("Permissions-Policy") then
response_handle:headers():add("Permissions-Policy",
"camera 'none';"..
"microphone 'none';"..
"geolocation 'none';"..
"encrypted-media 'none';"..
"payment 'none';"..
"speaker 'none';"..
"usb 'none';");
end
if response_handle:headers():get("X-Powered-By") then
response_handle:headers():remove("X-Powered-By");
end
end
@ironstar94
Copy link

Heya!
This config is no longer valid
Filter name needs to be replaced with envoy.filters.network.http_connection_manager , subfilter name with envoy.filters.http.router and typed_config with type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua

That gets it working with Istio 1.9 :)

@ashishmahamuni21
Copy link

ashishmahamuni21 commented Mar 14, 2024

thanks @ironstar94 and @kabute for the resolution :)
it worked for me for the v.1.21.1 as well

@win5923
Copy link

win5923 commented Mar 22, 2024

thanks @ironstar94 and @kabute !

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