Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
Overview
Calico is an open-source CNI plugin that provides fine-grained network policy enforcement for Kubernetes clusters. It implements the full Kubernetes NetworkPolicy API and extends it with Calico-specific GlobalNetworkPolicy, supporting policy ordering, deny rules, and service-account-based selectors.
When to Use
- When deploying or configuring implementing kubernetes network policy with calico capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Kubernetes cluster (v1.24+)
- Calico CNI installed (v3.26+)
kubectlandcalicoctlCLI tools- Cluster admin RBAC permissions
Installing Calico
Operator-based Installation (Recommended)
# Install the Tigera operator
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml
# Install Calico custom resources
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml
# Verify installation
kubectl get pods -n calico-system
watch kubectl get pods -n calico-system
# Install calicoctl
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calicoctl.yamlVerify Calico is Running
# Check Calico pods
kubectl get pods -n calico-system
# Check Calico node status
kubectl exec -n calico-system calicoctl -- calicoctl node status
# Check IP pools
kubectl exec -n calico-system calicoctl -- calicoctl get ippool -o wideKubernetes NetworkPolicy
Default Deny All Traffic
# deny-all-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# deny-all-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- EgressAllow Specific Pod-to-Pod Communication
# allow-frontend-to-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080Allow DNS Egress
# allow-dns-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Namespace Isolation
# allow-same-namespace.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}Calico-Specific Policies
GlobalNetworkPolicy (Cluster-Wide)
# global-deny-external.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-external-ingress
spec:
order: 100
selector: "projectcalico.org/namespace != 'ingress-nginx'"
types:
- Ingress
ingress:
- action: Deny
source:
nets:
- 0.0.0.0/0
destination: {}Calico NetworkPolicy with Deny Rules
# calico-deny-policy.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: deny-database-from-frontend
namespace: production
spec:
order: 10
selector: app == 'database'
types:
- Ingress
ingress:
- action: Deny
source:
selector: app == 'frontend'
- action: Allow
source:
selector: app == 'backend'
destination:
ports:
- 5432Service Account Based Policy
# sa-based-policy.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-by-service-account
namespace: production
spec:
selector: app == 'api'
ingress:
- action: Allow
source:
serviceAccounts:
names:
- frontend-sa
- monitoring-sa
egress:
- action: Allow
destination:
serviceAccounts:
names:
- database-saHost Endpoint Protection
# host-endpoint-policy.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: restrict-host-ssh
spec:
order: 10
selector: "has(kubernetes.io/hostname)"
applyOnForward: false
types:
- Ingress
ingress:
- action: Allow
protocol: TCP
source:
nets:
- 10.0.0.0/8
destination:
ports:
- 22
- action: Deny
protocol: TCP
destination:
ports:
- 22Calico Policy Tiers
# security-tier.yaml
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: security
spec:
order: 100
---
# platform-tier.yaml
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: platform
spec:
order: 200Monitoring and Troubleshooting
# List all network policies
kubectl get networkpolicy --all-namespaces
# List Calico-specific policies
kubectl exec -n calico-system calicoctl -- calicoctl get networkpolicy --all-namespaces -o wide
kubectl exec -n calico-system calicoctl -- calicoctl get globalnetworkpolicy -o wide
# Check policy evaluation for a specific endpoint
kubectl exec -n calico-system calicoctl -- calicoctl get workloadendpoint -n production -o yaml
# View Calico logs
kubectl logs -n calico-system -l k8s-app=calico-node --tail=100
# Test connectivity
kubectl exec -n production frontend-pod -- wget -qO- --timeout=2 http://backend-svc:8080/healthBest Practices
- Start with default deny - Apply deny-all policies to every namespace, then allow specific traffic
- Use labels consistently - Define a labeling standard for app, tier, environment
- Order policies - Use Calico policy ordering (
orderfield) to control evaluation precedence - Allow DNS first - Always create DNS egress rules before applying egress deny policies
- Use GlobalNetworkPolicy for cluster-wide security baselines
- Test policies in staging - Validate network connectivity after applying policies
- Monitor denied traffic - Enable Calico flow logs for visibility into blocked connections
- Use tiers - Organize policies into security, platform, and application tiers
Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md1.4 KB
API Reference: Implementing Kubernetes Network Policy with Calico
Kubernetes NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes: [Ingress, Egress]Calico GlobalNetworkPolicy
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-external
spec:
order: 100
selector: app == "backend"
types: [Ingress]
ingress:
- action: Deny
source:
nets: ["0.0.0.0/0"]calicoctl CLI
# Apply policy
calicoctl apply -f policy.yaml
# Get policies
calicoctl get globalnetworkpolicy -o yaml
# Get host endpoints
calicoctl get hostendpointPolicy Types
| Type | Scope | Ordering |
|---|---|---|
| NetworkPolicy | Namespace | Additive (OR) |
| GlobalNetworkPolicy | Cluster-wide | Ordered by order field |
Common Policy Patterns
| Pattern | Description |
|---|---|
| Default deny | Empty podSelector, no rules |
| Allow DNS | Egress to kube-system UDP/TCP 53 |
| Allow ingress from namespace | namespaceSelector match |
| Allow to external CIDR | ipBlock in egress |
References
- Calico Docs: https://docs.tigera.io/calico/
- K8s NetworkPolicy: https://kubernetes.io/docs/concepts/services-networking/network-policies/
- Calico Policy Tutorial: https://docs.tigera.io/calico/latest/network-policy/
standards.md2.6 KB
Standards and References - Kubernetes Network Policy with Calico
Industry Standards
NIST SP 800-190: Application Container Security Guide
- Section 4.4: Container Networking - Isolate container network traffic using network policies
- Section 5.3: Network Security - Implement micro-segmentation between containers
- Recommends default-deny policies with explicit allowlisting
CIS Kubernetes Benchmark v1.8
- 5.3.1: Ensure that the CNI in use supports Network Policies
- 5.3.2: Ensure that all Namespaces have Network Policies defined
- 5.3.3: Ensure that the default namespace does not contain any pods
NIST SP 800-53 Rev 5
- SC-7: Boundary Protection - Implement network segmentation controls
- AC-4: Information Flow Enforcement - Control network traffic between pods
- SC-7(5): Deny by Default / Allow by Exception
NSA/CISA Kubernetes Hardening Guide v1.2
- Section 3: Network Separation and Hardening
- Use network policies to isolate workloads
- Implement default deny ingress and egress policies
- Limit pod-to-pod communication to minimum required
Calico Documentation References
| Resource | URL |
|---|---|
| Calico NetworkPolicy | https://docs.tigera.io/calico/latest/network-policy/get-started/calico-policy/calico-network-policy |
| Kubernetes Policy Tutorial | https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-policy-basic |
| GlobalNetworkPolicy | https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy |
| Policy Tiers | https://docs.tigera.io/calico-enterprise/latest/network-policy/policy-tiers/tiered-policy |
| Calico eBPF Dataplane | https://docs.tigera.io/calico/latest/operations/ebpf/enabling-ebpf |
Zero Trust Network Model
Principles Applied
- Never trust, always verify - Default deny all traffic between pods
- Least privilege access - Only allow specific required communication paths
- Micro-segmentation - Isolate workloads at pod-to-pod granularity
- Identity-based policies - Use service accounts and labels for policy selection
- Continuous monitoring - Log and alert on denied traffic patterns
Compliance Mappings
PCI DSS v4.0
- Requirement 1.2.1: Restrict inbound and outbound traffic to that which is necessary
- Requirement 1.3.1: Inbound traffic is restricted to that which is necessary
- Requirement 1.3.2: Outbound traffic is restricted to that which is necessary
SOC 2 Type II
- CC6.1: Logical access security - Network isolation between components
- CC6.6: Network boundaries - Restrict access at network boundaries
HIPAA
- 164.312(e)(1): Transmission Security - Protect data in transit between services
workflows.md4.5 KB
Workflow - Implementing Kubernetes Network Policy with Calico
Phase 1: Discovery and Planning
Map Application Communication Flows
# Identify all namespaces
kubectl get namespaces
# List all services per namespace
kubectl get svc --all-namespaces -o wide
# Identify pod labels
kubectl get pods --all-namespaces --show-labels
# Check existing network policies
kubectl get networkpolicy --all-namespacesDocument Required Traffic Flows
Create a traffic matrix documenting:
- Source pod/namespace -> Destination pod/namespace
- Protocol and port
- Business justification
Phase 2: Install and Verify Calico
# Install Tigera operator
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml
# Wait for operator
kubectl wait --for=condition=Available deployment/tigera-operator -n tigera-operator --timeout=120s
# Install Calico custom resources
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml
# Verify all Calico pods are running
kubectl get pods -n calico-system -w
# Install calicoctl as a pod
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calicoctl.yaml
# Verify node status
kubectl exec -n calico-system calicoctl -- calicoctl node statusPhase 3: Apply Default Deny Policies
Step 1 - Create DNS Allow Policy First
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to: []
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
EOFStep 2 - Apply Default Deny Ingress
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
EOFStep 3 - Apply Default Deny Egress
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
EOFStep 4 - Apply Allow Rules per Traffic Flow
# Allow frontend to backend
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
EOFPhase 4: Validate Policies
Connectivity Testing
# Test allowed path (should succeed)
kubectl exec -n production deploy/frontend -- wget -qO- --timeout=5 http://backend-svc:8080/health
# Test blocked path (should timeout/fail)
kubectl exec -n production deploy/frontend -- wget -qO- --timeout=5 http://database-svc:5432
# Test cross-namespace (should fail if denied)
kubectl exec -n staging deploy/test -- wget -qO- --timeout=5 http://backend-svc.production:8080/healthMonitor Denied Connections
# Check Calico logs for denied connections
kubectl logs -n calico-system -l k8s-app=calico-node --tail=50 | grep -i deny
# Enable flow logs (Calico Enterprise)
kubectl exec -n calico-system calicoctl -- calicoctl get felixconfiguration default -o yamlPhase 5: Advanced Calico Policies
Apply Global Security Baseline
kubectl exec -n calico-system calicoctl -- calicoctl apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security-baseline
spec:
order: 100
types:
- Ingress
- Egress
egress:
- action: Allow
protocol: UDP
destination:
ports:
- 53
- action: Allow
protocol: TCP
destination:
ports:
- 53
ingress:
- action: Allow
source:
selector: "projectcalico.org/namespace in {'kube-system', 'monitoring'}"
EOFPhase 6: Ongoing Operations
Regular Policy Audits
- Review traffic flow matrix monthly
- Validate policies match documented flows
- Remove stale policies for decommissioned services
- Update policies when new services are deployed
Incident Response
- If suspicious traffic detected, apply emergency deny policy
- Analyze Calico flow logs for investigation
- Identify compromised pod via workload endpoint
- Isolate pod by applying targeted deny policy
Scripts 2
agent.py7.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for auditing and generating Calico Kubernetes network policies."""
import json
import argparse
import subprocess
from datetime import datetime
def kubectl_get(resource, namespace=None, label_selector=None):
"""Get Kubernetes resources via kubectl."""
cmd = ["kubectl", "get", resource, "-o", "json"]
if namespace:
cmd.extend(["-n", namespace])
else:
cmd.append("--all-namespaces")
if label_selector:
cmd.extend(["-l", label_selector])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
if result.returncode != 0:
return {"error": result.stderr.strip()}
return json.loads(result.stdout) if result.stdout.strip() else {}
def list_network_policies():
"""List all NetworkPolicy and Calico GlobalNetworkPolicy resources."""
k8s_np = kubectl_get("networkpolicy")
calico_gnp = kubectl_get("globalnetworkpolicy")
return {
"k8s_network_policies": k8s_np.get("items", []) if isinstance(k8s_np, dict) else [],
"calico_global_policies": calico_gnp.get("items", []) if isinstance(calico_gnp, dict) else [],
}
def audit_network_policies(policies_path):
"""Audit network policies for security gaps."""
with open(policies_path) as f:
data = json.load(f)
policies = data if isinstance(data, list) else data.get("items", data.get("policies", []))
findings = []
namespaces_covered = set()
for policy in policies:
metadata = policy.get("metadata", {})
spec = policy.get("spec", {})
ns = metadata.get("namespace", "default")
namespaces_covered.add(ns)
policy_types = spec.get("policyTypes", [])
if "Ingress" not in policy_types and "Egress" not in policy_types:
findings.append({
"policy": metadata.get("name", ""),
"namespace": ns,
"issue": "No policyTypes defined (defaults to ingress-only)",
"severity": "MEDIUM",
})
if "Egress" not in policy_types:
findings.append({
"policy": metadata.get("name", ""),
"namespace": ns,
"issue": "No egress policy - all outbound traffic allowed",
"severity": "HIGH",
})
ingress_rules = spec.get("ingress", [])
for rule in ingress_rules:
if not rule.get("from"):
findings.append({
"policy": metadata.get("name", ""),
"issue": "Ingress rule allows from all sources",
"severity": "HIGH",
})
egress_rules = spec.get("egress", [])
for rule in egress_rules:
if not rule.get("to"):
findings.append({
"policy": metadata.get("name", ""),
"issue": "Egress rule allows to all destinations",
"severity": "MEDIUM",
})
return {"findings": findings, "namespaces_covered": list(namespaces_covered),
"total_policies": len(policies)}
def generate_default_deny(namespace):
"""Generate a default deny-all NetworkPolicy for a namespace."""
return {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {"name": "default-deny-all", "namespace": namespace},
"spec": {
"podSelector": {},
"policyTypes": ["Ingress", "Egress"],
},
}
def generate_allow_dns_egress(namespace):
"""Generate a policy allowing DNS egress to kube-dns."""
return {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {"name": "allow-dns-egress", "namespace": namespace},
"spec": {
"podSelector": {},
"policyTypes": ["Egress"],
"egress": [{
"to": [{"namespaceSelector": {"matchLabels": {
"kubernetes.io/metadata.name": "kube-system"}}}],
"ports": [{"protocol": "UDP", "port": 53},
{"protocol": "TCP", "port": 53}],
}],
},
}
def generate_app_policy(namespace, app_label, allowed_ingress_labels=None,
allowed_egress_ports=None):
"""Generate a Calico-style network policy for an application."""
policy = {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {"name": f"allow-{app_label}", "namespace": namespace},
"spec": {
"podSelector": {"matchLabels": {"app": app_label}},
"policyTypes": ["Ingress", "Egress"],
"ingress": [],
"egress": [],
},
}
if allowed_ingress_labels:
for label in allowed_ingress_labels:
policy["spec"]["ingress"].append({
"from": [{"podSelector": {"matchLabels": {"app": label}}}],
})
if allowed_egress_ports:
for port_info in allowed_egress_ports:
policy["spec"]["egress"].append({
"ports": [{"protocol": port_info.get("protocol", "TCP"),
"port": port_info["port"]}],
})
return policy
def check_unprotected_namespaces():
"""Find namespaces without any network policies."""
namespaces = kubectl_get("namespaces")
policies = kubectl_get("networkpolicy")
if isinstance(namespaces, dict) and "error" not in namespaces:
all_ns = {item["metadata"]["name"] for item in namespaces.get("items", [])}
else:
return {"error": "Cannot list namespaces"}
protected_ns = set()
if isinstance(policies, dict) and "error" not in policies:
for item in policies.get("items", []):
protected_ns.add(item.get("metadata", {}).get("namespace", "default"))
system_ns = {"kube-system", "kube-public", "kube-node-lease"}
unprotected = all_ns - protected_ns - system_ns
return {
"total_namespaces": len(all_ns),
"protected": len(protected_ns),
"unprotected": list(unprotected),
"severity": "HIGH" if unprotected else "INFO",
}
def main():
parser = argparse.ArgumentParser(description="Calico Network Policy Agent")
parser.add_argument("--audit", help="Network policies JSON to audit")
parser.add_argument("--namespace", help="Namespace for policy generation")
parser.add_argument("--app", help="App label for policy generation")
parser.add_argument("--action", choices=["audit", "generate", "check", "full"],
default="full")
parser.add_argument("--output", default="calico_netpol_report.json")
args = parser.parse_args()
report = {"generated_at": datetime.utcnow().isoformat(), "results": {}}
if args.action in ("audit", "full") and args.audit:
result = audit_network_policies(args.audit)
report["results"]["audit"] = result
print(f"[+] Audit: {len(result['findings'])} findings across {result['total_policies']} policies")
if args.action in ("generate", "full") and args.namespace:
policies = [
generate_default_deny(args.namespace),
generate_allow_dns_egress(args.namespace),
]
if args.app:
policies.append(generate_app_policy(args.namespace, args.app))
report["results"]["generated"] = policies
print(f"[+] Generated {len(policies)} policies for {args.namespace}")
if args.action in ("check", "full"):
result = check_unprotected_namespaces()
report["results"]["unprotected"] = result
print(f"[+] Unprotected namespaces: {result.get('unprotected', [])}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()
process.py7.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Calico Network Policy Manager - Generate, validate, and audit Kubernetes
network policies using Calico for zero-trust pod communication.
"""
import json
import subprocess
import sys
import argparse
import yaml
from typing import Optional
def run_kubectl(args: list, namespace: Optional[str] = None) -> str:
"""Execute kubectl command and return output."""
cmd = ["kubectl"]
if namespace:
cmd.extend(["-n", namespace])
cmd.extend(args)
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"kubectl error: {result.stderr}", file=sys.stderr)
return result.stdout
def get_namespaces() -> list:
"""Get all non-system namespaces."""
output = run_kubectl(["get", "namespaces", "-o", "json"])
ns_data = json.loads(output)
system_ns = {"kube-system", "kube-public", "kube-node-lease", "calico-system", "tigera-operator"}
return [
ns["metadata"]["name"]
for ns in ns_data["items"]
if ns["metadata"]["name"] not in system_ns
]
def get_network_policies(namespace: str) -> list:
"""Get all network policies in a namespace."""
output = run_kubectl(["get", "networkpolicy", "-o", "json"], namespace=namespace)
if not output.strip():
return []
data = json.loads(output)
return data.get("items", [])
def check_default_deny(namespace: str) -> dict:
"""Check if default deny policies exist for a namespace."""
policies = get_network_policies(namespace)
has_ingress_deny = False
has_egress_deny = False
for pol in policies:
spec = pol.get("spec", {})
selector = spec.get("podSelector", {})
policy_types = spec.get("policyTypes", [])
if selector == {} or selector.get("matchLabels") is None:
if "Ingress" in policy_types and not spec.get("ingress"):
has_ingress_deny = True
if "Egress" in policy_types and not spec.get("egress"):
has_egress_deny = True
return {
"namespace": namespace,
"default_deny_ingress": has_ingress_deny,
"default_deny_egress": has_egress_deny,
"policy_count": len(policies),
}
def audit_all_namespaces() -> list:
"""Audit all namespaces for network policy coverage."""
namespaces = get_namespaces()
results = []
for ns in namespaces:
result = check_default_deny(ns)
results.append(result)
return results
def generate_default_deny(namespace: str) -> str:
"""Generate default deny ingress and egress policies for a namespace."""
policies = [
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "default-deny-ingress",
"namespace": namespace,
},
"spec": {
"podSelector": {},
"policyTypes": ["Ingress"],
},
},
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "default-deny-egress",
"namespace": namespace,
},
"spec": {
"podSelector": {},
"policyTypes": ["Egress"],
},
},
{
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": "allow-dns-egress",
"namespace": namespace,
},
"spec": {
"podSelector": {},
"policyTypes": ["Egress"],
"egress": [
{
"ports": [
{"protocol": "UDP", "port": 53},
{"protocol": "TCP", "port": 53},
]
}
],
},
},
]
return yaml.dump_all(policies, default_flow_style=False)
def generate_allow_policy(
namespace: str,
name: str,
target_labels: dict,
source_labels: dict,
port: int,
protocol: str = "TCP",
) -> str:
"""Generate an allow ingress policy."""
policy = {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": name,
"namespace": namespace,
},
"spec": {
"podSelector": {"matchLabels": target_labels},
"policyTypes": ["Ingress"],
"ingress": [
{
"from": [{"podSelector": {"matchLabels": source_labels}}],
"ports": [{"protocol": protocol, "port": port}],
}
],
},
}
return yaml.dump(policy, default_flow_style=False)
def print_audit_report(results: list):
"""Print formatted audit report."""
print("\n=== Kubernetes Network Policy Audit Report ===\n")
print(f"{'Namespace':<30} {'Deny Ingress':<15} {'Deny Egress':<15} {'Policies':<10} {'Status'}")
print("-" * 85)
compliant = 0
total = len(results)
for r in results:
ingress = "YES" if r["default_deny_ingress"] else "NO"
egress = "YES" if r["default_deny_egress"] else "NO"
status = "COMPLIANT" if r["default_deny_ingress"] and r["default_deny_egress"] else "NON-COMPLIANT"
if status == "COMPLIANT":
compliant += 1
print(f"{r['namespace']:<30} {ingress:<15} {egress:<15} {r['policy_count']:<10} {status}")
print(f"\n{compliant}/{total} namespaces compliant with default-deny policy")
def main():
parser = argparse.ArgumentParser(description="Calico Network Policy Manager")
subparsers = parser.add_subparsers(dest="command")
# Audit command
subparsers.add_parser("audit", help="Audit all namespaces for network policy coverage")
# Generate deny command
gen_deny = subparsers.add_parser("generate-deny", help="Generate default deny policies")
gen_deny.add_argument("--namespace", "-n", required=True, help="Target namespace")
gen_deny.add_argument("--apply", action="store_true", help="Apply policies directly")
# Generate allow command
gen_allow = subparsers.add_parser("generate-allow", help="Generate allow policy")
gen_allow.add_argument("--namespace", "-n", required=True)
gen_allow.add_argument("--name", required=True, help="Policy name")
gen_allow.add_argument("--target-app", required=True, help="Target pod app label")
gen_allow.add_argument("--source-app", required=True, help="Source pod app label")
gen_allow.add_argument("--port", type=int, required=True, help="Allowed port")
gen_allow.add_argument("--protocol", default="TCP", choices=["TCP", "UDP"])
args = parser.parse_args()
if args.command == "audit":
results = audit_all_namespaces()
print_audit_report(results)
elif args.command == "generate-deny":
policy_yaml = generate_default_deny(args.namespace)
if args.apply:
proc = subprocess.run(
["kubectl", "apply", "-f", "-"],
input=policy_yaml,
capture_output=True,
text=True,
)
print(proc.stdout)
if proc.stderr:
print(proc.stderr, file=sys.stderr)
else:
print(policy_yaml)
elif args.command == "generate-allow":
policy_yaml = generate_allow_policy(
namespace=args.namespace,
name=args.name,
target_labels={"app": args.target_app},
source_labels={"app": args.source_app},
port=args.port,
protocol=args.protocol,
)
print(policy_yaml)
else:
parser.print_help()
if __name__ == "__main__":
main()
Assets 1
template.mdtext/markdown · 1.9 KBKeep exploring