Skip to content

Getting Started

This guide walks you through a minimal end-to-end setup: install the USP Core WAAP operator into a Kubernetes cluster and protect an example backend application — the intentionally vulnerable OWASP Juice Shop — with a CoreWaapService custom resource.

If you prefer a fully prepared, browser-based environment, you can also follow the Killercoda Core WAAP scenarios instead.

Tip

The steps below use the latest Helm chart version: 2.0.2.

Prerequisites

Before you start, make sure you have:

  • A running Kubernetes cluster (e.g. kind, minikube, or a managed cluster) and kubectl configured to access it.
  • Helm 3 installed locally.
  • Pull credentials for the USP container registry (uspregistry.azurecr.io). If you do not yet have one, get in touch with us.

Tip

We recommend using a private registry proxy or pull-through cache that handles authentication with the upstream server and is accessible internally without authentication. However, it is also possible to use the provided registry directly with some additional steps as described in the steps below.

1. Log in to the USP container registry

The operator image and Helm chart are hosted on a private OCI registry. Log in once with the credentials you received from USP:

helm registry login uspregistry.azurecr.io --username <your-username>

You will be prompted for the password.

2. Create USP Core WAAP operator namespace

The operator will be installed in its own namespace usp-core-waap-operator:

kubectl create namespace usp-core-waap-operator

3. Create Pull secret for operator installation

To install the operator from our registry, you need to setup a pull secret.

 kubectl -n usp-core-waap-operator create secret docker-registry uspregistry --docker-server=uspregistry.azurecr.io --docker-username=<your-username> --docker-password=<your-password>
For other ways how to create such a secret see Kubernetes.io - Pull an Image from a Private Registry

4. Install the USP Core WAAP operator

To use the created pull secret you need to create a local helm values file:

cat > custom-values.yaml <<EOL
operator:
  imagePullSecretName: uspregistry
EOL

Install the operator into its own namespace usp-core-waap-operator.

helm install -f custom-values.yaml usp-core-waap-operator \
  oci://uspregistry.azurecr.io/helm/usp/core/waap/usp-core-waap-operator \
  --version 2.0.2 \
  --namespace usp-core-waap-operator

Verify that the operator pod is running:

kubectl get pods -n usp-core-waap-operator

Expected output (pod name will differ):

NAME                                  READY   STATUS    RESTARTS   AGE
core-waap-operator-744f7c8b8-7kfbs    1/1     Running   0          30s

The operator now watches for resources of kind CoreWaapService. As soon as such a custom resource is created, the operator deploys a USP Core WAAP instance that protects the configured backend.

For more options (custom values, namespace layout, upgrades, CRD extraction) see the Helm Charts page.

5. Deploy the Juice Shop example application

Create a namespace and deploy the Juice Shop in it:

kubectl create namespace juiceshop
cat > juiceshop.yaml <<EOL
# juiceshop.yaml
apiVersion: v1
kind: Pod
metadata:
  name: juiceshop
  namespace: juiceshop
  labels:
    app: juiceshop
spec:
  containers:
    - name: juiceshop
      image: bkimminich/juice-shop:latest
      ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: juiceshop
  namespace: juiceshop
spec:
  selector:
    app: juiceshop
  ports:
    - name: http
      port: 8080
      targetPort: 3000
EOL

Apply it and wait until the pod is ready:

kubectl apply -f juiceshop.yaml
kubectl wait pod/juiceshop -n juiceshop --for=condition=Ready --timeout=300s

At this point the Juice Shop is reachable inside the cluster on juiceshop.juiceshop.svc:8080, but it is not yet protected by USP Core WAAP.

6. Protect the Juice Shop with a CoreWaapService

Create a CoreWaapService resource that puts USP Core WAAP in front of the Juice Shop service:

cat > juiceshop-core-waap.yaml <<EOL
# juiceshop-core-waap.yaml
apiVersion: waap.core.u-s-p.ch/v1alpha1
kind: CoreWaapService
metadata:
  name: juiceshop-usp-core-waap
  namespace: juiceshop
spec:
  coraza:
    crs:
      paranoiaLevel: 2
      requestRuleExceptions:
        - location: /rest/basket/.+/checkout$
          regEx: true
          requestPartName: json.couponData
          requestPartType: ARGS_POST
          ruleIds:
            - 942120
  websocket: true
  routes:
    - match:
        path: "/"
        pathType: "PREFIX"
      backend:
        address: juiceshop
        port: 8080
        protocol:
          selection: h1
EOL

Note

This example raises the default Paranoia Level from 1 to 2 and adds a requestRuleException so legitimate basket checkouts are not blocked as false positives.

Before we can apply the CoreWaapService resource, we need to ensure that the used service account can pull the container image. Therefore we create a pull secret in the juiceshop namespace and patch the default service account to use it:

 kubectl -n juiceshop create secret docker-registry uspregistry --docker-server=uspregistry.azurecr.io --docker-username=<your-username> --docker-password=<your-password>
kubectl patch serviceaccount default -n juiceshop --type=json \
  -p='[{"op": "add", "path": "/imagePullSecrets/-", "value": {"name": "uspregistry"}}]'

Apply the resource and wait for the proxy pod to come up:

kubectl apply -f juiceshop-core-waap.yaml

Verify that the resources are in place:

kubectl wait pods \
  -l app.kubernetes.io/name=usp-core-waap-proxy \
  -n juiceshop \
  --for=condition=Ready --timeout=300s
kubectl get corewaapservices -n juiceshop
kubectl get pods -l app.kubernetes.io/name=usp-core-waap-proxy -n juiceshop

7. Verify the protection

Port-forward to the Core WAAP proxy and send a request that triggers an SQL-injection rule:

kubectl port-forward -n juiceshop svc/juiceshop-usp-core-waap 8080:8080

Open a browser and visit http://localhost:8080 and you should see the OWASP Juice Shop.

To verify that the WAF actually blocks, you can send the following request from an other terminal:

curl -i -X POST http://localhost:8080/rest/user/login \
  -H 'Origin: http://localhost:8080' \
  -H 'Content-Type: application/json' \
  -d '{"email":"%27 OR true;","password":"fail"}'

USP Core WAAP rejects the request with HTTP/1.1 403 Forbidden. You can inspect the matching CRS rule in the proxy logs:

kubectl logs -f \
  -l app.kubernetes.io/name=usp-core-waap-proxy \
  -n juiceshop \
  | grep APPLICATION-ATTACK-SQLI

Next steps