# Bypassing Imperva with a Secondary Ingress Controller

## Problem

The `redtag-prod` cluster's primary ingress controller (`tbi-webrouter`) uses a Classic ELB with a security group that only allows traffic from Imperva WAF CIDR ranges. This means:

- All traffic must flow through Imperva before reaching the cluster
- Imperva classifies mobile app requests as bots and blocks them
- Direct access to the ELB from public IPs times out

## Solution

Deploy a **secondary nginx ingress controller** with its own NLB (Network Load Balancer) that is open to all traffic. This allows the mobile app to bypass Imperva while keeping the existing setup untouched.

## Architecture

```
Mobile App → api-mobile.prod.tbidevelopment.ca → NLB (open) → nginx-mobile controller → mobile-api-proxy → backend services
Web Browser → api-mobile.redtag.ca → Imperva WAF → Classic ELB (Imperva-only SG) → nginx controller → mobile-api-proxy → backend services
```

## What Was Deployed

### 1. Secondary Ingress Controller

```bash
helm install tbi-webrouter-mobile ingress-nginx/ingress-nginx \
  --namespace webrouter \
  --kube-context redtag-prod \
  --set controller.ingressClass=nginx-mobile \
  --set controller.ingressClassResource.name=nginx-mobile \
  --set controller.ingressClassResource.controllerValue=k8s.io/ingress-nginx-mobile \
  --set controller.service.type=LoadBalancer \
  --set 'controller.service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type=nlb' \
  --set 'controller.service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-scheme=internet-facing' \
  --set controller.replicaCount=2 \
  --set controller.admissionWebhooks.enabled=false
```

- **Ingress class:** `nginx-mobile`
- **NLB:** `af8039466a426420db3c60c07c179501-ac557599e1aca747.elb.ca-central-1.amazonaws.com`
- **Open to all traffic** (NLBs don't have security groups)

### 2. DNS Record

```
api-mobile.prod.tbidevelopment.ca → CNAME → af8039466a426420db3c60c07c179501-ac557599e1aca747.elb.ca-central-1.amazonaws.com
```

Created in Route53 hosted zone `Z0531133JQNFFFJP6T4G` (`tbidevelopment.ca`) in the `tbi-shared` account (TTL: 120s).

### 3. Ingress Resource

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tbi-rlv-mobile-api-proxy-direct-ingress
  namespace: redtag
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "tbi-webrouter-mobile-letsencrypt"
spec:
  ingressClassName: nginx-mobile
  tls:
  - hosts:
    - api-mobile.prod.tbidevelopment.ca
    secretName: tbi-rlv-mobile-api-proxy-direct-tls
  rules:
  - host: api-mobile.prod.tbidevelopment.ca
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: tbi-rlv-mobile-api-proxy
            port:
              number: 80
```

### 4. ClusterIssuer for TLS

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: tbi-webrouter-mobile-letsencrypt
spec:
  acme:
    email: security@travelbrands.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: tbi-webrouter-mobile-letsencrypt
    solvers:
    - http01:
        ingress:
          class: nginx-mobile
```

### 5. ConfigMap Update

The `tbi-rlv-mobile-api-proxy-config` configmap's `server_name` was updated to accept both hostnames:

```nginx
server_name api-mobile.redtag.ca api-mobile.prod.tbidevelopment.ca;
```

## Impact on Existing Setup

| Component | Impact |
|-----------|--------|
| Existing `tbi-webrouter` controller | None — different ingress class |
| Existing ELB (Imperva-locked) | None — untouched |
| Existing ingress resources | None — they use class `nginx` |
| Existing cert-manager issuers | None — separate issuer |
| `api-mobile.redtag.ca` | Still works via Imperva |

## Verification

```bash
# Test direct endpoint (bypasses Imperva)
curl https://api-mobile.prod.tbidevelopment.ca/health

# Test Imperva endpoint (for web)
curl https://api-mobile.redtag.ca/health

# Check cert
kubectl --context redtag-prod -n redtag get certificate tbi-rlv-mobile-api-proxy-direct-tls

# Check ingress controller pods
kubectl --context redtag-prod -n webrouter get pods -l app.kubernetes.io/instance=tbi-webrouter-mobile

# Check NLB service
kubectl --context redtag-prod -n webrouter get svc tbi-webrouter-mobile-ingress-nginx-controller
```

## Rollback

```bash
# Delete ingress
kubectl --context redtag-prod -n redtag delete ingress tbi-rlv-mobile-api-proxy-direct-ingress

# Delete ClusterIssuer
kubectl --context redtag-prod delete clusterissuer tbi-webrouter-mobile-letsencrypt

# Uninstall ingress controller (removes NLB too)
helm uninstall tbi-webrouter-mobile -n webrouter --kube-context redtag-prod

# Delete DNS record
aws route53 change-resource-record-sets --hosted-zone-id Z0531133JQNFFFJP6T4G --profile tbi-shared \
  --change-batch '{"Changes":[{"Action":"DELETE","ResourceRecordSet":{"Name":"api-mobile.prod.tbidevelopment.ca","Type":"CNAME","TTL":120,"ResourceRecords":[{"Value":"af8039466a426420db3c60c07c179501-ac557599e1aca747.elb.ca-central-1.amazonaws.com"}]}}]}'
```

## Applying to Other Services

To expose another service directly (bypassing Imperva), create an ingress with `ingressClassName: nginx-mobile` and add a DNS CNAME pointing to the NLB.
