Skip to main content
Version: v0.10

Quick Start: allow and deny HTTP requests

This tutorial creates an owned HTTP backend and an injected client in varmor-networkproxy-demo. Only GET /allow/… to the backend is allowed. The backend itself returns 200 for any GET path, so its access log can distinguish proxy denial from a backend error.

Prerequisites

  • Install vArmor v0.10.5 with its matching custom Envoy/proxyinit images; see Installation.
  • Use Linux Pods with their own network namespaces and admission settings that permit the injected root containers and NET_ADMIN. Check Security and Compatibility.
  • The example assumes the cluster DNS suffix cluster.local; replace it consistently in the policy and request URLs if yours differs.
  • Use a namespace name that is not already in use. The cleanup deletes this entire dedicated namespace. Do not reuse a business namespace.

The application UID is 1000, distinct from the default proxy UID 1337. No external API credentials or MITM certificates are needed.

1. Create the backend

Save the following as backend.yaml, then apply it:

backend.yaml
apiVersion: v1
kind: Namespace
metadata:
name: varmor-networkproxy-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: varmor-networkproxy-demo
spec:
replicas: 1
selector:
matchLabels: {app: np-guide-backend}
template:
metadata:
labels: {app: np-guide-backend}
spec:
automountServiceAccountToken: false
securityContext:
runAsUser: 1000
runAsNonRoot: true
containers:
- name: backend
image: python:3.12-alpine
command: [python3, -u, -c]
args:
- |
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b"backend reached\n")
HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()
ports:
- containerPort: 8000
readinessProbe:
tcpSocket: {port: 8000}
---
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: varmor-networkproxy-demo
spec:
selector: {app: np-guide-backend}
ports:
- port: 8000
targetPort: 8000
kubectl apply -f backend.yaml
kubectl rollout status deployment/backend -n varmor-networkproxy-demo --timeout=120s

The backend is not labeled for vArmor injection. Its readiness check opens a TCP connection without generating an HTTP test request.

2. Create the policy before the client

Save as policy.yaml:

policy.yaml
apiVersion: crd.varmor.org/v1beta1
kind: VarmorPolicy
metadata:
name: http-guide
namespace: varmor-networkproxy-demo
spec:
target:
kind: Pod
name: client
policy:
enforcer: NetworkProxy
mode: EnhanceProtect
enhanceProtect:
networkProxyRawRules:
egress:
defaultAction: deny
httpRules:
- qualifiers: [allow, audit]
match:
hosts: [backend.varmor-networkproxy-demo.svc.cluster.local]
ports: [{port: 8000}]
paths: [{prefix: /allow/}]
methods: [GET]
kubectl apply -f policy.yaml
kubectl wait -n varmor-networkproxy-demo --for=jsonpath='{.status.ready}'=true varmorpolicy/http-guide --timeout=120s

On timeout, inspect the policy's status/conditions before continuing. Next, create the client and verify its requests.

3. Create and inspect the client

Save as client.yaml:

client.yaml
apiVersion: v1
kind: Pod
metadata:
name: client
namespace: varmor-networkproxy-demo
labels:
sandbox.varmor.org/enable: "true"
spec:
automountServiceAccountToken: false
securityContext:
runAsUser: 1000
runAsNonRoot: true
containers:
- name: client
image: curlimages/curl:8.12.1
command: [sh, -c, "sleep 3600"]
kubectl apply -f client.yaml
kubectl wait -n varmor-networkproxy-demo --for=condition=Ready pod/client --timeout=120s
kubectl get pod client -n varmor-networkproxy-demo -o jsonpath='{.spec.initContainers[*].name}{"\n"}{.spec.containers[*].name}{"\n"}'

Expect init container varmor-network-proxy-init and containers client and varmor-network-proxy. If either injected container is missing, check the policy target and Pod events before continuing.

4. Verify allowed and denied requests

Run each once, keeping its status code and response:

kubectl exec -n varmor-networkproxy-demo client -c client -- \
curl --noproxy '*' --max-time 10 -sS -w '\nHTTP %{http_code}\n' \
'http://backend.varmor-networkproxy-demo.svc.cluster.local:8000/allow/?case=allow-1'

kubectl exec -n varmor-networkproxy-demo client -c client -- \
curl --noproxy '*' --max-time 10 -sS -w '\nHTTP %{http_code}\n' \
'http://backend.varmor-networkproxy-demo.svc.cluster.local:8000/deny/?case=deny-1'

kubectl logs -n varmor-networkproxy-demo deployment/backend -c backend
RequestClientBackend access logSelected audit
/allow/?case=allow-1200, backend reachedOne matching GETAUDIT
/deny/?case=deny-1403 from proxyNo matching GETDENIED

Curl can exit successfully for HTTP 403; check the HTTP code. A timeout or connection refusal is not the expected deny result for this example. If the initial configuration is not usable, inspect Troubleshooting.

Find the audit records at the node or sidecar location described in Observability, filtered to this namespace and Pod.

5. Change one rule and verify again

Change the allow rule's path prefix from /allow/ to /deny/ in policy.yaml and apply it. Inspect policy status and proxy reload logs; wait for the configuration files to update and the proxy to load them. Then repeat the pair using new case values: /allow/ should now be denied and /deny/ allowed.

This rule change takes effect without recreating the client Pod. For other changes, see Lifecycle and Upgrades.

6. Clean up

kubectl delete namespace varmor-networkproxy-demo

This removes only the dedicated tutorial resources. Continue with Policy Semantics, then TLS and Credentials for HTTPS.