From 6b85bf78c0f7018f393679bcc27282c231f714ab Mon Sep 17 00:00:00 2001 From: Vegard Engen Date: Sun, 20 Apr 2025 10:30:21 +0200 Subject: [PATCH] Add status fields and finalizer --- api/v1beta1/firewallrule_types.go | 15 +- .../unifi.engen.priv.no_firewallrules.yaml | 13 +- .../controller/firewallgroup_controller.go | 4 + .../controller/firewallrule_controller.go | 445 ++++++++++++------ 4 files changed, 325 insertions(+), 152 deletions(-) diff --git a/api/v1beta1/firewallrule_types.go b/api/v1beta1/firewallrule_types.go index 9fb72c6..54ab304 100644 --- a/api/v1beta1/firewallrule_types.go +++ b/api/v1beta1/firewallrule_types.go @@ -40,9 +40,6 @@ import ( //} type FirewallRuleSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - Name string `json:"name"` Source FirewallSource `json:"source"` Destination FirewallDestination `json:"destination"` @@ -52,9 +49,6 @@ type FirewallRuleSpec struct { // FirewallRuleStatus defines the observed state of FirewallRule. type FirewallRuleStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file - ResourcesManaged *FirewallRuleResourcesManaged `json:"resources_managed,omitempty"` } @@ -64,9 +58,12 @@ type FirewallRuleResourcesManaged struct { } type UnifiFirewallRuleEntry struct { - From string `json:"from"` - To string `json:"to"` - RuleID string `json:"rule_id"` + From string `json:"from"` + To string `json:"to"` + TcpIpv4ID string `json:"tcpipv4_id"` + UdpIpv4ID string `json:"udpipv4_id"` + TcpIpv6ID string `json:"tcpipv6_id"` + UdpIpv6ID string `json:"udpipv6_id"` } // +kubebuilder:object:root=true diff --git a/config/crd/bases/unifi.engen.priv.no_firewallrules.yaml b/config/crd/bases/unifi.engen.priv.no_firewallrules.yaml index ffb7612..b6d8c1b 100644 --- a/config/crd/bases/unifi.engen.priv.no_firewallrules.yaml +++ b/config/crd/bases/unifi.engen.priv.no_firewallrules.yaml @@ -110,14 +110,23 @@ spec: properties: from: type: string - rule_id: + tcpipv4_id: + type: string + tcpipv6_id: type: string to: type: string + udpipv4_id: + type: string + udpipv6_id: + type: string required: - from - - rule_id + - tcpipv4_id + - tcpipv6_id - to + - udpipv4_id + - udpipv6_id type: object type: array type: object diff --git a/internal/controller/firewallgroup_controller.go b/internal/controller/firewallgroup_controller.go index 05529b9..105b3ae 100644 --- a/internal/controller/firewallgroup_controller.go +++ b/internal/controller/firewallgroup_controller.go @@ -97,6 +97,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R log.Info("Running finalizer logic for FirewallGroup", "name", firewallGroup.Name) if len(firewallGroup.Status.ResourcesManaged.IPV4Object.ID) > 0 { + log.Info(fmt.Sprintf("Trying to delete ipv4 object %s", firewallGroup.Status.ResourcesManaged.IPV4Object.ID)) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV4Object.ID) if err != nil { msg := strings.ToLower(err.Error()) @@ -123,6 +124,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R } } if len(firewallGroup.Status.ResourcesManaged.IPV6Object.ID) > 0 { + log.Info(fmt.Sprintf("Trying to delete ipv6 object %s", firewallGroup.Status.ResourcesManaged.IPV6Object.ID)) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV6Object.ID) if err != nil { msg := strings.ToLower(err.Error()) @@ -149,6 +151,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R } } if len(firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID) > 0 { + log.Info(fmt.Sprintf("Trying to delete tcp object %s", firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID)) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID) if err != nil { msg := strings.ToLower(err.Error()) @@ -175,6 +178,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R } } if len(firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID) > 0 { + log.Info(fmt.Sprintf("Trying to delete udp object %s", firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID)) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID) if err != nil { msg := strings.ToLower(err.Error()) diff --git a/internal/controller/firewallrule_controller.go b/internal/controller/firewallrule_controller.go index daec052..a132a9b 100644 --- a/internal/controller/firewallrule_controller.go +++ b/internal/controller/firewallrule_controller.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" @@ -45,6 +46,8 @@ type FirewallRuleReconciler struct { ConfigLoader *config.ConfigLoaderType } +const firewallRuleFinalizer = "finalizer.unifi.engen.priv.no/firewallrule" + // +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=firewallrules,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=firewallrules/status,verbs=get;update;patch // +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=firewallrules/finalizers,verbs=update @@ -115,6 +118,101 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request } log.Info(firewallRule.Spec.Name) + if firewallRule.DeletionTimestamp != nil { + if controllerutil.ContainsFinalizer(&firewallRule, firewallRuleFinalizer) { + err := r.UnifiClient.Reauthenticate() + if err != nil { + return ctrl.Result{}, err + } + log.Info("Running finalizer logic for FirewallRule", "name", firewallRule.Name) + + if len(firewallRule.Status.ResourcesManaged.UnifiFirewallRules) > 0 { + for i, UnifiFirewallRule := range firewallRule.Status.ResourcesManaged.UnifiFirewallRules { + if len(UnifiFirewallRule.TcpIpv4ID) > 0 { + err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallRule.TcpIpv4ID) + if err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } else { + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv4ID = "" + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + } + } + if len(UnifiFirewallRule.UdpIpv4ID) > 0 { + err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallRule.UdpIpv4ID) + if err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } else { + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv4ID = "" + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + } + } + if len(UnifiFirewallRule.TcpIpv6ID) > 0 { + err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallRule.TcpIpv6ID) + if err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } else { + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv6ID = "" + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + } + } + if len(UnifiFirewallRule.UdpIpv6ID) > 0 { + err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallRule.UdpIpv6ID) + if err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } else { + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv6ID = "" + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + } + } + } + } + + if len(firewallRule.Status.ResourcesManaged.FirewallGroups) > 0 { + for i, firewallGroup := range firewallRule.Status.ResourcesManaged.FirewallGroups { + var firewallGroupCRD unifiv1beta1.FirewallGroup + if firewallGroup.Name != "" { + if err := r.Get(ctx, types.NamespacedName{Name: firewallGroup.Name, Namespace: firewallGroupCRD.Namespace}, &firewallGroupCRD); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + if err := r.Delete(ctx, &firewallGroupCRD); err != nil { + log.Error(err, "Could not delete firewall group") + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + firewallRule.Status.ResourcesManaged.FirewallGroups[i].Name = "" + firewallRule.Status.ResourcesManaged.FirewallGroups[i].Namespace = "" + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{RequeueAfter: 10 * time.Minute}, err + } + } + } + } + controllerutil.RemoveFinalizer(&firewallRule, firewallRuleFinalizer) + if err := r.Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } + + log.Info("Successfully finalized FirewallGroup") + } + return ctrl.Result{}, nil + } + if !controllerutil.ContainsFinalizer(&firewallRule, firewallRuleFinalizer) { + controllerutil.AddFinalizer(&firewallRule, firewallRuleFinalizer) + if err := r.Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } + } + + firewallruleindex := make(map[string]int) + + nextIndex := 0 if firewallRule.Status.ResourcesManaged == nil { firewallGroupsManaged := []unifiv1beta1.FirewallGroupEntry{} unifiFirewallRules := []unifiv1beta1.UnifiFirewallRuleEntry{} @@ -122,6 +220,11 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request UnifiFirewallRules: unifiFirewallRules, FirewallGroups: firewallGroupsManaged, } + } else { + for index, firewallRuleEntry := range firewallRule.Status.ResourcesManaged.UnifiFirewallRules { + firewallruleindex[firewallRuleEntry.From+"/"+firewallRuleEntry.To] = index + nextIndex = nextIndex + 1 + } } err = r.UnifiClient.Reauthenticate() if err != nil { @@ -297,35 +400,53 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request if i, found := zoneCRDNames[namespace+"/"+zoneEntry.Name]; found { log.Info(fmt.Sprintf("Creating firewallrules for %s", zoneCRDs.Items[i].Name)) for _, firewallGroup := range myFirewallGroups { + i, found := firewallruleindex["zone:"+zoneCRDs.Items[i].Name+"/"+firewallGroup.Name] + if !found { + firewallRuleEntry := unifiv1beta1.UnifiFirewallRuleEntry{ + From: "zone:" + zoneCRDs.Items[i].Name, + To: firewallGroup.Name, + TcpIpv4ID: "", + UdpIpv4ID: "", + TcpIpv6ID: "", + UdpIpv6ID: "", + } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules = append(firewallRule.Status.ResourcesManaged.UnifiFirewallRules, firewallRuleEntry) + i = nextIndex + nextIndex = nextIndex + 1 + } + if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { rulename := "k8s-fw-" + firewallRule.Name + "-" + zoneCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv4-tcp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv4 tcp firewallrule for %s to %s: %s", zoneCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID - firewallRule.Source.MatchingTarget = "ANY" - firewallRule.Protocol = "tcp" - firewallRule.IPVersion = "IPV4" - firewallRule.Description = fmt.Sprintf("Allow tcp IPV4 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID + unifiFirewallRule.Source.MatchingTarget = "ANY" + unifiFirewallRule.Protocol = "tcp" + unifiFirewallRule.IPVersion = "IPV4" + unifiFirewallRule.Description = fmt.Sprintf("Allow tcp IPV4 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } - + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv4ID = updatedRule.ID + if err = r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv4 tcp %s to %s already exists", zoneCRDs.Items[i].Name, firewallGroup.Name)) } @@ -334,29 +455,33 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + zoneCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv4-udp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv4 udp firewallrule for %s to %s: %s", zoneCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID - firewallRule.Source.MatchingTarget = "ANY" - firewallRule.Protocol = "udp" - firewallRule.IPVersion = "IPV4" - firewallRule.Description = fmt.Sprintf("Allow udp IPV4 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID + unifiFirewallRule.Source.MatchingTarget = "ANY" + unifiFirewallRule.Protocol = "udp" + unifiFirewallRule.IPVersion = "IPV4" + unifiFirewallRule.Description = fmt.Sprintf("Allow udp IPV4 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv4ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv4 udp %s to %s already exists", zoneCRDs.Items[i].Name, firewallGroup.Name)) @@ -368,29 +493,33 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + zoneCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv6-tcp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv6 tcp firewallrule for %s to %s: %s", zoneCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID - firewallRule.Source.MatchingTarget = "ANY" - firewallRule.Protocol = "tcp" - firewallRule.IPVersion = "IPV6" - firewallRule.Description = fmt.Sprintf("Allow tcp IPV6 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID + unifiFirewallRule.Source.MatchingTarget = "ANY" + unifiFirewallRule.Protocol = "tcp" + unifiFirewallRule.IPVersion = "IPV6" + unifiFirewallRule.Description = fmt.Sprintf("Allow tcp IPV6 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv6ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv6 tcp %s to %s already exists", zoneCRDs.Items[i].Name, firewallGroup.Name)) @@ -400,29 +529,33 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + zoneCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv6-udp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv6 udp firewallrule for %s to %s: %s", zoneCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID - firewallRule.Source.MatchingTarget = "ANY" - firewallRule.Protocol = "udp" - firewallRule.IPVersion = "IPV6" - firewallRule.Description = fmt.Sprintf("Allow udp IPV6 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = zoneCRDs.Items[i].Spec.ID + unifiFirewallRule.Source.MatchingTarget = "ANY" + unifiFirewallRule.Protocol = "udp" + unifiFirewallRule.IPVersion = "IPV6" + unifiFirewallRule.Description = fmt.Sprintf("Allow udp IPV6 from %s to %s", zoneCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from zone %s to %s: %+v", zoneCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv6ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv6 udp %s to %s already exists", zoneCRDs.Items[i].Name, firewallGroup.Name)) @@ -440,36 +573,54 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request if i, found := networkCRDNames[namespace+"/"+networkEntry.Name]; found { log.Info(fmt.Sprintf("Creating firewallrules for %s", networkCRDs.Items[i].Name)) for _, firewallGroup := range myFirewallGroups { + i, found := firewallruleindex["network:"+networkCRDs.Items[i].Name+"/"+firewallGroup.Name] + if !found { + firewallRuleEntry := unifiv1beta1.UnifiFirewallRuleEntry{ + From: "zone:" + networkCRDs.Items[i].Name, + To: firewallGroup.Name, + TcpIpv4ID: "", + UdpIpv4ID: "", + TcpIpv6ID: "", + UdpIpv6ID: "", + } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules = append(firewallRule.Status.ResourcesManaged.UnifiFirewallRules, firewallRuleEntry) + i = nextIndex + nextIndex = nextIndex + 1 + } if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { rulename := "k8s-fw-" + firewallRule.Name + "-" + networkCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv4-tcp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv4 tcp firewallrule for %s to %s: %s", networkCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID - firewallRule.Source.MatchingTarget = "NETWORK" - firewallRule.Protocol = "tcp" - firewallRule.IPVersion = "IPV4" - firewallRule.Description = fmt.Sprintf("Allow tcp IPV4 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID + unifiFirewallRule.Source.MatchingTarget = "NETWORK" + unifiFirewallRule.Protocol = "tcp" + unifiFirewallRule.IPVersion = "IPV4" + unifiFirewallRule.Description = fmt.Sprintf("Allow tcp IPV4 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv4ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv4 tcp %s to %s already exists", networkCRDs.Items[i].Name, firewallGroup.Name)) } @@ -478,30 +629,34 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + networkCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv4-udp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv4 udp firewallrule for %s to %s: %s", networkCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID - firewallRule.Source.MatchingTarget = "NETWORK" - firewallRule.Protocol = "udp" - firewallRule.IPVersion = "IPV4" - firewallRule.Description = fmt.Sprintf("Allow udp IPV4 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID + unifiFirewallRule.Source.MatchingTarget = "NETWORK" + unifiFirewallRule.Protocol = "udp" + unifiFirewallRule.IPVersion = "IPV4" + unifiFirewallRule.Description = fmt.Sprintf("Allow udp IPV4 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV4Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv4ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv4 udp %s to %s already exists", networkCRDs.Items[i].Name, firewallGroup.Name)) @@ -513,30 +668,34 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + networkCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv6-tcp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv6 tcp firewallrule for %s to %s: %s", networkCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID - firewallRule.Source.MatchingTarget = "NETWORK" - firewallRule.Protocol = "tcp" - firewallRule.IPVersion = "IPV6" - firewallRule.Description = fmt.Sprintf("Allow tcp IPV6 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID + unifiFirewallRule.Source.MatchingTarget = "NETWORK" + unifiFirewallRule.Protocol = "tcp" + unifiFirewallRule.IPVersion = "IPV6" + unifiFirewallRule.Description = fmt.Sprintf("Allow tcp IPV6 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].TcpIpv6ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv6 tcp %s to %s already exists", networkCRDs.Items[i].Name, firewallGroup.Name)) @@ -546,30 +705,34 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request rulename := "k8s-fw-" + firewallRule.Name + "-" + networkCRDs.Items[i].Name + "-" + firewallGroup.Name + "-ipv6-udp" if _, found := unifiFirewallruleNames[rulename]; !found { log.Info(fmt.Sprintf("Creating ipv6 udp firewallrule for %s to %s: %s", networkCRDs.Items[i].Name, firewallGroup.Name, rulename)) - firewallRule := fillDefaultRule() - firewallRule.Name = rulename - firewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} - firewallRule.Source.PortMatchingType = "ANY" - firewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID - firewallRule.Source.MatchingTarget = "NETWORK" - firewallRule.Protocol = "udp" - firewallRule.IPVersion = "IPV6" - firewallRule.Description = fmt.Sprintf("Allow udp IPV6 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) - firewallRule.Destination.MatchingTargetType = "OBJECT" - firewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID - firewallRule.Destination.MatchingTarget = "IP" - firewallRule.Destination.PortMatchingType = "OBJECT" - firewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID - firewallRule.Destination.ZoneID = kubernetesZoneID + unifiFirewallRule := fillDefaultRule() + unifiFirewallRule.Name = rulename + unifiFirewallRule.Source.NetworkIDs = []string{networkCRDs.Items[i].Spec.ID} + unifiFirewallRule.Source.PortMatchingType = "ANY" + unifiFirewallRule.Source.ZoneID = networkCRDs.Items[i].Status.FirewallZoneID + unifiFirewallRule.Source.MatchingTarget = "NETWORK" + unifiFirewallRule.Protocol = "udp" + unifiFirewallRule.IPVersion = "IPV6" + unifiFirewallRule.Description = fmt.Sprintf("Allow udp IPV6 from %s to %s", networkCRDs.Items[i].Name, firewallGroup.Name) + unifiFirewallRule.Destination.MatchingTargetType = "OBJECT" + unifiFirewallRule.Destination.IPGroupID = firewallGroup.Status.ResourcesManaged.IPV6Object.ID + unifiFirewallRule.Destination.MatchingTarget = "IP" + unifiFirewallRule.Destination.PortMatchingType = "OBJECT" + unifiFirewallRule.Destination.PortGroupID = firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID + unifiFirewallRule.Destination.ZoneID = kubernetesZoneID - log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, firewallRule)) - pretty, _ := json.MarshalIndent(firewallRule, "", " ") + log.Info(fmt.Sprintf("Trying to create firewall rule from network %s to %s: %+v", networkCRDs.Items[i].Name, firewallGroup.Name, unifiFirewallRule)) + pretty, _ := json.MarshalIndent(unifiFirewallRule, "", " ") log.Info(string(pretty)) - _, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &firewallRule) + updatedRule, err := r.UnifiClient.Client.CreateFirewallPolicy(context.Background(), r.UnifiClient.SiteID, &unifiFirewallRule) if err != nil { log.Error(err, "Could not create firewall policy") return ctrl.Result{}, err } + firewallRule.Status.ResourcesManaged.UnifiFirewallRules[i].UdpIpv6ID = updatedRule.ID + if err := r.Status().Update(ctx, &firewallRule); err != nil { + return ctrl.Result{}, err + } } else { log.Info(fmt.Sprintf("Firewall rule for ipv6 udp %s to %s already exists", networkCRDs.Items[i].Name, firewallGroup.Name))