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)

Open
#911 2 comments 1 reaction 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.