npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
Calico provides Kubernetes-native and extended network policy enforcement through its CNI plugin. This skill covers creating and auditing Calico NetworkPolicy and GlobalNetworkPolicy resources to implement pod-to-pod traffic control, namespace isolation, egress restrictions, and DNS-based policy rules using calicoctl and the Kubernetes API.
When to Use
- When deploying or configuring implementing container network policies 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 with Calico CNI installed
- Python 3.9+ with
kubernetesclient library - calicoctl CLI tool installed and configured
- kubectl access with RBAC permissions for network policy management
Steps
Step 1: Audit Existing Network Policies
Use calicoctl and kubectl to inventory current network policies and identify unprotected namespaces.
Step 2: Implement Default-Deny Policies
Create default-deny ingress and egress policies per namespace as a zero-trust baseline.
Step 3: Create Workload-Specific Allow Rules
Define granular allow rules for legitimate pod-to-pod and pod-to-service communication.
Step 4: Validate Policy Enforcement
Test connectivity between pods to verify policies are correctly enforced.
Expected Output
JSON audit report listing all network policies, unprotected namespaces, policy rule counts, and connectivity test results.
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md1.9 KB
API Reference: Implementing Container Network Policies with Calico
calicoctl Commands
# List network policies across all namespaces
calicoctl get networkpolicy --all-namespaces -o json
# List global network policies
calicoctl get globalnetworkpolicy -o json
# Check Calico node status
calicoctl node status
# Apply a Calico network policy
calicoctl apply -f policy.yaml
# Get workload endpoints
calicoctl get workloadendpoint -o wide
# Check IP pool configuration
calicoctl get ippool -o jsonKubernetes NetworkPolicy vs Calico
| Feature | K8s NetworkPolicy | Calico NetworkPolicy | Calico GlobalNetworkPolicy |
|---|---|---|---|
| Scope | Namespace | Namespace | Cluster-wide |
| Selector | Pod labels | Pod + service account | All workloads + host endpoints |
| Rule types | Ingress, Egress | Ingress, Egress | Ingress, Egress |
| DNS policy | No | Yes | Yes |
| Order/Priority | No | Yes (order field) | Yes (order field) |
| CIDR ranges | Yes | Yes | Yes |
Default-Deny Policy Template
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- IngressPython kubernetes Client
from kubernetes import client, config
config.load_kube_config()
net_v1 = client.NetworkingV1Api()
policies = net_v1.list_network_policy_for_all_namespaces()
for p in policies.items:
print(p.metadata.name, p.metadata.namespace)Install: pip install kubernetes
References
- Calico Network Policy: https://docs.tigera.io/calico/latest/network-policy/get-started/calico-policy/calico-network-policy
- calicoctl Reference: https://docs.tigera.io/calico-enterprise/latest/reference/clis/calicoctl/overview
- K8s Network Policy: https://kubernetes.io/docs/concepts/services-networking/network-policies/
Scripts 1
agent.py7.8 KB
#!/usr/bin/env python3
"""Agent for implementing container network policies with Calico.
Audits Kubernetes network policies, identifies unprotected
namespaces, validates Calico policy enforcement, and generates
default-deny baseline policy manifests.
"""
import argparse
import json
import os
import subprocess
from datetime import datetime
from pathlib import Path
try:
from kubernetes import client, config
except ImportError:
client = None
config = None
DEFAULT_DENY_INGRESS = {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {"name": "default-deny-ingress"},
"spec": {"podSelector": {}, "policyTypes": ["Ingress"]},
}
DEFAULT_DENY_EGRESS = {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {"name": "default-deny-egress"},
"spec": {"podSelector": {}, "policyTypes": ["Egress"]},
}
class CalicoNetworkPolicyAgent:
"""Audits and manages Calico network policies on Kubernetes."""
def __init__(self, kubeconfig=None, output_dir="./calico_policy_audit"):
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.findings = []
self.v1 = None
self.net_v1 = None
if client and config:
try:
if kubeconfig:
config.load_kube_config(config_file=kubeconfig)
else:
config.load_kube_config()
self.v1 = client.CoreV1Api()
self.net_v1 = client.NetworkingV1Api()
except Exception:
pass
def _run_calicoctl(self, args):
"""Run calicoctl command and return parsed output."""
try:
result = subprocess.run(
["calicoctl"] + args, capture_output=True, text=True, timeout=30
)
return result.stdout, result.returncode
except FileNotFoundError:
return "", 1
except subprocess.TimeoutExpired:
return "", 1
def list_k8s_network_policies(self):
"""List all Kubernetes NetworkPolicy resources across namespaces."""
if not self.net_v1:
return []
policies = self.net_v1.list_network_policy_for_all_namespaces()
return [{"name": p.metadata.name, "namespace": p.metadata.namespace,
"pod_selector": p.spec.pod_selector.match_labels or {},
"policy_types": p.spec.policy_types or [],
"ingress_rules": len(p.spec.ingress or []),
"egress_rules": len(p.spec.egress or [])}
for p in policies.items]
def list_calico_policies(self):
"""List Calico-specific NetworkPolicy and GlobalNetworkPolicy resources."""
policies = []
stdout, rc = self._run_calicoctl(["get", "networkpolicy", "-o", "json", "--all-namespaces"])
if rc == 0 and stdout.strip():
try:
data = json.loads(stdout)
items = data.get("items", [data]) if "items" in data else [data]
for item in items:
meta = item.get("metadata", {})
policies.append({"kind": "NetworkPolicy", "name": meta.get("name"),
"namespace": meta.get("namespace")})
except json.JSONDecodeError:
pass
stdout, rc = self._run_calicoctl(["get", "globalnetworkpolicy", "-o", "json"])
if rc == 0 and stdout.strip():
try:
data = json.loads(stdout)
items = data.get("items", [data]) if "items" in data else [data]
for item in items:
policies.append({"kind": "GlobalNetworkPolicy",
"name": item.get("metadata", {}).get("name")})
except json.JSONDecodeError:
pass
return policies
def find_unprotected_namespaces(self):
"""Identify namespaces without any network policies."""
if not self.v1 or not self.net_v1:
return []
namespaces = [ns.metadata.name for ns in self.v1.list_namespace().items]
policies = self.net_v1.list_network_policy_for_all_namespaces()
protected = {p.metadata.namespace for p in policies.items}
system_ns = {"kube-system", "kube-public", "kube-node-lease", "calico-system"}
unprotected = [ns for ns in namespaces if ns not in protected and ns not in system_ns]
for ns in unprotected:
self.findings.append({"severity": "high", "type": "Unprotected Namespace",
"detail": f"Namespace '{ns}' has no network policies"})
return unprotected
def generate_default_deny(self, namespace):
"""Generate default-deny policy manifests for a namespace."""
ingress = {**DEFAULT_DENY_INGRESS, "metadata": {**DEFAULT_DENY_INGRESS["metadata"],
"namespace": namespace}}
egress = {**DEFAULT_DENY_EGRESS, "metadata": {**DEFAULT_DENY_EGRESS["metadata"],
"namespace": namespace}}
return {"namespace": namespace, "ingress_policy": ingress, "egress_policy": egress}
def check_calico_node_status(self):
"""Check Calico node status using calicoctl."""
stdout, rc = self._run_calicoctl(["node", "status"])
if rc == 0:
return {"status": "healthy", "output": stdout[:500]}
return {"status": "unavailable"}
def test_connectivity(self, src_pod, dst_pod, namespace, port=80):
"""Test pod-to-pod connectivity using kubectl exec."""
try:
result = subprocess.run(
["kubectl", "exec", src_pod, "-n", namespace, "--",
"wget", "--spider", "--timeout=3", f"http://{dst_pod}:{port}"],
capture_output=True, text=True, timeout=10,
)
return {"src": src_pod, "dst": dst_pod, "port": port,
"connected": result.returncode == 0}
except (FileNotFoundError, subprocess.TimeoutExpired):
return {"src": src_pod, "dst": dst_pod, "connected": None, "error": "test failed"}
def generate_report(self):
k8s_policies = self.list_k8s_network_policies()
calico_policies = self.list_calico_policies()
unprotected = self.find_unprotected_namespaces()
node_status = self.check_calico_node_status()
deny_manifests = [self.generate_default_deny(ns) for ns in unprotected[:5]]
report = {
"report_date": datetime.utcnow().isoformat(),
"k8s_network_policies": {"count": len(k8s_policies), "policies": k8s_policies},
"calico_policies": {"count": len(calico_policies), "policies": calico_policies},
"unprotected_namespaces": unprotected,
"calico_node_status": node_status,
"recommended_deny_policies": deny_manifests,
"findings": self.findings,
"total_findings": len(self.findings),
}
out = self.output_dir / "calico_policy_report.json"
with open(out, "w") as f:
json.dump(report, f, indent=2)
print(json.dumps(report, indent=2))
return report
def main():
parser = argparse.ArgumentParser(
description="Audit and manage Calico network policies on Kubernetes"
)
parser.add_argument("--kubeconfig", default=None,
help="Path to kubeconfig file")
parser.add_argument("--output-dir", default="./calico_policy_audit",
help="Output directory for report")
args = parser.parse_args()
os.makedirs(args.output_dir, exist_ok=True)
agent = CalicoNetworkPolicyAgent(kubeconfig=args.kubeconfig,
output_dir=args.output_dir)
agent.generate_report()
if __name__ == "__main__":
main()