This PoC demonstrates intercepting CSI driver calls at the gRPC layer by inserting a proxy between CSI sidecar containers and the actual CSI driver.
┌─────────────────────────────────────────────────────────────┐
│ CSI Driver Pod │
│ │
│ external-provisioner ─┐ │
│ external-attacher ├─→ /csi/csi.sock │
│ external-resizer ─┘ ↓ │
│ ┌───────────────────┐ │
│ │ Interceptor Proxy │ │
│ │ - Logs all RPCs │ │
│ │ - Policy checks │ │
│ │ - Can reject │ │
│ └───────────────────┘ │
│ ↓ │
│ /driver/csi.sock │
│ ↓ │
│ ┌───────────────────┐ │
│ │ Real CSI Driver │ │
│ │ (hostpath-csi) │ │
│ └───────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Proxy Socket: Sidecars connect to
/csi/csi.sock(interceptor) - Driver Socket: Real driver binds to
/driver/csi.sock - gRPC Proxy: Implements
csi.ControllerServerandcsi.NodeServer - Request Flow: Log → Policy Check → Forward → Log Response
- Policy Rejection: Returns gRPC error codes (PermissionDenied, ResourceExhausted)
- ✅ CreateVolume / DeleteVolume
- ✅ ControllerPublishVolume / ControllerUnpublishVolume
- ✅ CreateSnapshot / DeleteSnapshot
- ✅ ControllerExpandVolume
- ✅ ListVolumes, GetCapacity, ValidateVolumeCapabilities
- ✅ NodePublishVolume / NodeUnpublishVolume
- ✅ NodeStageVolume / NodeUnstageVolume
- ✅ NodeExpandVolume
- ✅ NodeGetVolumeStats, NodeGetCapabilities, NodeGetInfo
Allows all operations (for basic PoC testing)
policy := policy.NewQuotaChecker(10 * 1024 * 1024 * 1024) // 10GB max
// Rejects CreateVolume if size > 10GBtype OSACPolicyChecker struct {
controlPlaneClient osac.Client
}
func (o *OSACPolicyChecker) CheckCreateVolume(ctx, req) error {
// Call OSAC control plane
allowed, err := o.controlPlaneClient.CheckQuota(...)
if !allowed {
return status.Error(codes.ResourceExhausted, "quota exceeded")
}
return nil
}go build -o csi-proxy cmd/proxy/main.go# Terminal 1: Start a mock CSI driver on /driver/csi.sock
# (or use real hostpath driver)
# Terminal 2: Start the proxy
./csi-proxy \
--proxy-socket=/tmp/csi.sock \
--driver-socket=/driver/csi.sock \
--logger-url=http://localhost:8080/log
# Terminal 3: Test with csc (CSI command-line tool)
csc controller create-volume test-vol --endpoint=unix:///tmp/csi.sockThe proxy runs as a sidecar in the CSI driver pod:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: csi-hostpath-driver
spec:
template:
spec:
containers:
# CSI sidecars connect to /csi/csi.sock
- name: external-provisioner
volumeMounts:
- name: socket-dir
mountPath: /csi
# Interceptor proxy
- name: csi-interceptor
image: csi-interceptor:latest
args:
- --proxy-socket=/csi/csi.sock
- --driver-socket=/driver/csi.sock
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: driver-socket-dir
mountPath: /driver
# Real driver binds to /driver/csi.sock
- name: hostpath-driver
args:
- --endpoint=unix:///driver/csi.sock
volumeMounts:
- name: driver-socket-dir
mountPath: /driver
volumes:
- name: socket-dir
emptyDir: {}
- name: driver-socket-dir
emptyDir: {}Each CSI RPC produces two log entries:
Request:
{
"timestamp": "2026-05-20T12:34:56Z",
"direction": "request",
"method": "CreateVolume",
"parameters": {
"name": "pvc-12345",
"capacity": "1073741824"
}
}Response:
{
"timestamp": "2026-05-20T12:34:57Z",
"direction": "response",
"method": "CreateVolume",
"parameters": {
"volume_id": "vol-abcdef"
},
"latency": "123ms"
}Policy Rejection:
{
"timestamp": "2026-05-20T12:35:00Z",
"direction": "response",
"method": "CreateVolume",
"error": "rpc error: code = ResourceExhausted desc = quota exceeded",
"latency": "5ms"
}| Aspect | gRPC Proxy (this PoC) | Admission Webhook |
|---|---|---|
| Interception Point | CSI driver gRPC calls | Kubernetes API |
| Visibility | Full CSI operation details | PVC/VolumeAttachment metadata only |
| Can Modify | Can modify RPC params | Can reject, not modify |
| Driver Agnostic | Works with ANY CSI driver | Works regardless of driver |
| Deployment | Inject into driver pod | Separate webhook deployment |
| Latency | Per-RPC overhead | Per-API-call overhead |
| Policy Scope | Driver-level (size, IOPS) | Resource-level (quota, tenant) |
- Audit Logging: Track all volume operations with full context
- Policy Enforcement: Reject operations based on OSAC control plane decisions
- Testing: Inject failures, delays for chaos engineering
- Multi-Tenancy: Enforce tenant isolation at driver level
- Quota Management: Reject over-quota volume creates
- Performance Monitoring: Track CSI RPC latencies
- Requires modifying CSI driver deployment (socket paths)
- Adds latency to every CSI operation
- Must implement all CSI RPC methods (even if just pass-through)
- Identity service currently pass-through (could intercept too)
- Implement full Identity service interception
- Add metrics (Prometheus)
- Support bidirectional streaming RPCs
- Add request/response caching
- Circuit breaker for driver failures
- Rate limiting per tenant
- Integration with OSAC control plane API
Apache 2.0