Preliminary scaffolding
This commit is contained in:
20
api/v1beta1/common_types.go
Normal file
20
api/v1beta1/common_types.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package v1beta1
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// FirewallRuleSpec defines the desired state of FirewallRule.
|
||||
type ServiceSpec struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type FirewallSource struct {
|
||||
Zones []string `json:"from_zones,omitempty"`
|
||||
Networks []string `json:"from_networks,omitempty"`
|
||||
}
|
||||
|
||||
type FirewallDestination struct {
|
||||
FirewallGroups []string `json:"firewall_group,omitempty"`
|
||||
Services []ServiceSpec `json:"service,omitempty"`
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// FirewallGroupSpec defines the desired state of FirewallGroup.
|
||||
|
||||
type FirewallGroupSpec struct {
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
@@ -38,14 +39,11 @@ type FirewallGroupSpec struct {
|
||||
ManualAddresses []string `json:"manualAddresses,omitempty"`
|
||||
ManualPorts []string `json:"manualPorts,omitempty"`
|
||||
|
||||
AutoCreatedFrom ServiceSpec `json:"auto_created_from,omitempty"`
|
||||
|
||||
// AutoIncludeSelector defines which services to extract addresses from
|
||||
// +optional
|
||||
AutoIncludeSelector *metav1.LabelSelector `json:"autoIncludeSelector,omitempty"`
|
||||
|
||||
// AddressType can be "ip", "cidr", or "both"
|
||||
// +kubebuilder:validation:Enum=ip;cidr;both
|
||||
// +optional
|
||||
AddressType string `json:"addressType,omitempty"`
|
||||
}
|
||||
|
||||
// FirewallGroupStatus defines the observed state of FirewallGroup.
|
||||
|
||||
@@ -24,12 +24,30 @@ import (
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
// FirewallRuleSpec defines the desired state of FirewallRule.
|
||||
// type ServiceSpec struct {
|
||||
// Namespace string `json:"namespace,omitempty"`
|
||||
// Name string `json:"name,omitempty"`
|
||||
// }
|
||||
|
||||
// type FirewallSource struct {
|
||||
// Zones []string `json:"from_zones,omitempty"`
|
||||
// Networks []string `json:"from_networks,omitempty"`
|
||||
//}
|
||||
|
||||
//type FirewallDestination struct {
|
||||
// FirewallGroups []string `json:"firewall_group,omitempty"`
|
||||
// Services []ServiceSpec `json:"service,omitempty"`
|
||||
//}
|
||||
|
||||
type FirewallRuleSpec struct {
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
|
||||
// Foo is an example field of FirewallRule. Edit firewallrule_types.go to remove/update
|
||||
Foo string `json:"foo,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Source FirewallSource `json:"source"`
|
||||
Destination FirewallDestination `json:"destination"`
|
||||
MatchFirewallGroupsInAllNamespaces bool `json:"match_firewall_groups_in_all_namespaces,omitempty"`
|
||||
MatchServicesInAllNamespaces bool `json:"match_services_in_all_namespaces,omitempty"`
|
||||
}
|
||||
|
||||
// FirewallRuleStatus defines the observed state of FirewallRule.
|
||||
|
||||
@@ -25,6 +25,31 @@ import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FirewallDestination) DeepCopyInto(out *FirewallDestination) {
|
||||
*out = *in
|
||||
if in.FirewallGroups != nil {
|
||||
in, out := &in.FirewallGroups, &out.FirewallGroups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Services != nil {
|
||||
in, out := &in.Services, &out.Services
|
||||
*out = make([]ServiceSpec, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirewallDestination.
|
||||
func (in *FirewallDestination) DeepCopy() *FirewallDestination {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FirewallDestination)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FirewallGroup) DeepCopyInto(out *FirewallGroup) {
|
||||
*out = *in
|
||||
@@ -97,6 +122,7 @@ func (in *FirewallGroupSpec) DeepCopyInto(out *FirewallGroupSpec) {
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
out.AutoCreatedFrom = in.AutoCreatedFrom
|
||||
if in.AutoIncludeSelector != nil {
|
||||
in, out := &in.AutoIncludeSelector, &out.AutoIncludeSelector
|
||||
*out = new(v1.LabelSelector)
|
||||
@@ -143,7 +169,7 @@ func (in *FirewallRule) DeepCopyInto(out *FirewallRule) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
@@ -200,6 +226,8 @@ func (in *FirewallRuleList) DeepCopyObject() runtime.Object {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FirewallRuleSpec) DeepCopyInto(out *FirewallRuleSpec) {
|
||||
*out = *in
|
||||
in.Source.DeepCopyInto(&out.Source)
|
||||
in.Destination.DeepCopyInto(&out.Destination)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirewallRuleSpec.
|
||||
@@ -227,6 +255,31 @@ func (in *FirewallRuleStatus) DeepCopy() *FirewallRuleStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FirewallSource) DeepCopyInto(out *FirewallSource) {
|
||||
*out = *in
|
||||
if in.Zones != nil {
|
||||
in, out := &in.Zones, &out.Zones
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Networks != nil {
|
||||
in, out := &in.Networks, &out.Networks
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirewallSource.
|
||||
func (in *FirewallSource) DeepCopy() *FirewallSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FirewallSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FirewallZone) DeepCopyInto(out *FirewallZone) {
|
||||
*out = *in
|
||||
@@ -413,3 +466,18 @@ func (in *NetworkconfigurationStatus) DeepCopy() *NetworkconfigurationStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec.
|
||||
func (in *ServiceSpec) DeepCopy() *ServiceSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -37,15 +37,15 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: FirewallGroupSpec defines the desired state of FirewallGroup.
|
||||
properties:
|
||||
addressType:
|
||||
description: AddressType can be "ip", "cidr", or "both"
|
||||
enum:
|
||||
- ip
|
||||
- cidr
|
||||
- both
|
||||
type: string
|
||||
auto_created_from:
|
||||
description: FirewallRuleSpec defines the desired state of FirewallRule.
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
autoIncludeSelector:
|
||||
description: AutoIncludeSelector defines which services to extract
|
||||
addresses from
|
||||
|
||||
@@ -37,12 +37,45 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: FirewallRuleSpec defines the desired state of FirewallRule.
|
||||
properties:
|
||||
foo:
|
||||
description: Foo is an example field of FirewallRule. Edit firewallrule_types.go
|
||||
to remove/update
|
||||
destination:
|
||||
properties:
|
||||
firewall_group:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
service:
|
||||
items:
|
||||
description: FirewallRuleSpec defines the desired state of FirewallRule.
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
match_firewall_groups_in_all_namespaces:
|
||||
type: boolean
|
||||
match_services_in_all_namespaces:
|
||||
type: boolean
|
||||
name:
|
||||
type: string
|
||||
source:
|
||||
properties:
|
||||
from_networks:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
from_zones:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
required:
|
||||
- destination
|
||||
- name
|
||||
- source
|
||||
type: object
|
||||
status:
|
||||
description: FirewallRuleStatus defines the observed state of FirewallRule.
|
||||
|
||||
@@ -6,4 +6,3 @@ metadata:
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
name: firewallrule-sample
|
||||
spec:
|
||||
# TODO(user): Add fields here
|
||||
|
||||
@@ -18,10 +18,14 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
|
||||
@@ -41,6 +45,7 @@ type FirewallRuleReconciler struct {
|
||||
// +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
|
||||
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=list;get;watch
|
||||
// +kubebuilder:rbac:groups="",resources=services,verbs=list;get;watch
|
||||
|
||||
// Reconcile is part of the main kubernetes reconciliation loop which aims to
|
||||
// move the current state of the cluster closer to the desired state.
|
||||
@@ -69,13 +74,117 @@ func (r *FirewallRuleReconciler) Reconcile(ctx context.Context, req ctrl.Request
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
var zoneCRDs unifiv1beta1.FirewallZoneList
|
||||
var networkCRDs unifiv1beta1.NetworkconfigurationList
|
||||
|
||||
err = r.List(ctx, &zoneCRDs, client.InNamespace(defaultNs))
|
||||
if err != nil {
|
||||
log.Error(err, "Could not list firewall zones")
|
||||
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
|
||||
}
|
||||
|
||||
zoneCRDNames := make(map[string]struct{})
|
||||
|
||||
for _, zoneCRD := range zoneCRDs.Items {
|
||||
zoneCRDNames[zoneCRD.Name] = struct{}{}
|
||||
}
|
||||
|
||||
err = r.List(ctx, &networkCRDs, client.InNamespace(defaultNs))
|
||||
if err != nil {
|
||||
log.Error(err, "Could not list networks")
|
||||
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
|
||||
}
|
||||
|
||||
networkCRDNames := make(map[string]struct{})
|
||||
|
||||
for _, networkCRD := range networkCRDs.Items {
|
||||
networkCRDNames[networkCRD.Name] = struct{}{}
|
||||
}
|
||||
|
||||
var firewallRule unifiv1beta1.FirewallRule
|
||||
|
||||
if err := r.Get(ctx, req.NamespacedName, &firewallRule); err != nil {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
log.Info(firewallRule.Spec.Name)
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *FirewallRuleReconciler) mapFirewallGroupToFirewallRules(ctx context.Context, obj client.Object) []ctrl.Request {
|
||||
var requests []ctrl.Request
|
||||
service, ok := obj.(*corev1.Service)
|
||||
if !ok {
|
||||
return requests
|
||||
}
|
||||
|
||||
var allFirewallRules unifiv1beta1.FirewallRuleList
|
||||
|
||||
if err := r.List(ctx, &allFirewallRules); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, rule := range allFirewallRules.Items {
|
||||
if rule.Spec.MatchFirewallGroupsInAllNamespaces || rule.Namespace == service.Namespace {
|
||||
annotationKey := "unifi.engen.priv.no/firewall-rule"
|
||||
annotationVal := rule.Name
|
||||
if val, ok := service.Annotations[annotationKey]; ok && (annotationVal == "" || val == annotationVal) {
|
||||
requests = append(requests, ctrl.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: rule.Name,
|
||||
Namespace: rule.Namespace,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requests
|
||||
}
|
||||
|
||||
func (r *FirewallRuleReconciler) mapServiceToFirewallRules(ctx context.Context, obj client.Object) []ctrl.Request {
|
||||
var requests []ctrl.Request
|
||||
service, ok := obj.(*corev1.Service)
|
||||
if !ok {
|
||||
return requests
|
||||
}
|
||||
|
||||
var allFirewallRules unifiv1beta1.FirewallRuleList
|
||||
|
||||
if err := r.List(ctx, &allFirewallRules); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, rule := range allFirewallRules.Items {
|
||||
if rule.Spec.MatchServicesInAllNamespaces || rule.Namespace == service.Namespace {
|
||||
annotationKey := "unifi.engen.priv.no/firewall-rule"
|
||||
annotationVal := rule.Name
|
||||
if val, ok := service.Annotations[annotationKey]; ok && (annotationVal == "" || val == annotationVal) {
|
||||
requests = append(requests, ctrl.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Name: rule.Name,
|
||||
Namespace: rule.Namespace,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requests
|
||||
}
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *FirewallRuleReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&unifiv1beta1.FirewallRule{}).
|
||||
Named("firewallrule").
|
||||
Watches(
|
||||
&corev1.Service{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.mapServiceToFirewallRules),
|
||||
).
|
||||
Watches(
|
||||
&unifiv1beta1.FirewallGroup{},
|
||||
handler.EnqueueRequestsFromMapFunc(r.mapFirewallGroupToFirewallRules),
|
||||
).
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user