diff --git a/cmd/policy-assistant/pkg/cli/analyze.go b/cmd/policy-assistant/pkg/cli/analyze.go index 8db87b84..9b62886a 100644 --- a/cmd/policy-assistant/pkg/cli/analyze.go +++ b/cmd/policy-assistant/pkg/cli/analyze.go @@ -5,6 +5,8 @@ import ( "github.com/mattfenwick/cyclonus/examples" "github.com/mattfenwick/cyclonus/pkg/kube/netpol" "golang.org/x/net/context" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" "sigs.k8s.io/network-policy-api/apis/v1alpha1" "strings" "time" @@ -40,6 +42,8 @@ var AllModes = []string{ ProbeMode, } +const DefaultTimeout = 180 + type AnalyzeArgs struct { AllNamespaces bool Namespaces []string @@ -58,6 +62,8 @@ type AnalyzeArgs struct { // synthetic probe ProbePath string + + Timeout int } func SetupAnalyzeCommand() *cobra.Command { @@ -85,6 +91,8 @@ func SetupAnalyzeCommand() *cobra.Command { command.Flags().StringVar(&args.TrafficPath, "traffic-path", "", "path to json traffic file, containing of a list of traffic objects") command.Flags().StringVar(&args.ProbePath, "probe-path", "", "path to json model file for synthetic probe") + command.Flags().IntVar(&args.Timeout, "timeout", DefaultTimeout, "timeout time in seconds") + return command } @@ -92,10 +100,10 @@ func RunAnalyzeCommand(args *AnalyzeArgs) { // 1. read policies from kube var kubePolicies []*networkingv1.NetworkPolicy var kubeANPs []*v1alpha1.AdminNetworkPolicy - var kubeBANPs *v1alpha1.BaselineAdminNetworkPolicy + var kubeBANP *v1alpha1.BaselineAdminNetworkPolicy var kubePods []v1.Pod var kubeNamespaces []v1.Namespace - var netErr, anpErr, banpErr error + var netpolErr, anpErr, banpErr error if args.AllNamespaces || len(args.Namespaces) > 0 { kubeClient, err := kube.NewKubernetesForContext(args.Context) utils.DoOrDie(err) @@ -108,20 +116,21 @@ func RunAnalyzeCommand(args *AnalyzeArgs) { namespaces = []string{v1.NamespaceAll} } - //TODO: add a flag for the timeout - ctx, cancel := context.WithTimeout(context.TODO(), 15*time.Second) + includeANPS, includeBANPSs := shouldIncludeANPandBANP(kubeClient.ClientSet) + + ctx, cancel := context.WithTimeout(context.TODO(), time.Duration(args.Timeout)*time.Second) defer cancel() - kubePolicies, kubeANPs, kubeBANPs, netErr, anpErr, banpErr = kube.ReadNetworkPoliciesFromKube(ctx, kubeClient, namespaces) + kubePolicies, kubeANPs, kubeBANP, netpolErr, anpErr, banpErr = kube.ReadNetworkPoliciesFromKube(ctx, kubeClient, namespaces, includeANPS, includeBANPSs) - if netErr != nil { + if netpolErr != nil { logrus.Errorf("unable to read network policies from kube, ns '%s': %+v", namespaces, err) } if anpErr != nil { - fmt.Printf("Unable to fetch admin network policies: %s \n", anpErr) + logrus.Errorf("Unable to fetch admin network policies: %s \n", anpErr) } if banpErr != nil { - fmt.Printf("Unable to fetch base admin network policies: %s \n", banpErr) + logrus.Errorf("Unable to fetch base admin network policies: %s \n", banpErr) } } // 2. read policies from file @@ -130,18 +139,24 @@ func RunAnalyzeCommand(args *AnalyzeArgs) { utils.DoOrDie(err) kubePolicies = append(kubePolicies, policiesFromPath...) kubeANPs = append(kubeANPs, anpsFromPath...) - kubeBANPs = banpFromPath + if banpFromPath != nil && kubeBANP != nil { + logrus.Debugf("More that one banp parsed - setting banp from file") + } + kubeBANP = banpFromPath } // 3. read example policies if args.UseExamplePolicies { kubePolicies = append(kubePolicies, netpol.AllExamples...) kubeANPs = append(kubeANPs, examples.CoreGressRulesCombinedANB...) - kubeBANPs = kubeBANPs + if kubeBANP != nil { + logrus.Debugf("More that onew banp parsed - setting banp from the examples") + } + kubeBANP = examples.CoreGressRulesCombinedBANB } logrus.Debugf("parsed policies:\n%s", json.MustMarshalToString(kubePolicies)) - policies := matcher.BuildV1AndV2NetPols(args.SimplifyPolicies, kubePolicies, kubeANPs, kubeBANPs) + policies := matcher.BuildV1AndV2NetPols(args.SimplifyPolicies, kubePolicies, kubeANPs, kubeBANP) for _, mode := range args.Modes { switch mode { @@ -316,3 +331,28 @@ func ProbeSyntheticConnectivity(explainedPolicies *matcher.Policy, modelPath str fmt.Printf("Egress:\n%s\n", simulatedProbe.RenderEgress()) fmt.Printf("Combined:\n%s\n\n\n", simulatedProbe.RenderTable()) } + +func shouldIncludeANPandBANP(client *kubernetes.Clientset) (bool, bool) { + var includeANP, includeBANP bool + _, resources, _, err := client.DiscoveryClient.GroupsAndMaybeResources() + if err != nil { + logrus.Errorf("Unable to fetch all registered resources: %s", err) + return includeANP, includeBANP + } + gv := schema.GroupVersion{Group: "policy.networking.k8s.io", Version: "v1alpha1"} + + if groupResources, ok := resources[gv]; ok { + for _, res := range groupResources.APIResources { + switch res.Kind { + case "AdminNetworkPolicy": + includeANP = true + case "BaselineAdminNetworkPolicy": + includeBANP = true + default: + panic(fmt.Sprintf("unexpected resource kind %s", res.Kind)) + } + } + } + + return includeANP, includeBANP +} diff --git a/cmd/policy-assistant/pkg/kube/ikubernetes.go b/cmd/policy-assistant/pkg/kube/ikubernetes.go index ccf5ecf0..bbf69184 100644 --- a/cmd/policy-assistant/pkg/kube/ikubernetes.go +++ b/cmd/policy-assistant/pkg/kube/ikubernetes.go @@ -9,7 +9,7 @@ import ( networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "math/rand" - v1alpha12 "sigs.k8s.io/network-policy-api/apis/v1alpha1" + "sigs.k8s.io/network-policy-api/apis/v1alpha1" ) type IKubernetes interface { @@ -30,8 +30,15 @@ type IKubernetes interface { DeleteService(namespace string, name string) error GetServicesInNamespace(namespace string) ([]v1.Service, error) - GetAdminNetworkPoliciesInNamespace(ctx context.Context) ([]v1alpha12.AdminNetworkPolicy, error) - GetBaseAdminNetworkPoliciesInNamespace(ctx context.Context) (v1alpha12.BaselineAdminNetworkPolicy, error) + GetAdminNetworkPolicies(ctx context.Context) ([]v1alpha1.AdminNetworkPolicy, error) + CreateAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.AdminNetworkPolicy) (*v1alpha1.AdminNetworkPolicy, error) + UpdateAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.AdminNetworkPolicy) (*v1alpha1.AdminNetworkPolicy, error) + DeleteAdminNetworkPolicy(ctx context.Context, name string) error + + GetBaseAdminNetworkPolicies(ctx context.Context) ([]v1alpha1.BaselineAdminNetworkPolicy, error) + CreateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.BaselineAdminNetworkPolicy) (*v1alpha1.BaselineAdminNetworkPolicy, error) + UpdateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.BaselineAdminNetworkPolicy) (*v1alpha1.BaselineAdminNetworkPolicy, error) + DeleteBaselineAdminNetworkPolicy(ctx context.Context, name string) error CreatePod(kubePod *v1.Pod) (*v1.Pod, error) GetPod(namespace string, pod string) (*v1.Pod, error) @@ -88,12 +95,12 @@ func GetServicesInNamespaces(kubernetes IKubernetes, namespaces []string) ([]v1. return allServices, nil } -func GetAdminNetworkPoliciesInNamespaces(ctx context.Context, kubernetes IKubernetes) ([]v1alpha12.AdminNetworkPolicy, error) { - return kubernetes.GetAdminNetworkPoliciesInNamespace(ctx) +func GetAdminNetworkPoliciesInNamespaces(ctx context.Context, kubernetes IKubernetes) ([]v1alpha1.AdminNetworkPolicy, error) { + return kubernetes.GetAdminNetworkPolicies(ctx) } -func GetBaseAdminNetworkPoliciesInNamespaces(ctx context.Context, kubernetes IKubernetes) (v1alpha12.BaselineAdminNetworkPolicy, error) { - return kubernetes.GetBaseAdminNetworkPoliciesInNamespace(ctx) +func GetBaseAdminNetworkPoliciesInNamespaces(ctx context.Context, kubernetes IKubernetes) ([]v1alpha1.BaselineAdminNetworkPolicy, error) { + return kubernetes.GetBaseAdminNetworkPolicies(ctx) } type MockNamespace struct { @@ -104,12 +111,14 @@ type MockNamespace struct { } type MockKubernetes struct { - AdminNetworkPolicies func() ([]v1alpha12.AdminNetworkPolicy, error) - BaseNetworkPolicies func() (v1alpha12.BaselineAdminNetworkPolicy, error) - NetworkPolicies func() ([]networkingv1.NetworkPolicy, error) - Namespaces map[string]*MockNamespace - passRate float64 - podID int + AdminNetworkPolicies []v1alpha1.AdminNetworkPolicy + AdminNetworkPolicyError error + BaseNetworkPolicies []v1alpha1.BaselineAdminNetworkPolicy + BaseAdminNetworkPolicyError error + Namespaces map[string]*MockNamespace + NetworkPolicyError error + passRate float64 + podID int } func NewMockKubernetes(passRate float64) *MockKubernetes { @@ -208,14 +217,8 @@ func (m *MockKubernetes) DeleteNetworkPolicy(ns string, name string) error { } func (m *MockKubernetes) GetNetworkPoliciesInNamespace(ctx context.Context, namespace string) ([]networkingv1.NetworkPolicy, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - default: - res, err := m.NetworkPolicies() - if res != nil || err != nil { - return res, err - } + if m.NetworkPolicyError != nil { + return nil, m.NetworkPolicyError } nsObject, err := m.getNamespaceObject(namespace) @@ -390,21 +393,36 @@ func (m *MockKubernetes) ExecuteRemoteCommand(namespace string, pod string, cont return "", "", nil, nil } -func (m *MockKubernetes) GetAdminNetworkPoliciesInNamespace(ctx context.Context) ([]v1alpha12.AdminNetworkPolicy, error) { - select { - default: - return m.AdminNetworkPolicies() - case <-ctx.Done(): - return []v1alpha12.AdminNetworkPolicy{}, ctx.Err() - } +func (m *MockKubernetes) GetAdminNetworkPolicies(ctx context.Context) ([]v1alpha1.AdminNetworkPolicy, error) { + return m.AdminNetworkPolicies, m.AdminNetworkPolicyError +} +func (k *MockKubernetes) CreateAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.AdminNetworkPolicy) (*v1alpha1.AdminNetworkPolicy, error) { + return nil, ErrNotImplemented } -func (m *MockKubernetes) GetBaseAdminNetworkPoliciesInNamespace(ctx context.Context) (v1alpha12.BaselineAdminNetworkPolicy, error) { - select { - default: - return m.BaseNetworkPolicies() - case <-ctx.Done(): - return v1alpha12.BaselineAdminNetworkPolicy{}, ctx.Err() - } +func (k *MockKubernetes) UpdateAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.AdminNetworkPolicy) (*v1alpha1.AdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *MockKubernetes) DeleteAdminNetworkPolicy(ctx context.Context, name string) error { + //TODO: implement + return ErrNotImplemented +} + +func (m *MockKubernetes) GetBaseAdminNetworkPolicies(ctx context.Context) ([]v1alpha1.BaselineAdminNetworkPolicy, error) { + return m.BaseNetworkPolicies, m.BaseAdminNetworkPolicyError +} + +func (k *MockKubernetes) CreateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.BaselineAdminNetworkPolicy) (*v1alpha1.BaselineAdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *MockKubernetes) UpdateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha1.BaselineAdminNetworkPolicy) (*v1alpha1.BaselineAdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *MockKubernetes) DeleteBaselineAdminNetworkPolicy(ctx context.Context, name string) error { + //TODO: implement + return ErrNotImplemented } diff --git a/cmd/policy-assistant/pkg/kube/kubernetes.go b/cmd/policy-assistant/pkg/kube/kubernetes.go index b0e1a637..479e5a0e 100644 --- a/cmd/policy-assistant/pkg/kube/kubernetes.go +++ b/cmd/policy-assistant/pkg/kube/kubernetes.go @@ -20,6 +20,8 @@ import ( "k8s.io/client-go/tools/remotecommand" ) +var ErrNotImplemented = errors.New("Not implemented") + type Kubernetes struct { ClientSet *kubernetes.Clientset alphaClientSet *v1alpha1.PolicyV1alpha1Client @@ -109,7 +111,7 @@ func (k *Kubernetes) GetNetworkPoliciesInNamespace(ctx context.Context, namespac return netpolList.Items, nil } -func (k *Kubernetes) GetAdminNetworkPoliciesInNamespace(ctx context.Context) ([]v1alpha12.AdminNetworkPolicy, error) { +func (k *Kubernetes) GetAdminNetworkPolicies(ctx context.Context) ([]v1alpha12.AdminNetworkPolicy, error) { anps, err := k.alphaClientSet.AdminNetworkPolicies().List(ctx, metav1.ListOptions{}) if err != nil { return nil, err @@ -117,16 +119,38 @@ func (k *Kubernetes) GetAdminNetworkPoliciesInNamespace(ctx context.Context) ([] return anps.Items, nil } -func (k *Kubernetes) GetBaseAdminNetworkPoliciesInNamespace(ctx context.Context) (v1alpha12.BaselineAdminNetworkPolicy, error) { +func (k *Kubernetes) CreateAdminNetworkPolicy(ctx context.Context, policy *v1alpha12.AdminNetworkPolicy) (*v1alpha12.AdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *Kubernetes) UpdateAdminNetworkPolicy(ctx context.Context, policy *v1alpha12.AdminNetworkPolicy) (*v1alpha12.AdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *Kubernetes) DeleteAdminNetworkPolicy(ctx context.Context, name string) error { + //TODO: implement + return ErrNotImplemented +} + +func (k *Kubernetes) GetBaseAdminNetworkPolicies(ctx context.Context) ([]v1alpha12.BaselineAdminNetworkPolicy, error) { banp, err := k.alphaClientSet.BaselineAdminNetworkPolicies().List(ctx, metav1.ListOptions{}) if err != nil { - return v1alpha12.BaselineAdminNetworkPolicy{}, err - } - if len(banp.Items) > 0 { - return banp.Items[0], nil + return nil, err } - return v1alpha12.BaselineAdminNetworkPolicy{}, errors.New("BANP not found") + return banp.Items, nil +} + +func (k *Kubernetes) CreateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha12.BaselineAdminNetworkPolicy) (*v1alpha12.BaselineAdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} + +func (k *Kubernetes) UpdateBaselineAdminNetworkPolicy(ctx context.Context, policy *v1alpha12.BaselineAdminNetworkPolicy) (*v1alpha12.BaselineAdminNetworkPolicy, error) { + return nil, ErrNotImplemented +} +func (k *Kubernetes) DeleteBaselineAdminNetworkPolicy(ctx context.Context, name string) error { + //TODO: implement + return ErrNotImplemented } func (k *Kubernetes) UpdateNetworkPolicy(policy *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error) { diff --git a/cmd/policy-assistant/pkg/kube/read.go b/cmd/policy-assistant/pkg/kube/read.go index a186df49..e1b557bd 100644 --- a/cmd/policy-assistant/pkg/kube/read.go +++ b/cmd/policy-assistant/pkg/kube/read.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" v1alpha12 "sigs.k8s.io/network-policy-api/apis/v1alpha1" + "sync" ) // ReadNetworkPoliciesFromPath walks the folder and try to parse each file in @@ -23,8 +24,8 @@ import ( // 5. AdminNetworkPolicy func ReadNetworkPoliciesFromPath(policyPath string) ([]*networkingv1.NetworkPolicy, []*v1alpha12.AdminNetworkPolicy, *v1alpha12.BaselineAdminNetworkPolicy, error) { var netPolicies []*networkingv1.NetworkPolicy - var adminNetPolicies []*v1alpha12.AdminNetworkPolicy - var baseAdminNetPolicies *v1alpha12.BaselineAdminNetworkPolicy + var adminNetworkPolicies []*v1alpha12.AdminNetworkPolicy + var baselineAdminNetworkPolicy *v1alpha12.BaselineAdminNetworkPolicy err := filepath.Walk(policyPath, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -69,26 +70,29 @@ func ReadNetworkPoliciesFromPath(policyPath string) ([]*networkingv1.NetworkPoli banp, err := utils.ParseYamlStrict[v1alpha12.BaselineAdminNetworkPolicy](bytes) if err == nil { - baseAdminNetPolicies = banp + if baselineAdminNetworkPolicy != nil { + return errors.New("baseline admin network policy already exists") + } + baselineAdminNetworkPolicy = banp return nil } logrus.Debugf("unable to base admin network policies: %+v", err) anpList, err := utils.ParseYamlStrict[v1alpha12.AdminNetworkPolicyList](bytes) if err == nil { - adminNetPolicies = append(adminNetPolicies, refList(anpList.Items)...) + adminNetworkPolicies = append(adminNetworkPolicies, refList(anpList.Items)...) return nil } logrus.Debugf("unable to parse list of admin network policies: %+v", err) anp, err := utils.ParseYamlStrict[v1alpha12.AdminNetworkPolicy](bytes) if err == nil { - adminNetPolicies = append(adminNetPolicies, anp) + adminNetworkPolicies = append(adminNetworkPolicies, anp) return nil } logrus.Debugf("unable to single admin network policies: %+v", err) - if len(netPolicies) == 0 && len(adminNetPolicies) == 0 && baseAdminNetPolicies == nil { + if len(netPolicies) == 0 && len(adminNetworkPolicies) == 0 && baselineAdminNetworkPolicy == nil { return errors.WithMessagef(err, "unable to parse any policies from yaml at %s", path) } @@ -105,85 +109,54 @@ func ReadNetworkPoliciesFromPath(policyPath string) ([]*networkingv1.NetworkPoli } } } - return netPolicies, adminNetPolicies, baseAdminNetPolicies, nil -} - -func ReadNetworkPoliciesFromKube(ctx context.Context, kubeClient IKubernetes, namespaces []string) ([]*networkingv1.NetworkPolicy, []*v1alpha12.AdminNetworkPolicy, *v1alpha12.BaselineAdminNetworkPolicy, error, error, error) { - var netpols []*networkingv1.NetworkPolicy - var anps []*v1alpha12.AdminNetworkPolicy - var banp *v1alpha12.BaselineAdminNetworkPolicy - var neterr, anperr, banperr error - - var netPolsCn = make(chan apiResponse[[]networkingv1.NetworkPolicy], 1) - go func(ch chan apiResponse[[]networkingv1.NetworkPolicy]) { - ch <- readNetworkPolicies(ctx, kubeClient, namespaces) - }(netPolsCn) - - var anpsCh = make(chan apiResponse[[]v1alpha12.AdminNetworkPolicy], 1) - go func(ch chan apiResponse[[]v1alpha12.AdminNetworkPolicy]) { - ch <- readAdminNetworkPolicies(ctx, kubeClient) - }(anpsCh) - - var banpsCh = make(chan apiResponse[v1alpha12.BaselineAdminNetworkPolicy], 1) - go func(ch chan apiResponse[v1alpha12.BaselineAdminNetworkPolicy]) { - ch <- readBaseAdminNetworkPolicies(ctx, kubeClient) - }(banpsCh) - - for i := 0; i <= 2; i++ { - select { - case result := <-netPolsCn: - r, err := result.response() - netpols = refList(r) - neterr = err - case result := <-anpsCh: - r, err := result.response() - anps = refList(r) - anperr = err - case result := <-banpsCh: - r, err := result.response() - if err == nil { - banp = &r - } - banperr = err - } - } - - return netpols, anps, banp, neterr, anperr, banperr + return netPolicies, adminNetworkPolicies, baselineAdminNetworkPolicy, nil } func refList[T any](refs []T) []*T { return slice.Map(builtin.Reference[T], refs) } -type apiResponse[T []networkingv1.NetworkPolicy | []v1alpha12.AdminNetworkPolicy | v1alpha12.BaselineAdminNetworkPolicy] struct { - data T - error error -} +func ReadNetworkPoliciesFromKube(ctx context.Context, kubeClient IKubernetes, namespaces []string, includeANPs, includeBANPs bool) ([]*networkingv1.NetworkPolicy, []*v1alpha12.AdminNetworkPolicy, *v1alpha12.BaselineAdminNetworkPolicy, error, error, error) { + var netpols []networkingv1.NetworkPolicy + var anps []v1alpha12.AdminNetworkPolicy + var banp *v1alpha12.BaselineAdminNetworkPolicy + var netErr, anpErr, banpErr error -func (t apiResponse[T]) response() (T, error) { - return t.data, t.error -} + var wg sync.WaitGroup + wg.Add(3) -func readNetworkPolicies(ctx context.Context, kubeClient IKubernetes, namespaces []string) apiResponse[[]networkingv1.NetworkPolicy] { - result, err := GetNetworkPoliciesInNamespaces(ctx, kubeClient, namespaces) - if err != nil { - return apiResponse[[]networkingv1.NetworkPolicy]{nil, err} - } - return apiResponse[[]networkingv1.NetworkPolicy]{result, err} -} + go func(w *sync.WaitGroup) { + defer w.Done() + netpols, netErr = GetNetworkPoliciesInNamespaces(ctx, kubeClient, namespaces) + return + }(&wg) -func readAdminNetworkPolicies(ctx context.Context, kubeClient IKubernetes) apiResponse[[]v1alpha12.AdminNetworkPolicy] { - result, err := GetAdminNetworkPoliciesInNamespaces(ctx, kubeClient) - if err != nil { - return apiResponse[[]v1alpha12.AdminNetworkPolicy]{nil, err} - } - return apiResponse[[]v1alpha12.AdminNetworkPolicy]{result, err} -} + go func(w *sync.WaitGroup) { + defer w.Done() + if !includeANPs { + return + } + anps, anpErr = GetAdminNetworkPoliciesInNamespaces(ctx, kubeClient) + return + }(&wg) + + go func(w *sync.WaitGroup) { + defer w.Done() + if !includeBANPs { + return + } + result, err := GetBaseAdminNetworkPoliciesInNamespaces(ctx, kubeClient) + if err != nil { + banpErr = err + } + if len(result) > 0 { + banp = &result[0] + } -func readBaseAdminNetworkPolicies(ctx context.Context, kubeClient IKubernetes) apiResponse[v1alpha12.BaselineAdminNetworkPolicy] { - result, err := GetBaseAdminNetworkPoliciesInNamespaces(ctx, kubeClient) - if err != nil { - return apiResponse[v1alpha12.BaselineAdminNetworkPolicy]{result, err} - } - return apiResponse[v1alpha12.BaselineAdminNetworkPolicy]{result, err} + return + }(&wg) + + wg.Wait() + + return refList(netpols), refList(anps), banp, netErr, anpErr, banpErr } diff --git a/cmd/policy-assistant/pkg/kube/read_test.go b/cmd/policy-assistant/pkg/kube/read_test.go index d8918f9f..2fa8af1e 100644 --- a/cmd/policy-assistant/pkg/kube/read_test.go +++ b/cmd/policy-assistant/pkg/kube/read_test.go @@ -3,225 +3,109 @@ package kube import ( "context" "errors" - "fmt" v1 "k8s.io/api/networking/v1" - errors2 "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" v1alpha12 "sigs.k8s.io/network-policy-api/apis/v1alpha1" "testing" - "time" ) func TestReadNetworkPoliciesFromKube(t *testing.T) { - anpNotFound := errors2.NewNotFound(schema.GroupResource{v1alpha12.GroupName, "AdminNetworkPolicy"}, "AdminNetworkPolicy") - banpNotFound := errors2.NewNotFound(schema.GroupResource{v1alpha12.GroupName, "BaselineAdminNetworkPolicy"}, "BaselineAdminNetworkPolicy") - netpolNotFound := errors2.NewNotFound(schema.GroupResource{v1.GroupName, "NetworkPolicies"}, "NetworkPolicies") - scenarios := map[string]struct { - ctxCreator func() (context.Context, context.CancelFunc) - anpResponse func() ([]v1alpha12.AdminNetworkPolicy, error) - banpResponse func() (v1alpha12.BaselineAdminNetworkPolicy, error) - netPolResponse func() ([]v1.NetworkPolicy, error) + AdminNetworkPolicies []v1alpha12.AdminNetworkPolicy + BaselineAdminNetworkPolicies []v1alpha12.BaselineAdminNetworkPolicy + NetworkPolicies []v1.NetworkPolicy expectedNetErr error expectedAnpErr error expectedBanpErr error }{ - "timeout error on admin network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.WithTimeout(context.TODO(), 1*time.Nanosecond) - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - time.Sleep(1 * time.Millisecond) - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil - }, + "parse error on admin network policies retrieval": { expectedAnpErr: context.DeadlineExceeded, }, - "resource not found on admin network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, anpNotFound - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil - }, - expectedAnpErr: anpNotFound, - }, "return admin network policies": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "admin-network-policy", - }, + AdminNetworkPolicies: []v1alpha12.AdminNetworkPolicy{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "admin-network-policy", }, - }, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil + }, }, }, - "timeout error on base admin network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.WithTimeout(context.TODO(), 1*time.Nanosecond) - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - time.Sleep(1 * time.Millisecond) - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil - }, + "parse error on base admin network policies retrieval": { expectedAnpErr: context.DeadlineExceeded, }, - "resource not found on base admin network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, banpNotFound - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil - }, - expectedBanpErr: banpNotFound, - }, "return base admin network policies": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{ + BaselineAdminNetworkPolicies: []v1alpha12.BaselineAdminNetworkPolicy{ + { ObjectMeta: metav1.ObjectMeta{Name: "base-admin-network-policy"}, - }, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, nil + }, }, }, - "timeout error on network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.WithTimeout(context.TODO(), 1*time.Nanosecond) - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - time.Sleep(10 * time.Millisecond) - return nil, nil - }, + "parse error on network policies retrieval": { expectedNetErr: context.DeadlineExceeded, }, - "resource not found on network policies retrieval": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return nil, netpolNotFound - }, - expectedNetErr: netpolNotFound, - }, "return network policies": { - ctxCreator: func() (context.Context, context.CancelFunc) { - return context.TODO(), func() {} - }, - anpResponse: func() ([]v1alpha12.AdminNetworkPolicy, error) { - return []v1alpha12.AdminNetworkPolicy{}, nil - }, - banpResponse: func() (v1alpha12.BaselineAdminNetworkPolicy, error) { - return v1alpha12.BaselineAdminNetworkPolicy{}, nil - }, - netPolResponse: func() ([]v1.NetworkPolicy, error) { - return []v1.NetworkPolicy{ - { - ObjectMeta: metav1.ObjectMeta{Name: "network_policy"}, + NetworkPolicies: []v1.NetworkPolicy{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "network_policy", + Namespace: "default", }, - }, nil + }, }, }, } for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { - ctx, cancel := scenario.ctxCreator() - defer cancel() - k := &MockKubernetes{ - AdminNetworkPolicies: scenario.anpResponse, - BaseNetworkPolicies: scenario.banpResponse, - NetworkPolicies: scenario.netPolResponse, + AdminNetworkPolicies: scenario.AdminNetworkPolicies, + AdminNetworkPolicyError: scenario.expectedAnpErr, + BaseNetworkPolicies: scenario.BaselineAdminNetworkPolicies, + BaseAdminNetworkPolicyError: scenario.expectedBanpErr, + Namespaces: map[string]*MockNamespace{}, + NetworkPolicyError: scenario.expectedNetErr, } - netpol, anps, banp, netErr, anpErr, banpErr := ReadNetworkPoliciesFromKube(ctx, k, []string{"test"}) + + for _, np := range scenario.NetworkPolicies { + k.Namespaces[np.Namespace] = &MockNamespace{ + Netpols: map[string]*v1.NetworkPolicy{ + np.Name: &np, + }, + } + } + + netpol, anps, banp, netErr, anpErr, banpErr := ReadNetworkPoliciesFromKube(context.TODO(), k, []string{"default"}, true, true) if scenario.expectedNetErr != nil { if !errors.Is(netErr, scenario.expectedNetErr) { - t.Fatalf("Unexpected error1: %v, expected %v", netErr, scenario.expectedNetErr) + t.Fatalf("Unexpected error: %v, expected %v", netErr, scenario.expectedNetErr) } } if scenario.expectedAnpErr != nil { if !errors.Is(anpErr, scenario.expectedAnpErr) { - t.Fatalf("Unexpected error1: %v, expected %v", anpErr, scenario.expectedAnpErr) + t.Fatalf("Unexpected error: %v, expected %v", anpErr, scenario.expectedAnpErr) } } if scenario.expectedBanpErr != nil { if !errors.Is(banpErr, scenario.expectedBanpErr) { - t.Fatalf("Unexpected error1: %v, expected %v", banpErr, scenario.expectedBanpErr) + t.Fatalf("Unexpected error: %v, expected %v", banpErr, scenario.expectedBanpErr) } } - if len(anps) > 0 { - expected, _ := scenario.anpResponse() - if anps[0].Name != expected[0].Name { - t.Fatalf("Unexpected ANP: %v, expected %v", anps[0].Name, expected[0].Name) + if len(scenario.AdminNetworkPolicies) > 0 { + if anps[0].Name != scenario.AdminNetworkPolicies[0].Name { + t.Fatalf("Unexpected ANP: %v, expected %v", anps[0].Name, scenario.AdminNetworkPolicies[0].Name) } } - if banp != nil { - expected, _ := scenario.banpResponse() - if banp.Name != expected.Name { + if scenario.BaselineAdminNetworkPolicies != nil { + if banp.Name != scenario.BaselineAdminNetworkPolicies[0].Name { t.Fatalf("Unexpected BANP: %v, expected %v", banp.Name, banp.Name) } } - if len(netpol) > 0 { - expected, _ := scenario.netPolResponse() - fmt.Println(netpol[0].Name, expected[0].Name+"1") - if netpol[0].Name != expected[0].Name { - t.Fatalf("Unexpected NetworkPolicy: %v, expected %v", netpol[0].Name, expected[0].Name) + if len(scenario.NetworkPolicies) > 0 { + if netpol[0].Name != scenario.NetworkPolicies[0].Name { + t.Fatalf("Unexpected NetworkPolicy: %v, expected %v", netpol[0].Name, scenario.NetworkPolicies[0].Name) } } }) diff --git a/cmd/policy-assistant/pkg/kube/read_tests.go b/cmd/policy-assistant/pkg/kube/read_tests.go index fea1bd12..44922bad 100644 --- a/cmd/policy-assistant/pkg/kube/read_tests.go +++ b/cmd/policy-assistant/pkg/kube/read_tests.go @@ -8,12 +8,12 @@ import ( func RunReadNetworkPolicyTests() { Describe("ReadNetworkPolicies", func() { It("Should read a single policy from a single file", func() { - policies, _, _, err := ReadNetworkPoliciesFromPath("../../networkpolicies/features/portrange1.yaml") + policies, _, _, err := ReadNetworkPoliciesFromPath("../../test/example-policies/networkpolicies/features/portrange1.yaml") Expect(err).To(BeNil()) Expect(len(policies)).To(Equal(1)) }) It("Should read a list of policies from a single file", func() { - policies, _, _, err := ReadNetworkPoliciesFromPath("../../networkpolicies/yaml-syntax/yaml-list.yaml") + policies, _, _, err := ReadNetworkPoliciesFromPath("../../test/example-policies/networkpolicies/yaml-syntax/yaml-list.yaml") Expect(err).To(BeNil()) Expect(len(policies)).To(Equal(3)) }) @@ -28,27 +28,35 @@ func RunReadNetworkPolicyTests() { // }) It("Should read multiple policies from all files in a directory", func() { - policies, _, _, err := ReadNetworkPoliciesFromPath("../../networkpolicies/simple-example") + policies, _, _, err := ReadNetworkPoliciesFromPath("../../test/example-policies/networkpolicies/simple-example") Expect(err).To(BeNil()) Expect(len(policies)).To(Equal(7)) - policies, _, _, err = ReadNetworkPoliciesFromPath("../../networkpolicies/") + policies, _, _, err = ReadNetworkPoliciesFromPath("../../test/example-policies/networkpolicies/") Expect(err).To(BeNil()) Expect(len(policies)).To(Equal(14)) }) It("Should read multiple admin network policies", func() { - _, anps, _, err := ReadNetworkPoliciesFromPath("../../anps/") + _, anps, _, err := ReadNetworkPoliciesFromPath("../../test/example-policies/anps/") Expect(err).To(BeNil()) Expect(len(anps)).To(Equal(3)) }) It("Should read a base admin network policy", func() { - _, _, banp, err := ReadNetworkPoliciesFromPath("../../banp/") + _, _, banp, err := ReadNetworkPoliciesFromPath("../../test/example-policies/banp/") Expect(err).To(BeNil()) Expect(banp).ToNot(BeNil()) }) + It("Should parse multiple types from folder", func() { + policiies, anps, bapn, err := ReadNetworkPoliciesFromPath("../../test/example-policies/") + Expect(err).To(BeNil()) + Expect(len(policiies)).To(Equal(14)) + Expect(len(anps)).To(Equal(3)) + Expect(bapn).ToNot(BeNil()) + }) + // TODO test to show what happens for duplicate names }) } diff --git a/cmd/policy-assistant/anps/anp-list.yaml b/cmd/policy-assistant/test/example-policies/anps/anp-list.yaml similarity index 100% rename from cmd/policy-assistant/anps/anp-list.yaml rename to cmd/policy-assistant/test/example-policies/anps/anp-list.yaml diff --git a/cmd/policy-assistant/anps/anp.yaml b/cmd/policy-assistant/test/example-policies/anps/anp.yaml similarity index 100% rename from cmd/policy-assistant/anps/anp.yaml rename to cmd/policy-assistant/test/example-policies/anps/anp.yaml diff --git a/cmd/policy-assistant/banp/banp.yaml b/cmd/policy-assistant/test/example-policies/banp/banp.yaml similarity index 100% rename from cmd/policy-assistant/banp/banp.yaml rename to cmd/policy-assistant/test/example-policies/banp/banp.yaml diff --git a/cmd/policy-assistant/networkpolicies/allow-all-internal.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/allow-all-internal.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/allow-all-internal.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/allow-all-internal.yaml diff --git a/cmd/policy-assistant/networkpolicies/allow-all.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/allow-all.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/allow-all.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/allow-all.yaml diff --git a/cmd/policy-assistant/networkpolicies/features/portrange1.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/features/portrange1.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/features/portrange1.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/features/portrange1.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/allow-all-egress-by-label.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-all-egress-by-label.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/allow-all-egress-by-label.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-all-egress-by-label.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/allow-all-for-label.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-all-for-label.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/allow-all-for-label.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-all-for-label.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/allow-by-ip.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-by-ip.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/allow-by-ip.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-by-ip.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/allow-label-to-label.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-label-to-label.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/allow-label-to-label.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/allow-label-to-label.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/deny-all-egress.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all-egress.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/deny-all-egress.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all-egress.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/deny-all-for-label.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all-for-label.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/deny-all-for-label.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all-for-label.yaml diff --git a/cmd/policy-assistant/networkpolicies/simple-example/deny-all.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/simple-example/deny-all.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/simple-example/deny-all.yaml diff --git a/cmd/policy-assistant/networkpolicies/upstream_test_cases/allow-to-ns-y-pod-a.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/upstream_test_cases/allow-to-ns-y-pod-a.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/upstream_test_cases/allow-to-ns-y-pod-a.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/upstream_test_cases/allow-to-ns-y-pod-a.yaml diff --git a/cmd/policy-assistant/networkpolicies/yaml-syntax/yaml-list.yaml b/cmd/policy-assistant/test/example-policies/networkpolicies/yaml-syntax/yaml-list.yaml similarity index 100% rename from cmd/policy-assistant/networkpolicies/yaml-syntax/yaml-list.yaml rename to cmd/policy-assistant/test/example-policies/networkpolicies/yaml-syntax/yaml-list.yaml