digitalocean / digitalocean/digitalocean-cloud-controller-manager
firewall_controller: no way to restrict inbound source CIDRs for LoadBalancer services on DOKS (hardcoded to 0.0.0.0/0)
- Dominant language
- Go
- Stars
- 574
- Forks
- 153
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 3
Description
## Problem
When using a DOKS cluster with a `LoadBalancer` type Service, the CCM automatically
manages a `k8s-public-access-*` firewall and adds inbound rules for the service ports
(e.g. 80, 443) with source hardcoded to `0.0.0.0/0` / `::/0`.
There is no way to restrict these rules to private or specific CIDRs only.
Any manual changes to the firewall are reverted by the controller on the next
reconcile.
## Expected behavior
Allow specifying allowed source CIDRs for the auto-managed firewall inbound rules,
for example via a Service annotation or a CCM environment variable — similar to how
`spec.loadBalancerSourceRanges` works for the Load Balancer itself.
## Use case
Clusters behind Cloudflare (or any CDN/proxy) should only accept traffic from
the CDN IP ranges — not from the entire internet. Right now this is only possible
at the Load Balancer level (`spec.loadBalancerSourceRanges`), but the node-level
firewall stays wide open regardless.
While digging into the source, found a related inconsistency worth noting:
The annotation `kubernetes.digitalocean.com/firewall-managed: "false"` already exists and **works for `NodePort` services** — when set, the controller skips adding that service's ports to the firewall ([firewall_controller.go ~L286](https://github.com/digitalocean/digitalocean-cloud-controller-manager/blob/master/cloud-controller-manager/do/firewall_controller.go#L286)):
```go
// NodePort branch — annotation IS checked
if !managed {
continue // port not added to k8s-public-access
}
```
But for `LoadBalancer` services, `isManaged()` is **never called** — the ports are always added with `0.0.0.0/0` regardless of the annotation ([same file, ~L323](https://github.com/digitalocean/digitalocean-cloud-controller-manager/blob/master/cloud-controller-manager/do/firewall_controller.go#L323)):
```go
} else if svc.Spec.Type == v1.ServiceTypeLoadBalancer {
// isManaged() is not called here — annotation is ignored
loadBalancerPorts[portProtocol{...}] = struct{}{}
}
```
A minimal fix would be to extend the existing `isManaged()` check to the `LoadBalancer` branch as well. Alternatively, for source CIDR restriction, the controller could read `spec.loadBalancerSourceRanges` (already parsed in `loadbalancers.go` via `getSourceRangeRules()`) and use those as inbound rule sources instead of hardcoded `0.0.0.0/0`.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.