Skip to content

Commit

Permalink
specify acl on service directly
Browse files Browse the repository at this point in the history
  • Loading branch information
tchinmai7 committed Jan 22, 2024
1 parent 2b836cc commit 135c0dd
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 44 deletions.
2 changes: 1 addition & 1 deletion cloud/linode/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const (
annLinodeHostnameOnlyIngress = "service.beta.kubernetes.io/linode-loadbalancer-hostname-only-ingress"
annLinodeLoadBalancerTags = "service.beta.kubernetes.io/linode-loadbalancer-tags"
annLinodeCloudFirewallID = "service.beta.kubernetes.io/linode-loadbalancer-firewall-id"
annLinodeCloudFirewallCM = "service.beta.kubernetes.io/linode-loadbalancer-firewall-cm"
annLinodeCloudFirewallACL = "service.beta.kubernetes.io/linode-loadbalancer-firewall-acl"

annLinodeNodePrivateIP = "node.k8s.linode.com/private-ip"
annLinodeHostUUID = "node.k8s.linode.com/host-uuid"
Expand Down
57 changes: 27 additions & 30 deletions cloud/linode/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,21 +555,14 @@ func (l *loadbalancers) getLoadBalancerTags(_ context.Context, clusterName strin
return tags
}

func processACL(fwcreateOpts *linodego.FirewallCreateOptions, acl string, aclType, label, cmName, ports string) error {
var allowedIPs linodego.NetworkAddresses
err := json.Unmarshal([]byte(acl), &allowedIPs)
if err != nil {
klog.Error("Error marshalling IPs in allowList")
return err
}

func processACL(fwcreateOpts *linodego.FirewallCreateOptions, aclType, label, svcName, ports string, ips linodego.NetworkAddresses) error {
fwcreateOpts.Rules.Inbound = append(fwcreateOpts.Rules.Inbound, linodego.FirewallRule{
Action: aclType,
Label: fmt.Sprintf("%s-%s", aclType, cmName),
Description: fmt.Sprintf("Created by linode-ccm: %s, from %s", label, cmName),
Label: fmt.Sprintf("%s-%s", aclType, svcName),
Description: fmt.Sprintf("Created by linode-ccm: %s, for %s", label, svcName),
Protocol: linodego.TCP, // Nodebalancers support only TCP.
Ports: ports,
Addresses: allowedIPs,
Addresses: ips,
})
fwcreateOpts.Rules.OutboundPolicy = "ACCEPT"
if aclType == "ACCEPT" {
Expand All @@ -582,40 +575,44 @@ func processACL(fwcreateOpts *linodego.FirewallCreateOptions, acl string, aclTyp
return nil
}

func (l *loadbalancers) createFirewallOptsForSvc(ctx context.Context, fwCM, label string, tags []string, ports []v1.ServicePort) (*linodego.FirewallCreateOptions, error) {
// Fetch config map
cm, err := l.kubeClient.CoreV1().ConfigMaps("kube-system").Get(ctx, fwCM, metav1.GetOptions{})
if err != nil {
return nil, err
}
type aclConfig struct {
AllowList *linodego.NetworkAddresses `json:"allowList"`
DenyList *linodego.NetworkAddresses `json:"denyList"`
}

func (l *loadbalancers) createFirewallOptsForSvc(ctx context.Context, label string, tags []string, svc *v1.Service) (*linodego.FirewallCreateOptions, error) {
// Fetch acl from annotation
aclString := svc.GetAnnotations()[annLinodeCloudFirewallACL]
fwcreateOpts := linodego.FirewallCreateOptions{
Label: label,
Tags: tags,
}

servicePorts := make([]string, len(ports))
for idx, port := range ports {
servicePorts := make([]string, len(svc.Spec.Ports))
for idx, port := range svc.Spec.Ports {
servicePorts[idx] = strconv.Itoa(int(port.Port))
}

portsString := strings.Join(servicePorts[:], ",")
var acl aclConfig
err := json.Unmarshal([]byte(aclString), &acl)
if err != nil {
return nil, err
}

allowListJson, allowListOk := cm.Data[allowListKey]
denyListJson, denyListOk := cm.Data[denyListKey]

if (allowListOk && denyListOk) || (!allowListOk && !denyListOk) {
if (acl.AllowList != nil && acl.DenyList != nil) || (acl.AllowList == nil && acl.DenyList == nil) {
// it is a problem if both are set, or if both are not set
return nil, errInvalidFWConfig
}

aclType := "ACCEPT"
acl := allowListJson
if denyListOk {
allowedIPs := acl.AllowList
if acl.DenyList != nil {
aclType = "DROP"
acl = denyListJson
allowedIPs = acl.DenyList
}

err = processACL(&fwcreateOpts, acl, aclType, label, cm.Name, portsString)
err = processACL(&fwcreateOpts, aclType, label, svc.Name, portsString, *allowedIPs)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -643,10 +640,10 @@ func (l *loadbalancers) createNodeBalancer(ctx context.Context, clusterName stri
}
createOpts.FirewallID = firewallID
} else {
// There's no firewallID already set, see if we need to create a new fw
fwCM, ok := getServiceAnnotation(service, annLinodeCloudFirewallCM)
// There's no firewallID already set, see if we need to create a new fw, look for the acl annotation.
_, ok := service.GetAnnotations()[annLinodeCloudFirewallACL]
if ok {
fwcreateOpts, err := l.createFirewallOptsForSvc(ctx, fwCM, label, tags, service.Spec.Ports)
fwcreateOpts, err := l.createFirewallOptsForSvc(ctx, label, tags, service)
firewall, err := l.client.CreateFirewall(ctx, *fwcreateOpts)
if err != nil {
return nil, err
Expand Down
11 changes: 0 additions & 11 deletions examples/firewall.yaml

This file was deleted.

9 changes: 7 additions & 2 deletions examples/http-nginx.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ metadata:
namespace: kube-system
annotations:
service.beta.kubernetes.io/linode-loadbalancer-default-protocol: "http"
service.beta.kubernetes.io/linode-loadbalancer-firewall-cm: "firewall-rules"
service.beta.kubernetes.io/linode-loadbalancer-firewall-acl: |
{
"denyList": {
"ipv4": ["8.8.8.8/32"],
}
}
spec:
type: LoadBalancer
selector:
Expand All @@ -22,7 +27,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-http-deployment
namespace: kube-system
namespace: kube-system
spec:
replicas: 2
selector:
Expand Down

0 comments on commit 135c0dd

Please sign in to comment.