diff --git a/Workshops/Kubernetes-Security/Stage-4-Policy-Reporter-Visualization.md b/Workshops/Kubernetes-Security/Stage-4-Policy-Reporter-Visualization.md index dfc11fb..bb1c1c2 100644 --- a/Workshops/Kubernetes-Security/Stage-4-Policy-Reporter-Visualization.md +++ b/Workshops/Kubernetes-Security/Stage-4-Policy-Reporter-Visualization.md @@ -63,17 +63,6 @@ $ ./stage-4-policy-reporter-visualization.sh ═══════════════════════════════════════════════════════════ Stage 4: Policy Reporter Visualization - Testing ═══════════════════════════════════════════════════════════ - -ℹ Checking prerequisites... -✓ Prerequisites check passed - -═══════════════════════════════════════════════════════════ - Creating Test Environment -═══════════════════════════════════════════════════════════ - -ℹ Creating namespace policy-test... -namespace/policy-test created -✓ Namespace created ... ``` @@ -91,7 +80,7 @@ NAME KIND NAME PAS 843dab32-08bc-41de-9af3-1234a84a365e Pod non-compliant-latest-tag 2 1 0 0 0 7s d7908844-98a5-446a-a170-8faacfdb2741 Pod compliant-pod 3 0 0 0 0 8s -kubectl -n policy-test describe policyreport 5d653b12-8fe9-4e17-8464-551f35fb76d5 +$ kubectl -n policy-test describe policyreport 5d653b12-8fe9-4e17-8464-551f35fb76d5 Name: 5d653b12-8fe9-4e17-8464-551f35fb76d5 Namespace: policy-test Labels: app.kubernetes.io/managed-by=kyverno diff --git a/Workshops/Kubernetes-Security/scripts/functions.source b/Workshops/Kubernetes-Security/scripts/functions.source new file mode 100755 index 0000000..9af6cd5 --- /dev/null +++ b/Workshops/Kubernetes-Security/scripts/functions.source @@ -0,0 +1,69 @@ +#!/bin/bash + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_info() { + echo -e "${BLUE}ℹ${NC} $1" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +print_step() { + echo "" + echo -e "${GREEN}$1${NC}" + echo "" +} + +print_header() { + echo "" + echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" + echo -e "${GREEN} $1${NC}" + echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" + echo "" +} + +check_kyverno() { + print_info "Checking Kyverno..." + if ! kubectl get namespace kyverno &> /dev/null; then + print_error 'Kyverno is not installed. Please install it first.' + echo 'To install Kyverno:' + echo 'helm repo add kyverno https://kyverno.github.io/kyverno/' + echo 'helm update' + echo 'helm upgrade --install kyverno kyverno/kyverno \' + echo ' --create-namespace --namespace kyverno' + echo ' --version 3.1.4' + exit 1 + fi + print_success "Kyverno is present." +} + +check_kyverno_policy_reporter() { + if ! kubectl get namespace policy-reporter &> /dev/null; then + print_error 'Policy Reporter is not installed. Please install it first.' + echo 'To install Kyverno Policy Reporter:' + echo 'helm repo add policy-reporter https://kyverno.github.io/policy-reporter' + echo 'helm update' + echo 'helm upgrade --install policy-reporter policy-reporter/policy-reporter \' + echo ' --create-namespace --namespace policy-reporter \' + echo ' --set ui.enabled=true \' + echo ' --set kyvernoPlugin.enabled=true \' + echo ' --set ui.plugins.kyverno=true' + exit 1 + fi +} diff --git a/Workshops/Kubernetes-Security/scripts/stage-1-network-policies-namespaces.sh b/Workshops/Kubernetes-Security/scripts/stage-1-network-policies-namespaces.sh new file mode 100755 index 0000000..41cab02 --- /dev/null +++ b/Workshops/Kubernetes-Security/scripts/stage-1-network-policies-namespaces.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +set -e + +source functions.source + +print_header "Stage 1: Network Policies Namespaces - Test" + +print_info "This script will test Pod isolation using a Network Policy." + +FRONTENDPOD=frontend +EXTERNALPOD=external + +if [ "$1" == "clean" ]; then + print_step "Cleaning up things..." + kubectl delete --wait namespace backend frontend external + print_header "Cleanup complete." + exit 0 +fi + +print_step "Preparation" + +print_info "Creating namespaces..." +kubectl create namespace backend +kubectl create namespace frontend +kubectl create namespace external +print_success "Namespaces created." + +print_info "Creating backend deployment..." +kubectl --namespace backend create deployment backend --image nginx:latest +kubectl wait --namespace backend --for=condition=ready pod --selector=app=backend --timeout=90s +BACKENDIP=$(kubectl -n backend get pod -l app=backend -o jsonpath="{.items[0].status.podIP}") +print_success "Deployment backend created." + +print_info "Running frontend Pod on frontend namespace..." +kubectl -n frontend run $FRONTENDPOD --image=curlimages/curl:latest --restart=Never -- /bin/sh -c "while true; do sleep 3600; done" +kubectl wait --namespace frontend --for=condition=ready pod --selector=run=$FRONTENDPOD --timeout=90s +print_success "Pod frontend on frontend namespace created." + +print_info "Running external Pod on external namespace..." +kubectl -n external run $EXTERNALPOD --image=curlimages/curl:latest --restart=Never -- /bin/sh -c "while true; do sleep 3600; done" +kubectl wait --namespace external --for=condition=ready pod --selector=run=$EXTERNALPOD --timeout=90s +print_success "Pod external on external namespace created." + +print_step "First check: connectivity should work for both frontend and external" + +print_info "Checking connectivity BEFORE NetworkPolicy (frontend)..." +kubectl -n frontend exec -it $FRONTENDPOD \ + -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE + +print_info "Checking connectivity BEFORE NetworkPolicy (external)..." +kubectl -n external exec -it $EXTERNALPOD \ + -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE + +print_step "Create Network Policy" + +print_info "Adding labels to namespaces..." +kubectl label namespace frontend name=frontend +kubectl label namespace backend name=backend +kubectl label namespace external name=external +print_success "Labels added" + +print_info "Creating Network Policy deny-all-except-frontend..." +kubectl create -f - < /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE + +print_info "Checking connectivity AFTER NetworkPolicy (external)" +kubectl -n external exec -it $EXTERNALPOD \ + -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE + +print_header "Test Complete" diff --git a/Workshops/Kubernetes-Security/stage-2-use-default-network-policy-on-namespaces.sh b/Workshops/Kubernetes-Security/scripts/stage-2-use-default-network-policy-on-namespaces.sh similarity index 50% rename from Workshops/Kubernetes-Security/stage-2-use-default-network-policy-on-namespaces.sh rename to Workshops/Kubernetes-Security/scripts/stage-2-use-default-network-policy-on-namespaces.sh index ef38037..7c0aa42 100755 --- a/Workshops/Kubernetes-Security/stage-2-use-default-network-policy-on-namespaces.sh +++ b/Workshops/Kubernetes-Security/scripts/stage-2-use-default-network-policy-on-namespaces.sh @@ -1,16 +1,33 @@ #!/bin/bash -clean() { - kubectl delete --wait clusterpolicies add-namespace-name-label add-default-deny - kubectl delete --wait namespace backend frontend external -} +set -e + +source functions.source + +print_header "Stage 2: Default Network Policiy on Namespace - Test" + +print_info "This script will test a default Network Policy applied to a Namespace." + +FRONTENDPOD=frontend +EXTERNALPOD=external if [ "$1" == "clean" ]; then - echo "Cleaning up things..." - clean - exit $? + print_step "Cleaning up things..." + kubectl delete --wait clusterpolicies add-namespace-name-label add-default-deny + kubectl delete --wait namespace backend frontend external + print_header "Cleanup complete." + exit 0 fi +print_step "Prerequisites" + +check_kyverno + +print_success "Prerequisites check passed" + +print_step "Preparation" + +print_info "Creating two Cluster Policies: add-namespace-name-label and add-default-deny..." kubectl create -f - < /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE -echo -n "Before NetworkPolicy (frontend): " -kubectl -n frontend exec -it $FRONTENDPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE -echo -n "Before NetworkPolicy (external): " -kubectl -n external exec -it $EXTERNALPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE +print_info "Checking connectivity BEFORE NetworkPolicy (external)..." +kubectl -n external exec -it $EXTERNALPOD \ + -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE +print_step "Create Network Policy" + +print_info "Creating Network Policy allow-ingress-egress-from-backend..." kubectl create -f - < /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE + +print_info "Checking connectivity AFTER NetworkPolicy (external)" +kubectl -n external exec -it $EXTERNALPOD \ + -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 \ + && print_success REACHABLE || print_error UNREACHABLE -echo -n "After NetworkPolicy (frontend): " -kubectl -n frontend exec -it $FRONTENDPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE -echo -n "After NetworkPolicy (external): " -kubectl -n external exec -it $EXTERNALPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE +print_header "Test Complete" diff --git a/Workshops/Kubernetes-Security/scripts/stage-4-policy-reporter-visualization.sh b/Workshops/Kubernetes-Security/scripts/stage-4-policy-reporter-visualization.sh new file mode 100755 index 0000000..ceb73c1 --- /dev/null +++ b/Workshops/Kubernetes-Security/scripts/stage-4-policy-reporter-visualization.sh @@ -0,0 +1,209 @@ +#!/bin/bash + +set -e + +source functions.source + +print_header "Stage 4: Policy Reporter Visualization - Testing" + +if [ "$1" == "clean" ]; then + print_step "Cleaning up things..." + kubectl delete namespace policy-test --ignore-not-found=true + kubectl delete clusterpolicy require-labels disallow-latest-tag --ignore-not-found=true + print_header "Cleanup complete." + exit 0 +fi + +print_step "Prerequisites" + +check_kyverno + +check_kyverno_policy_reporter + +print_success "Prerequisites check passed" + +print_step "Preparation" + +# Create test namespace +print_info "Creating namespace policy-test..." +kubectl create namespace policy-test --dry-run=client -o yaml | kubectl apply -f - +print_success "Namespace created" + +# Create Kyverno policies +print_header "Creating Kyverno Policies" + +print_info "Creating 'require-labels' policy..." +cat <- + Requires all pods to have 'app' and 'owner' labels. +spec: + validationFailureAction: Audit + background: true + rules: + - name: check-for-labels + match: + any: + - resources: + kinds: + - Pod + validate: + message: "Pods must have 'app' and 'owner' labels." + pattern: + metadata: + labels: + app: "?*" + owner: "?*" +EOF +print_success "Policy 'require-labels' created" + +print_info "Creating 'disallow-latest-tag' policy..." +cat <- + Disallow use of the 'latest' tag in container images. +spec: + validationFailureAction: Audit + background: true + rules: + - name: require-image-tag + match: + any: + - resources: + kinds: + - Pod + validate: + message: "Using 'latest' tag is not allowed. Specify a version tag." + pattern: + spec: + containers: + - image: "!*:latest" + - name: require-image-tag-initcontainers + match: + any: + - resources: + kinds: + - Pod + validate: + message: "Using 'latest' tag is not allowed in init containers." + pattern: + spec: + =(initContainers): + - image: "!*:latest" +EOF +print_success "Policy 'disallow-latest-tag' created" + +print_step "Test" + +# Deploy test pods +print_header "Deploying Test Pods" + +print_info "Creating compliant pod (has labels, versioned image)..." +cat < /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE -echo -n "Before NetworkPolicy (external): " -kubectl -n external exec -it $EXTERNALPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE - -kubectl label namespace frontend name=frontend -kubectl label namespace backend name=backend -kubectl label namespace external name=external - -kubectl create -f - < /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE -echo -n "After NetworkPolicy (external): " -kubectl -n external exec -it $EXTERNALPOD -- curl -s --connect-timeout 5 $BACKENDIP > /dev/null 2>&1 && echo REACHABLE || echo UNREACHABLE diff --git a/Workshops/Kubernetes-Security/stage-4-policy-reporter-visualization.sh b/Workshops/Kubernetes-Security/stage-4-policy-reporter-visualization.sh deleted file mode 100755 index a37dec0..0000000 --- a/Workshops/Kubernetes-Security/stage-4-policy-reporter-visualization.sh +++ /dev/null @@ -1,289 +0,0 @@ -#!/bin/bash - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_info() { - echo -e "${BLUE}ℹ${NC} $1" -} - -print_success() { - echo -e "${GREEN}✓${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}⚠${NC} $1" -} - -print_error() { - echo -e "${RED}✗${NC} $1" -} - -print_header() { - echo "" - echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" - echo -e "${GREEN} $1${NC}" - echo -e "${GREEN}═══════════════════════════════════════════════════════════${NC}" - echo "" -} - -# Function to wait for resources -wait_for_resource() { - local resource=$1 - local name=$2 - local namespace=$3 - local timeout=${4:-30} - - print_info "Waiting for $resource $name in namespace $namespace..." - local counter=0 - while [ $counter -lt $timeout ]; do - if kubectl get $resource $name -n $namespace &> /dev/null; then - print_success "$resource $name is ready" - return 0 - fi - sleep 2 - counter=$((counter + 2)) - done - print_warning "Timeout waiting for $resource $name" - return 1 -} - -print_header "Stage 4: Policy Reporter Visualization - Testing" - -# Check prerequisites -print_info "Checking prerequisites..." - -if ! kubectl get namespace kyverno &> /dev/null; then - print_error "Kyverno is not installed. Please install it first." - echo "Run: helm install kyverno kyverno/kyverno -n kyverno --create-namespace --version 3.1.4" - exit 1 -fi - -if ! kubectl get namespace policy-reporter &> /dev/null; then - print_error "Policy Reporter is not installed. Please install it first." - echo "See Stage-4-Policy-Reporter-Visualization.md for installation instructions." - exit 1 -fi - -print_success "Prerequisites check passed" - -# Create test namespace -print_header "Creating Test Environment" - -print_info "Creating namespace policy-test..." -kubectl create namespace policy-test --dry-run=client -o yaml | kubectl apply -f - -print_success "Namespace created" - -# Create Kyverno policies -print_header "Creating Kyverno Policies" - -print_info "Creating 'require-labels' policy..." -cat <- - Requires all pods to have 'app' and 'owner' labels. -spec: - validationFailureAction: Audit - background: true - rules: - - name: check-for-labels - match: - any: - - resources: - kinds: - - Pod - validate: - message: "Pods must have 'app' and 'owner' labels." - pattern: - metadata: - labels: - app: "?*" - owner: "?*" -EOF -print_success "Policy 'require-labels' created" - -print_info "Creating 'disallow-latest-tag' policy..." -cat <- - Disallow use of the 'latest' tag in container images. -spec: - validationFailureAction: Audit - background: true - rules: - - name: require-image-tag - match: - any: - - resources: - kinds: - - Pod - validate: - message: "Using 'latest' tag is not allowed. Specify a version tag." - pattern: - spec: - containers: - - image: "!*:latest" - - name: require-image-tag-initcontainers - match: - any: - - resources: - kinds: - - Pod - validate: - message: "Using 'latest' tag is not allowed in init containers." - pattern: - spec: - =(initContainers): - - image: "!*:latest" -EOF -print_success "Policy 'disallow-latest-tag' created" - -# Deploy test pods -print_header "Deploying Test Pods" - -print_info "Creating compliant pod (has labels, versioned image)..." -cat < /dev/null; then - echo "" - kubectl get policyreport -n policy-test - echo "" - print_info "Detailed policy report:" - echo "" - kubectl describe policyreport -n policy-test | grep -A 50 "Results:" || kubectl describe policyreport -n policy-test -else - print_warning "No policy reports found yet" - print_info "Policy reports might take a moment to appear" -fi - -# Show how to access UI -print_header "Accessing Policy Reporter UI" - -echo "" -print_info "To view the reports in the Policy Reporter UI:" -echo "" -echo " 1. Start port forwarding:" -echo " ${GREEN}kubectl port-forward -n policy-reporter svc/policy-reporter-ui 8082:8080${NC}" -echo "" -echo " 2. Open your browser:" -echo " ${GREEN}http://localhost:8082${NC}" -echo "" -echo " 3. Navigate to the 'policy-test' namespace to see violations" -echo "" - -# Cleanup function -cleanup() { - print_header "Cleanup" - - print_info "Deleting test pods..." - kubectl delete pod -n policy-test --all --ignore-not-found=true - print_success "Test pods deleted" - - print_info "Deleting cluster policies..." - kubectl delete clusterpolicy require-labels disallow-latest-tag --ignore-not-found=true - print_success "Cluster policies deleted" - - print_info "Deleting test namespace..." - kubectl delete namespace policy-test --ignore-not-found=true - print_success "Test namespace deleted" - - echo "" - print_success "Cleanup completed!" -} - -# Ask for cleanup -echo "" -read -p "$(echo -e ${YELLOW}Do you want to cleanup test resources? [y/N]:${NC} )" -n 1 -r -echo "" - -if [[ $REPLY =~ ^[Yy]$ ]]; then - cleanup -else - print_info "Cleanup skipped" - echo "" - print_warning "To cleanup later, run the following commands:" - echo " kubectl delete namespace policy-test" - echo " kubectl delete clusterpolicy require-labels disallow-latest-tag" -fi - -print_header "Stage 4 Testing Complete" -echo "" -print_success "All tests completed successfully!" -echo ""