Security headers with istio

NIRAV SHAH
3 min readMar 26, 2021

--

Security is important on most of the company. I remember the configuration for the nginx , as it has been done multiple times. However when we moved to istio world ensuring that looks tricky. Let’s see how we can do that easily.

Security Headers check before applying configuration

https://securityheaders.com/ performs security header check. It provide failed result for the site as it is not yet done through istio/envoy

Failed Security headers Checks

NGINX configuration for Security Headers

If we have to perform that on nginx, below configuration would do the magic. However, we are using istio. Next block will help you for doing that.

   add_header Content-Security-Policy "base-uri 'self'; " always;
add_header Strict-Transport-Security "max-age=16070400; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer" always;
add_header Feature-Policy "none" always;
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
add_header Access-Control-Expose-Headers "ETag, Link, Location, Retry-After, X-Awacs-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-Awacs-Media-Type, Deprecation, Sunset";
add_header Cache-Control "no-cache" always;
add_header Vary "Accept-Encoding, Accept, X-Requested-With" always;
add_header X-Request-Id $request_id;

Istio Security Headers

Here, we will use envoyfilter with lua configuration. If you dont want to go in details just use below configuration file & apply to kubernetes environment where your gateway configured. create a file with name istio-envoy-filter.yaml.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: security-by-default-header-filter
spec:
filters:
- listenerMatch:
listenerType: GATEWAY
filterType: HTTP
filterName: envoy.lua
filterConfig:
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("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("Feature-Policy") then
response_handle:headers():add("Feature-Policy",
"camera 'none';"..
"microphone 'none';"..
"geolocation 'none';"..
"encrypted-media 'none';"..
"payment 'none';"..
"speaker 'none';"..
"usb 'none';");
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

configure on kubernetes

kubectl apply -f istio-envoy-filter.yaml

Security Headers check after applying configuration

https://securityheaders.com/ performs security header check. It provide successful result for the site as we applied required configuration on istio/envoy. Sometimes managing security is easy.

Successful Security headers check

Give claps if you liked the simple article.

Reference:

--

--

NIRAV SHAH
NIRAV SHAH

Written by NIRAV SHAH

Working as Cloud Architect & Software enthusiastic

No responses yet