Create simple NGINX image

This readme we create simple NGINX image and illustrate docker command usage

Create an HTML file with the below content

<html>
<head>
<title>Demo</title>
</head>
<body>
<h1>Hello Team</h1>
</body>

Create a Dockerfile

# Filename: Dockerfile
FROM nginx
COPY index.html /usr/share/nginx/html/

Build the Docker Image

docker build -t zc-content-nginx .

Check the image

docker image ls

Run the container and expose

docker run --name zc-nginx -d -p 8080:80 zc-content-nginx

Test the container, browse to http://localhost:8080

Exec to the container

docker exec -it zc-nginx bash

Stop and delete the container

docker stop zc-nginx
docker rm zc-nginx

Kubernetes Ingress with NGINX

In this blog, we are going to implement the NGINX ingress for Kubernetes Cluster.

Deploy Ingress Controller

# Add NGINX stable repo
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Deploy NGINX Controller
helm install ingress-nginx ingress-nginx/ingress-nginx

Deploy Hello App (Pod and Service)

In Progress

Deploy Ingress without TLS

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: hello-app
            port:
              number: 8080
        path: /
        pathType: Prefix

Deploy Ingress with TLS

Create Kubernetes Secret

In this example, I am creating a self-signed certificate

export HOST="zaid.cloud.com"

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=${HOST}/O=${HOST}"

kubectl create secret tls ingress-tls-sec --key tls.key --cert tls.crt
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - zaid.cloud.com
    secretName: ingress-tls-sec
  rules:
  - host: zaid.cloud.com
    http:
      paths:
      - backend:
          service:
            name: hello-app
            port:
              number: 8080
        path: /
        pathType: Prefix

Validate the Ingress

# Get the NGINX service external LB IP
kubcetl get service

# Curl to test the Ingress
curl -v -k --resolve zaid.cloud.com:443:<LB-External-IP>https://zaid.cloud.com

Examine Azure Application Gateway WAF logs using Azure Log Analytics

Recently encountered a scenario post cutover where clients were getting 403 forbidden errors when trying to reach the Application hosted behind Application Gateway. We already had the client IP whitelisted on Application Gateway WAF. Log Analytics really came to our rescue.

  • We had the Application Gateway already integrated with Log Analytics.
AGW – Diagnostics Log Analytics
  • We started by looking at the Application Gateway Access logs to check which API was returning 403 error
AGW Access Log
// Errors by URI 
// Number of errors by URI. 
// To create an alert for this query, click '+ New alert rule'
AzureDiagnostics
| where ResourceType == "APPLICATIONGATEWAYS" and OperationName == "ApplicationGatewayAccess" and httpStatus_d == 403
| summarize AggregatedValue = count() by requestUri_s, _ResourceId
| sort by AggregatedValue desc
  • Next, we pulled all the Blocked records for the request URI from Application Gateway Firewall Log
AGW Firewall Log
AzureDiagnostics 
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayFirewallLog"
| where action_s contains "Blocked"
| where requestUri_s contains "/manager/html"
  • Add transactionId_g column in the result
Add transactionId_g column
  • Scroll to the right of results view to get the transactionId_g for the forbidden error
View transactionId_g
  • Run the below query to get the detailed message for the Transaction id
Detailed Firewall Log
AzureDiagnostics 
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayFirewallLog"
| where action_s contains "Blocked"
| where requestUri_s contains "/manager/html"
| where transactionId_g contains "e7c58a61-e42f-3063-0a24-90f3a2d01044"

Post this we were able to go ahead and provide feedback to the client on OWASP issues.

Other Queries:

AzureDiagnostics 
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayFirewallLog"
| where action_s contains "Blocked"
| where TimeGenerated > ago(48h)
| sort by TimeGenerated desc   
| where policyId_s == "<>"
| summarize count() by clientIp_s

AzureDiagnostics 
| where ResourceProvider == "MICROSOFT.NETWORK" and Category == "ApplicationGatewayFirewallLog"
| where action_s contains "Blocked"
| where TimeGenerated > ago(0.15h)
| sort by TimeGenerated desc   
| where policyId_s == "<>"

Resources:
Use Log Analytics

Turn off (stop) your AKS cluster

Save cost on a development cluster. Stop your control plane and agent nodes altogether, allowing you to save on all the compute costs, while maintaining all your objects and cluster state stored for when you start it again.

Stop the Cluster

az aks stop --name zcAKSCluster --resource-group zcResourceGroup

Start the Cluster

az aks start --name zcAKSCluster --resource-group zcResourceGroup

Validate the state

az aks show --name zcAKSCluster --resource-group zcResourceGroup

Start/Stop cluster