KubeGuard is a Kubernetes admission controller that monitors shell access (kubectl exec) and port forwarding (kubectl port-forward) activities in specified namespaces and sends notifications to Mattermost.
- Shell Access Monitoring: Detects when users execute shells in pods via
kubectl exec - Port Forward Monitoring: Detects when users create port forwards via
kubectl port-forward - Mattermost Integration: Sends detailed notifications to Mattermost channels
- ConfigMap Configuration: Easy configuration management through Kubernetes ConfigMaps
- Namespace Filtering: Monitor specific namespaces (default:
my-namespace) - User Information: Includes user details in notifications for better auditing
-
Clone and build:
git clone <repository> cd kube-guard
-
Deploy with Helm:
./helm-deploy.sh --webhook-url "https://your-mattermost.example.com/hooks/your-webhook-id"Or with custom namespace monitoring:
./helm-deploy.sh \ --webhook-url "https://your-mattermost.example.com/hooks/your-webhook-id" \ --monitored-namespace "production"
-
Test:
kubectl exec -it <pod-name> -n my-namespace -- /bin/bash
-
Clone and build:
git clone <repository> cd kube-guard
-
Update configuration: Edit
k8s/configmap.yamlto set your Mattermost webhook URL:data: config.yaml: | mattermost: webhook_url: "https://your-mattermost.example.com/hooks/your-webhook-id" channel: "alerts" monitored_namespace: "my-namespace"
-
Deploy:
./deploy.sh
When using Helm, configure KubeGuard through values.yaml or command-line parameters:
config:
mattermost:
webhookUrl: "https://your-mattermost.example.com/hooks/your-webhook-id"
channel: "alerts"
monitoredNamespaces:
- "*"
namespaceChannels:
- channel: "team-a-alerts"
namespaces: ["team-a", "team-a-staging"]
- channel: "team-b-alerts"
webhookUrl: "https://mattermost.team-b.example.com/hooks/xyz789"
namespaces: ["team-b"]
notifications:
shellAccess: true
portForward: trueKey Helm values:
config.mattermost.webhookUrl: Your Mattermost incoming webhook URLconfig.mattermost.channel: Global channel for notifications (without #)config.monitoredNamespaces: List of namespaces to monitor;["*"]monitors allconfig.namespaceChannels: Per-namespace channel routing (see below)config.notifications.*: Enable/disable individual detection types
namespaceChannels routes alerts for specific namespaces to additional channels:
- The global channel (
config.mattermost.channel) always receives every alert; a matchingnamespaceChannelsentry sends the alert to its channel in addition. - Namespaces listed in a
namespaceChannelsentry are monitored even if they are not inmonitoredNamespaces. - An entry may set its own
webhookUrlto post to a different Mattermost hook — e.g. another team's workspace. If omitted, the global webhook is used. Notification toggles are always global. - Cluster-scoped alerts (e.g. ClusterRole changes) go only to the global channel. Namespaced RBAC changes and namespace deletions are routed by their namespace.
When using raw Kubernetes manifests, configure via ConfigMap (kube-guard-config):
mattermost:
webhook_url: "https://your-mattermost.example.com/hooks/your-webhook-id"
channel: "alerts"
monitored_namespaces:
- "*"
namespace_channels:
- channel: "team-a-alerts"
namespaces: ["team-a", "team-a-staging"]
- channel: "team-b-alerts"
webhook_url: "https://mattermost.team-b.example.com/hooks/xyz789"
namespaces: ["team-b"]
notifications:
shell_access: true
port_forward: true┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ kubectl exec │───▶│ API Server │───▶│ KubeGuard │
│kubectl port-fwd │ │ │ │ Admission │
└─────────────────┘ └─────────────────┘ │ Controller │
└─────────────────┘
│
▼
┌─────────────────┐
│ Mattermost │
│ Channel │
└─────────────────┘
Shell access notifications:
⚠️ Shell Access Alert
User: john.doe@company.com
Namespace: my-namespace
Pod: web-app-123
Action: Shell access (kubectl exec)
Time: 2024-01-15 14:30:25 UTC
Port forward notifications:
⚠️ Port Forward Alert
User: jane.smith@company.com
Namespace: my-namespace
Pod: database-456
Action: Port forwarding
Time: 2024-01-15 14:31:10 UTC
- The admission controller runs with minimal RBAC permissions
- Uses non-root user in container
- Read-only root filesystem
- TLS encryption for webhook communication
- Fails open (doesn't block operations if webhook fails)
-
Check Helm release status:
helm status kube-guard helm get values kube-guard
-
Check pod logs:
kubectl logs -n kube-guard deployment/kube-guard
-
Update configuration:
helm upgrade kube-guard ./helm/kube-guard \ --set config.mattermost.webhookUrl="NEW_URL"
-
Check pod logs:
kubectl logs -n kube-guard deployment/kube-guard
-
Verify webhook configuration:
kubectl get validatingadmissionwebhooks kube-guard-validator -o yaml
-
Test webhook endpoint:
kubectl port-forward -n kube-guard svc/kube-guard-webhook 8443:443 curl -k https://localhost:8443/healthz
-
Update configuration:
kubectl edit configmap kube-guard-config -n kube-guard kubectl rollout restart deployment/kube-guard -n kube-guard
helm uninstall kube-guard
kubectl delete namespace kube-guardkubectl delete validatingadmissionwebhook kube-guard-validator
kubectl delete mutatingadmissionwebhook kube-guard-mutator
kubectl delete namespace kube-guard