Edge Security with Cloud Armor

Cloud Armor is managed service from Google Cloud used to secure web applications behind external HTTP(S) load balancers.

Policies can be applied on external HTTP(S) load balancer to allow or deny traffic based on IP address, CIDR ranges, country code and request attributes.

cross-site scripting (XSS) and SQL injection (SQLi) attacks can be mitigated by using pre-configured rules.

In this blog we will deploy a simple app on Google Kubernetes Engine and configure Cloud Armor.

Create deployment in GKE

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
selector:
matchLabels:
run: web
template:
metadata:
labels:
run: web
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
imagePullPolicy: IfNotPresent
name: web
ports:
- containerPort: 8080
protocol: TCP
kubectl apply -f deployment.yaml

Create Security Policy

SECURITY_POLICY_NAME=security-policy-name

gcloud compute security-policies create ${SECURITY_POLICY_NAME} \
--description "policy for users"

Update Default Rule in Security Policy to deny all traffic

gcloud compute security-policies rules update 2147483647 \
--security-policy ${SECURITY_POLICY_NAME} \
--action "deny-404"

Define Security Policy Rules

gcloud compute security-policies rules create 1000 \
--security-policy ${SECURITY_POLICY_NAME} \
--expression "evaluatePreconfiguredExpr('sqli-stable')" \
--action "deny-403" \
--description "mitigate SQLi attack"

gcloud compute security-policies rules create 2000 \
--security-policy ${SECURITY_POLICY_NAME} \
--expression "evaluatePreconfiguredExpr('xss-stable')" \
--action "deny-403" \
--description "mitigate XSS attack"

gcloud compute security-policies rules create 3000 \
--security-policy ${SECURITY_POLICY_NAME} \
--expression "origin.region_code == 'IN' && inIpRange(origin.ip, '171.76.120.0/24')" \
--action "allow" \
--description "allow traffic from IN region with specific CIDR"

Creating a BackendConfig

A BackendConfig resource holds configuration information that’s specific to Cloud Load Balancing.

backend-config.yaml

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
name: backend-config
namespace: default
spec:
securityPolicy:
name: SECURITY_POLICY_NAME
sed -i -e "s/SECURITY_POLICY_NAME/${SECURITY_POLICY_NAME}/g" backend-config.yaml

kubectl apply -f backend-config.yaml

Create Service

service.yaml

apiVersion: v1
kind: Service
metadata:
name: web
namespace: default
annotations:
beta.cloud.google.com/backend-config: '{"ports": {"8080":"backend-config"}}'
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
run: web
type: NodePort
kubectl apply -f service.yaml

Reserve global static ip address

gcloud compute addresses create address-name --global --ip-version IPV4
STATIC_IP=`gcloud compute addresses describe address-name --global | awk 'NR == 1 {print $2}'`

Create ingress resource

ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: address-name
spec:
backend:
serviceName: web
servicePort: 8080

Test access

Wait for ingress resource to created.

curl ${STATIC_IP}

Hello, world!
Version: 1.0.0

Try SQL injection

curl http://${STATIC_IP}/?id=1%20or%201=1

403 Forbidden

Summary

When hosting any Web Applications or API’s, protecting against threats and unwanted traffic is important. Cloud Armor gives a simple interface to integrate security policies with external HTTP(S) Load Balancers.

andcloud.io

Cloud Consulting and Services