This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch refactor-with-go
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/refactor-with-go by this push:
     new 4927fe21 Update authorization rule (#1061)
4927fe21 is described below

commit 4927fe21ca0a35775016b81fa34b4cb9c90f56ff
Author: Albumen Kevin <[email protected]>
AuthorDate: Sun Mar 26 18:18:10 2023 +0800

    Update authorization rule (#1061)
    
    * Update authorization rule
    
    * Update mod
---
 deploy/crd.yaml                                    |  16 +
 deploy/example-peerauthentication.yaml             |   2 +-
 go.mod                                             |   2 +-
 .../apis/dubbo.apache.org/v1beta1/types.go         |  13 +
 .../v1beta1/zz_generated.deepcopy.go               |  10 +
 .../v1beta1/authorizationpolicyspec.go             |   9 +
 .../v1beta1/authorizationpolicytarget.go           |  22 +
 pkg/authority/k8s/client.go                        |   3 +
 pkg/authority/k8s/controller.go                    |  57 +-
 pkg/authority/rule/authentication/definition.go    |  34 +
 pkg/authority/rule/authentication/rule.go          |  17 +-
 pkg/authority/rule/authorization/definition.go     | 192 +++++
 .../rule/authorization/definition_test.go          | 119 +++
 pkg/authority/rule/authorization/rule.go           | 201 ++++-
 pkg/authority/rule/authorization/rule_test.go      | 858 ++++++++++++++++++++-
 15 files changed, 1510 insertions(+), 45 deletions(-)

diff --git a/deploy/crd.yaml b/deploy/crd.yaml
index ac792c9b..0228f0a8 100644
--- a/deploy/crd.yaml
+++ b/deploy/crd.yaml
@@ -222,6 +222,16 @@ spec:
                         type: object
                         description: "The destination of the traffic to be 
matched."
                         properties:
+                          namespaces:
+                            type: array
+                            description: "The namespaces to match of the 
source workload."
+                            items:
+                              type: string
+                          notNamespaces:
+                            type: array
+                            description: "The namespaces not to match of the 
source workload."
+                            items:
+                              type: string
                           ipBlocks:
                             type: array
                             description: "The IP addresses to match of the 
destination workload."
@@ -305,6 +315,12 @@ spec:
                   minimum: 0
                   default: 100
                   maximum: 100
+                order:
+                    type: number
+                    description: "The order of the rule."
+                    minimum: -2147483648
+                    default: 0
+                    maximum: 2147483647
                 matchType:
                   type: string
                   description: "The match type of the rules."
diff --git a/deploy/example-peerauthentication.yaml 
b/deploy/example-peerauthentication.yaml
index fb016fbd..73f07105 100644
--- a/deploy/example-peerauthentication.yaml
+++ b/deploy/example-peerauthentication.yaml
@@ -32,7 +32,7 @@ metadata:
   name: default
   namespace: dubbo-demo-new
 spec:
-  action: ALLOW
+  action: DENY
   rules:
     -  from:
         namespaces: ["dubbo-demo"]
diff --git a/go.mod b/go.mod
index 2f43008a..0c73e66e 100644
--- a/go.mod
+++ b/go.mod
@@ -38,6 +38,7 @@ require (
        k8s.io/api v0.26.1
        k8s.io/apimachinery v0.26.1
        k8s.io/client-go v0.26.1
+       k8s.io/utils v0.0.0-20221107191617-1a15be271d1d
        sigs.k8s.io/structured-merge-diff/v4 v4.2.3
 )
 
@@ -133,7 +134,6 @@ require (
        gopkg.in/yaml.v3 v3.0.1 // indirect
        k8s.io/klog/v2 v2.80.1 // indirect
        k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
-       k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
        sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
        sigs.k8s.io/yaml v1.3.0 // indirect
 )
diff --git a/pkg/authority/apis/dubbo.apache.org/v1beta1/types.go 
b/pkg/authority/apis/dubbo.apache.org/v1beta1/types.go
index 9b1958b7..1dbe9457 100644
--- a/pkg/authority/apis/dubbo.apache.org/v1beta1/types.go
+++ b/pkg/authority/apis/dubbo.apache.org/v1beta1/types.go
@@ -144,6 +144,13 @@ type AuthorizationPolicySpec struct {
        // +kubebuilder:validation:Maximum=100
        // +kubebuilder:default=100
        Samples float32 `json:"samples,omitempty"`
+       // The order of the rule.
+       // +optional
+       // +kubebuilder:validation:Type=number
+       // +kubebuilder:validation:Minimum=-2147483648
+       // +kubebuilder:validation:Maximum=2147483647
+       // +kubebuilder:default=0
+       Order float32 `json:"order,omitempty"`
        // The match type of the rules.
        // +optional
        // +kubebuilder:validation:Type=string
@@ -191,6 +198,12 @@ type AuthorizationPolicySource struct {
 }
 
 type AuthorizationPolicyTarget struct {
+       // The namespaces to match of the source workload.
+       // +optional
+       Namespaces []string `json:"namespaces,omitempty"`
+       // The namespaces not to match of the source workload.
+       // +optional
+       NotNamespaces []string `json:"notNamespaces,omitempty"`
        // The IP addresses to match of the destination workload.
        // +optional
        IpBlocks []string `json:"ipBlocks,omitempty"`
diff --git 
a/pkg/authority/apis/dubbo.apache.org/v1beta1/zz_generated.deepcopy.go 
b/pkg/authority/apis/dubbo.apache.org/v1beta1/zz_generated.deepcopy.go
index 01dcfe56..a5542bf4 100644
--- a/pkg/authority/apis/dubbo.apache.org/v1beta1/zz_generated.deepcopy.go
+++ b/pkg/authority/apis/dubbo.apache.org/v1beta1/zz_generated.deepcopy.go
@@ -419,6 +419,16 @@ func (in *AuthorizationPolicySpec) DeepCopy() 
*AuthorizationPolicySpec {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *AuthorizationPolicyTarget) DeepCopyInto(out 
*AuthorizationPolicyTarget) {
        *out = *in
+       if in.Namespaces != nil {
+               in, out := &in.Namespaces, &out.Namespaces
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
+       if in.NotNamespaces != nil {
+               in, out := &in.NotNamespaces, &out.NotNamespaces
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
        if in.IpBlocks != nil {
                in, out := &in.IpBlocks, &out.IpBlocks
                *out = make([]string, len(*in))
diff --git 
a/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicyspec.go
 
b/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicyspec.go
index 82de34b5..ccb22ab1 100644
--- 
a/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicyspec.go
+++ 
b/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicyspec.go
@@ -23,6 +23,7 @@ type AuthorizationPolicySpecApplyConfiguration struct {
        Action    *string                                     
`json:"action,omitempty"`
        Rules     []AuthorizationPolicyRuleApplyConfiguration 
`json:"rules,omitempty"`
        Samples   *float32                                    
`json:"samples,omitempty"`
+       Order     *float32                                    
`json:"order,omitempty"`
        MatchType *string                                     
`json:"matchType,omitempty"`
 }
 
@@ -61,6 +62,14 @@ func (b *AuthorizationPolicySpecApplyConfiguration) 
WithSamples(value float32) *
        return b
 }
 
+// WithOrder sets the Order field in the declarative configuration to the 
given value
+// and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
+// If called multiple times, the Order field is set to the value of the last 
call.
+func (b *AuthorizationPolicySpecApplyConfiguration) WithOrder(value float32) 
*AuthorizationPolicySpecApplyConfiguration {
+       b.Order = &value
+       return b
+}
+
 // WithMatchType sets the MatchType field in the declarative configuration to 
the given value
 // and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
 // If called multiple times, the MatchType field is set to the value of the 
last call.
diff --git 
a/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicytarget.go
 
b/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicytarget.go
index 474c043d..490b77ab 100644
--- 
a/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicytarget.go
+++ 
b/pkg/authority/generated/applyconfiguration/dubbo.apache.org/v1beta1/authorizationpolicytarget.go
@@ -20,6 +20,8 @@ package v1beta1
 // AuthorizationPolicyTargetApplyConfiguration represents an declarative 
configuration of the AuthorizationPolicyTarget type for use
 // with apply.
 type AuthorizationPolicyTargetApplyConfiguration struct {
+       Namespaces    []string                                      
`json:"namespaces,omitempty"`
+       NotNamespaces []string                                      
`json:"notNamespaces,omitempty"`
        IpBlocks      []string                                      
`json:"ipBlocks,omitempty"`
        NotIpBlocks   []string                                      
`json:"notIpBlocks,omitempty"`
        Principals    []string                                      
`json:"principals,omitempty"`
@@ -34,6 +36,26 @@ func AuthorizationPolicyTarget() 
*AuthorizationPolicyTargetApplyConfiguration {
        return &AuthorizationPolicyTargetApplyConfiguration{}
 }
 
+// WithNamespaces adds the given value to the Namespaces field in the 
declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" 
function invocations.
+// If called multiple times, values provided by each call will be appended to 
the Namespaces field.
+func (b *AuthorizationPolicyTargetApplyConfiguration) WithNamespaces(values 
...string) *AuthorizationPolicyTargetApplyConfiguration {
+       for i := range values {
+               b.Namespaces = append(b.Namespaces, values[i])
+       }
+       return b
+}
+
+// WithNotNamespaces adds the given value to the NotNamespaces field in the 
declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" 
function invocations.
+// If called multiple times, values provided by each call will be appended to 
the NotNamespaces field.
+func (b *AuthorizationPolicyTargetApplyConfiguration) WithNotNamespaces(values 
...string) *AuthorizationPolicyTargetApplyConfiguration {
+       for i := range values {
+               b.NotNamespaces = append(b.NotNamespaces, values[i])
+       }
+       return b
+}
+
 // WithIpBlocks adds the given value to the IpBlocks field in the declarative 
configuration
 // and returns the receiver, so that objects can be build by chaining "With" 
function invocations.
 // If called multiple times, values provided by each call will be appended to 
the IpBlocks field.
diff --git a/pkg/authority/k8s/client.go b/pkg/authority/k8s/client.go
index c58a91a1..5621d5bb 100644
--- a/pkg/authority/k8s/client.go
+++ b/pkg/authority/k8s/client.go
@@ -57,6 +57,7 @@ type Client interface {
 }
 
 type ClientImpl struct {
+       options        *config.Options
        kubeClient     *kubernetes.Clientset
        informerClient *infoemerclient.Clientset
 }
@@ -66,6 +67,7 @@ func NewClient() Client {
 }
 
 func (c *ClientImpl) Init(options *config.Options) bool {
+       c.options = options
        config, err := rest.InClusterConfig()
        options.InPodEnv = err == nil
        if err != nil {
@@ -369,6 +371,7 @@ func (c *ClientImpl) InitController(
 
        stopCh := make(chan struct{})
        controller := NewController(c.informerClient,
+               c.options.Namespace,
                authenticationHandler,
                authorizationHandler,
                informerFactory.Dubbo().V1beta1().AuthenticationPolicies(),
diff --git a/pkg/authority/k8s/controller.go b/pkg/authority/k8s/controller.go
index 3f65863a..ac0302a0 100644
--- a/pkg/authority/k8s/controller.go
+++ b/pkg/authority/k8s/controller.go
@@ -23,6 +23,7 @@ import (
        "github.com/apache/dubbo-admin/pkg/authority/rule/authorization"
        "github.com/apache/dubbo-admin/pkg/logger"
        "k8s.io/client-go/tools/cache"
+       "k8s.io/utils/strings/slices"
 )
 
 type NotificationType int
@@ -40,6 +41,8 @@ const (
 type Controller struct {
        dubboClientSet clientSet.Interface
 
+       rootNamespace string
+
        authenticationSynced cache.InformerSynced
        authorizationSynced  cache.InformerSynced
 
@@ -50,13 +53,16 @@ type Controller struct {
 // NewController returns a new sample controller
 func NewController(
        clientSet clientSet.Interface,
+       rootNamespace string,
        authenticationHandler authentication.Handler,
        authorizationHandler authorization.Handler,
        acInformer informerV1beta1.AuthenticationPolicyInformer,
        apInformer informerV1beta1.AuthorizationPolicyInformer,
 ) *Controller {
        controller := &Controller{
-               dubboClientSet:       clientSet,
+               dubboClientSet: clientSet,
+               rootNamespace:  rootNamespace,
+
                authenticationSynced: acInformer.Informer().HasSynced,
                authorizationSynced:  apInformer.Informer().HasSynced,
 
@@ -118,7 +124,7 @@ func (c *Controller) handleEvent(obj interface{}, eventType 
NotificationType) {
 
        switch o := obj.(type) {
        case *apiV1beta1.AuthenticationPolicy:
-               a := CopyToAuthentication(key, o)
+               a := CopyToAuthentication(key, c.rootNamespace, o)
 
                switch eventType {
                case AddNotification:
@@ -130,7 +136,7 @@ func (c *Controller) handleEvent(obj interface{}, eventType 
NotificationType) {
                }
                return
        case *apiV1beta1.AuthorizationPolicy:
-               a := CopyToAuthorization(key, o)
+               a := CopyToAuthorization(key, c.rootNamespace, o)
 
                switch eventType {
                case AddNotification:
@@ -146,7 +152,7 @@ func (c *Controller) handleEvent(obj interface{}, eventType 
NotificationType) {
        }
 }
 
-func CopyToAuthentication(key string, pa *apiV1beta1.AuthenticationPolicy) 
*authentication.Policy {
+func CopyToAuthentication(key, rootNamespace string, pa 
*apiV1beta1.AuthenticationPolicy) *authentication.Policy {
        a := &authentication.Policy{}
        a.Name = key
        a.Spec = &authentication.PolicySpec{}
@@ -191,10 +197,27 @@ func CopyToAuthentication(key string, pa 
*apiV1beta1.AuthenticationPolicy) *auth
                        a.Spec.PortLevel = append(a.Spec.PortLevel, r)
                }
        }
+
+       if rootNamespace == pa.Namespace {
+               return a
+       }
+
+       if len(a.Spec.Selector) == 0 {
+               a.Spec.Selector = append(a.Spec.Selector, 
&authentication.Selector{
+                       Namespaces: []string{pa.Namespace},
+               })
+       } else {
+               for _, selector := range a.Spec.Selector {
+                       if !slices.Contains(selector.Namespaces, pa.Namespace) {
+                               selector.Namespaces = 
append(selector.Namespaces, pa.Namespace)
+                       }
+               }
+       }
+
        return a
 }
 
-func CopyToAuthorization(key string, pa *apiV1beta1.AuthorizationPolicy) 
*authorization.Policy {
+func CopyToAuthorization(key, rootNamespace string, pa 
*apiV1beta1.AuthorizationPolicy) *authorization.Policy {
        a := &authorization.Policy{}
        a.Name = key
        a.Spec = &authorization.PolicySpec{}
@@ -211,6 +234,8 @@ func CopyToAuthorization(key string, pa 
*apiV1beta1.AuthorizationPolicy) *author
                                        NotPrincipals: rule.From.NotPrincipals,
                                },
                                To: &authorization.Target{
+                                       Namespaces:    rule.To.Namespaces,
+                                       NotNamespaces: rule.To.NotNamespaces,
                                        IpBlocks:      rule.To.IpBlocks,
                                        NotIpBlocks:   rule.To.NotIpBlocks,
                                        Principals:    rule.To.Principals,
@@ -273,6 +298,28 @@ func CopyToAuthorization(key string, pa 
*apiV1beta1.AuthorizationPolicy) *author
                }
        }
        a.Spec.Samples = pa.Spec.Samples
+       a.Spec.Order = pa.Spec.Order
        a.Spec.MatchType = pa.Spec.MatchType
+
+       if rootNamespace == pa.Namespace {
+               return a
+       }
+
+       if len(a.Spec.Rules) == 0 {
+               a.Spec.Rules = append(a.Spec.Rules, &authorization.PolicyRule{
+                       To: &authorization.Target{
+                               Namespaces: []string{pa.Namespace},
+                       },
+               })
+       } else {
+               for _, rule := range a.Spec.Rules {
+                       if rule.To != nil {
+                               rule.To = &authorization.Target{}
+                       }
+                       if !slices.Contains(rule.To.Namespaces, pa.Namespace) {
+                               rule.To.Namespaces = append(rule.To.Namespaces, 
pa.Namespace)
+                       }
+               }
+       }
        return a
 }
diff --git a/pkg/authority/rule/authentication/definition.go 
b/pkg/authority/rule/authentication/definition.go
index e61176a1..0165c709 100644
--- a/pkg/authority/rule/authentication/definition.go
+++ b/pkg/authority/rule/authentication/definition.go
@@ -21,12 +21,39 @@ type Policy struct {
        Spec *PolicySpec `json:"spec"`
 }
 
+func (p *Policy) CopyToClient() *PolicyToClient {
+       toClient := &PolicyToClient{
+               Name: p.Name,
+       }
+
+       if p.Spec != nil {
+               toClient.Spec = p.Spec.CopyToClient()
+       }
+
+       return toClient
+}
+
 type PolicySpec struct {
        Action    string       `json:"action"`
        Selector  []*Selector  `json:"selector,omitempty"`
        PortLevel []*PortLevel `json:"PortLevel,omitempty"`
 }
 
+func (p *PolicySpec) CopyToClient() *PolicySpecToClient {
+       toClient := &PolicySpecToClient{
+               Action: p.Action,
+       }
+
+       if p.PortLevel != nil {
+               toClient.PortLevel = make([]*PortLevelToClient, 0, 
len(p.PortLevel))
+               for _, portLevel := range p.PortLevel {
+                       toClient.PortLevel = append(toClient.PortLevel, 
portLevel.CopyToClient())
+               }
+       }
+
+       return toClient
+}
+
 type Selector struct {
        Namespaces    []string  `json:"namespaces,omitempty"`
        NotNamespaces []string  `json:"notNamespaces,omitempty"`
@@ -43,6 +70,13 @@ type PortLevel struct {
        Action string `json:"action,omitempty"`
 }
 
+func (p *PortLevel) CopyToClient() *PortLevelToClient {
+       return &PortLevelToClient{
+               Port:   p.Port,
+               Action: p.Action,
+       }
+}
+
 type Extend struct {
        Key   string `json:"key,omitempty"`
        Value string `json:"value,omitempty"`
diff --git a/pkg/authority/rule/authentication/rule.go 
b/pkg/authority/rule/authentication/rule.go
index fd67672d..fd9fa3d0 100644
--- a/pkg/authority/rule/authentication/rule.go
+++ b/pkg/authority/rule/authentication/rule.go
@@ -61,8 +61,6 @@ func (o *Origin) Revision() int64 {
 func (o *Origin) Exact(endpoint *rule.Endpoint) (rule.ToClient, error) {
        matchedRule := make([]*PolicyToClient, 0, len(o.data))
 
-       // TODO match endpoint
-
        for _, v := range o.data {
                if v.Spec == nil {
                        continue
@@ -81,20 +79,7 @@ func (o *Origin) Exact(endpoint *rule.Endpoint) 
(rule.ToClient, error) {
                        }
                }
 
-               toClient := &PolicyToClient{
-                       Name: v.Name,
-                       Spec: &PolicySpecToClient{
-                               Action: v.Spec.Action,
-                       },
-               }
-               if v.Spec.PortLevel != nil {
-                       for _, p := range v.Spec.PortLevel {
-                               toClient.Spec.PortLevel = 
append(toClient.Spec.PortLevel, &PortLevelToClient{
-                                       Port:   p.Port,
-                                       Action: p.Action,
-                               })
-                       }
-               }
+               toClient := v.CopyToClient()
                matchedRule = append(matchedRule, toClient)
        }
 
diff --git a/pkg/authority/rule/authorization/definition.go 
b/pkg/authority/rule/authorization/definition.go
index c9a756d1..3670ac4b 100644
--- a/pkg/authority/rule/authorization/definition.go
+++ b/pkg/authority/rule/authorization/definition.go
@@ -21,19 +21,64 @@ type Policy struct {
        Spec *PolicySpec `json:"spec"`
 }
 
+func (p *Policy) CopyToClient() *PolicyToClient {
+       toClient := &PolicyToClient{
+               Name: p.Name,
+       }
+
+       if p.Spec != nil {
+               toClient.Spec = p.Spec.CopyToClient()
+       }
+
+       return toClient
+}
+
 type PolicySpec struct {
        Action    string        `json:"action,omitempty"`
        Rules     []*PolicyRule `json:"rules,omitempty"`
        Samples   float32       `json:"samples,omitempty"`
+       Order     float32       `json:"order,omitempty"`
        MatchType string        `json:"matchType,omitempty"`
 }
 
+func (p *PolicySpec) CopyToClient() *PolicySpecToClient {
+       toClient := &PolicySpecToClient{
+               Action:    p.Action,
+               Samples:   p.Samples,
+               Order:     p.Order,
+               MatchType: p.MatchType,
+       }
+
+       if p.Rules != nil {
+               toClient.Rules = make([]*PolicyRuleToClient, 0, len(p.Rules))
+               for _, rule := range p.Rules {
+                       toClient.Rules = append(toClient.Rules, 
rule.CopyToClient())
+               }
+       }
+
+       return toClient
+}
+
 type PolicyRule struct {
        From *Source    `json:"from,omitempty"`
        To   *Target    `json:"to,omitempty"`
        When *Condition `json:"when,omitempty"`
 }
 
+func (p *PolicyRule) CopyToClient() *PolicyRuleToClient {
+       toClient := &PolicyRuleToClient{}
+
+       if p.From != nil {
+               toClient.From = p.From.CopyToClient()
+       }
+
+       if p.When != nil {
+               toClient.When = p.When.CopyToClient()
+       }
+
+       return toClient
+}
+
 type Source struct {
        Namespaces    []string  `json:"namespaces,omitempty"`
        NotNamespaces []string  `json:"notNamespaces,omitempty"`
@@ -45,7 +90,59 @@ type Source struct {
        NotExtends    []*Extend `json:"sourceNotExtends,omitempty"`
 }
 
+func (s *Source) CopyToClient() *SourceToClient {
+       toClient := &SourceToClient{}
+
+       if s.Namespaces != nil {
+               toClient.Namespaces = make([]string, len(s.Namespaces))
+               copy(toClient.Namespaces, s.Namespaces)
+       }
+
+       if s.NotNamespaces != nil {
+               toClient.NotNamespaces = make([]string, len(s.NotNamespaces))
+               copy(toClient.NotNamespaces, s.NotNamespaces)
+       }
+
+       if s.IpBlocks != nil {
+               toClient.IpBlocks = make([]string, len(s.IpBlocks))
+               copy(toClient.IpBlocks, s.IpBlocks)
+       }
+
+       if s.NotIpBlocks != nil {
+               toClient.NotIpBlocks = make([]string, len(s.NotIpBlocks))
+               copy(toClient.NotIpBlocks, s.NotIpBlocks)
+       }
+
+       if s.Principals != nil {
+               toClient.Principals = make([]string, len(s.Principals))
+               copy(toClient.Principals, s.Principals)
+       }
+
+       if s.NotPrincipals != nil {
+               toClient.NotPrincipals = make([]string, len(s.NotPrincipals))
+               copy(toClient.NotPrincipals, s.NotPrincipals)
+       }
+
+       if s.Extends != nil {
+               toClient.Extends = make([]*ExtendToClient, len(s.Extends))
+               for i, v := range s.Extends {
+                       toClient.Extends[i] = v.CopyToClient()
+               }
+       }
+
+       if s.NotExtends != nil {
+               toClient.NotExtends = make([]*ExtendToClient, len(s.NotExtends))
+               for i, v := range s.NotExtends {
+                       toClient.NotExtends[i] = v.CopyToClient()
+               }
+       }
+
+       return toClient
+}
+
 type Target struct {
+       Namespaces    []string  `json:"namespaces,omitempty"`
+       NotNamespaces []string  `json:"notNamespaces,omitempty"`
        IpBlocks      []string  `json:"ipBlocks,omitempty"`
        NotIpBlocks   []string  `json:"notIpBlocks,omitempty"`
        Principals    []string  `json:"principals,omitempty"`
@@ -60,12 +157,107 @@ type Condition struct {
        NotValues []*Match `json:"notValues,omitempty"`
 }
 
+func (c *Condition) CopyToClient() *ConditionToClient {
+       toClient := &ConditionToClient{
+               Key: c.Key,
+       }
+
+       if c.Values != nil {
+               toClient.Values = make([]*MatchToClient, len(c.Values))
+               for i, v := range c.Values {
+                       toClient.Values[i] = v.CopyToClient()
+               }
+       }
+
+       if c.NotValues != nil {
+               toClient.NotValues = make([]*MatchToClient, len(c.NotValues))
+               for i, v := range c.NotValues {
+                       toClient.NotValues[i] = v.CopyToClient()
+               }
+       }
+
+       return toClient
+}
+
 type Match struct {
        Type  string `json:"type,omitempty"`
        Value string `json:"value,omitempty"`
 }
 
+func (m *Match) CopyToClient() *MatchToClient {
+       return &MatchToClient{
+               Type:  m.Type,
+               Value: m.Value,
+       }
+}
+
 type Extend struct {
        Key   string `json:"key,omitempty"`
        Value string `json:"value,omitempty"`
 }
+
+func (e *Extend) CopyToClient() *ExtendToClient {
+       return &ExtendToClient{
+               Key:   e.Key,
+               Value: e.Value,
+       }
+}
+
+// To Client Rule
+
+type PolicyToClient struct {
+       Name string `json:"name,omitempty"`
+
+       Spec *PolicySpecToClient `json:"spec"`
+}
+
+type PolicySpecToClient struct {
+       Action    string                `json:"action,omitempty"`
+       Rules     []*PolicyRuleToClient `json:"rules,omitempty"`
+       Samples   float32               `json:"samples,omitempty"`
+       Order     float32               `json:"order,omitempty"`
+       MatchType string                `json:"matchType,omitempty"`
+}
+
+type PolicyRuleToClient struct {
+       From *SourceToClient    `json:"from,omitempty"`
+       When *ConditionToClient `json:"when,omitempty"`
+}
+
+type SourceToClient struct {
+       Namespaces    []string          `json:"namespaces,omitempty"`
+       NotNamespaces []string          `json:"notNamespaces,omitempty"`
+       IpBlocks      []string          `json:"ipBlocks,omitempty"`
+       NotIpBlocks   []string          `json:"notIpBlocks,omitempty"`
+       Principals    []string          `json:"principals,omitempty"`
+       NotPrincipals []string          `json:"notPrincipals,omitempty"`
+       Extends       []*ExtendToClient `json:"sourceExtends,omitempty"`
+       NotExtends    []*ExtendToClient `json:"sourceNotExtends,omitempty"`
+}
+
+type TargetToClient struct {
+       Namespaces    []string          `json:"namespaces,omitempty"`
+       NotNamespaces []string          `json:"notNamespaces,omitempty"`
+       IpBlocks      []string          `json:"ipBlocks,omitempty"`
+       NotIpBlocks   []string          `json:"notIpBlocks,omitempty"`
+       Principals    []string          `json:"principals,omitempty"`
+       NotPrincipals []string          `json:"notPrincipals,omitempty"`
+       Extends       []*ExtendToClient `json:"targetExtends,omitempty"`
+       NotExtends    []*ExtendToClient `json:"targetNotExtends,omitempty"`
+}
+
+type ConditionToClient struct {
+       Key       string           `json:"key,omitempty"`
+       Values    []*MatchToClient `json:"values,omitempty"`
+       NotValues []*MatchToClient `json:"notValues,omitempty"`
+}
+
+type MatchToClient struct {
+       Type  string `json:"type,omitempty"`
+       Value string `json:"value,omitempty"`
+}
+
+type ExtendToClient struct {
+       Key   string `json:"key,omitempty"`
+       Value string `json:"value,omitempty"`
+}
diff --git a/pkg/authority/rule/authorization/definition_test.go 
b/pkg/authority/rule/authorization/definition_test.go
new file mode 100644
index 00000000..01396821
--- /dev/null
+++ b/pkg/authority/rule/authorization/definition_test.go
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package authorization
+
+import (
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+)
+
+func TestCopy(t *testing.T) {
+       policy := &Policy{
+               Name: "test-policy",
+               Spec: &PolicySpec{
+                       Action: "test-action",
+                       Rules: []*PolicyRule{
+                               {
+                                       From: &Source{
+                                               Namespaces:    
[]string{"test-namespace"},
+                                               NotNamespaces: 
[]string{"test-not-namespace"},
+                                               IpBlocks:      
[]string{"test-ip-block"},
+                                               NotIpBlocks:   
[]string{"test-not-ip-block"},
+                                               Principals:    
[]string{"test-principal"},
+                                               NotPrincipals: 
[]string{"test-not-principal"},
+                                               Extends: []*Extend{
+                                                       {
+                                                               Key:   
"test-key",
+                                                               Value: 
"test-value",
+                                                       },
+                                               },
+                                               NotExtends: []*Extend{
+                                                       {
+                                                               Key:   
"test-not-key",
+                                                               Value: 
"test-not-value",
+                                                       },
+                                               },
+                                       },
+                                       To: &Target{
+                                               Namespaces:    
[]string{"test-namespace"},
+                                               NotNamespaces: 
[]string{"test-not-namespace"},
+                                               IpBlocks:      
[]string{"test-ip-block"},
+                                               NotIpBlocks:   
[]string{"test-not-ip-block"},
+                                               Principals:    
[]string{"test-principal"},
+                                               NotPrincipals: 
[]string{"test-not-principal"},
+                                               Extends: []*Extend{
+                                                       {
+                                                               Key:   
"test-key",
+                                                               Value: 
"test-value",
+                                                       },
+                                               },
+                                               NotExtends: []*Extend{
+                                                       {
+                                                               Key:   
"test-not-key",
+                                                               Value: 
"test-not-value",
+                                                       },
+                                               },
+                                       },
+                                       When: &Condition{
+                                               Key: "test-key",
+                                               Values: []*Match{
+                                                       {
+                                                               Type:  
"test-type",
+                                                               Value: 
"test-value",
+                                                       },
+                                               },
+                                               NotValues: []*Match{
+                                                       {
+                                                               Type:  
"test-not-type",
+                                                               Value: 
"test-not-value",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       Samples:   0.5,
+                       Order:     0.5,
+                       MatchType: "test-match-type",
+               },
+       }
+
+       toClient := policy.CopyToClient()
+
+       assert.Equal(t, policy.Name, toClient.Name)
+
+       assert.Equal(t, policy.Spec.Action, toClient.Spec.Action)
+       assert.Equal(t, policy.Spec.Samples, toClient.Spec.Samples)
+       assert.Equal(t, policy.Spec.Order, toClient.Spec.Order)
+       assert.Equal(t, policy.Spec.MatchType, toClient.Spec.MatchType)
+
+       assert.Equal(t, policy.Spec.Rules[0].From.Namespaces, 
toClient.Spec.Rules[0].From.Namespaces)
+       assert.Equal(t, policy.Spec.Rules[0].From.NotNamespaces, 
toClient.Spec.Rules[0].From.NotNamespaces)
+       assert.Equal(t, policy.Spec.Rules[0].From.IpBlocks, 
toClient.Spec.Rules[0].From.IpBlocks)
+       assert.Equal(t, policy.Spec.Rules[0].From.NotIpBlocks, 
toClient.Spec.Rules[0].From.NotIpBlocks)
+       assert.Equal(t, policy.Spec.Rules[0].From.Principals, 
toClient.Spec.Rules[0].From.Principals)
+       assert.Equal(t, policy.Spec.Rules[0].From.NotPrincipals, 
toClient.Spec.Rules[0].From.NotPrincipals)
+       assert.Equal(t, policy.Spec.Rules[0].From.Extends[0].Key, 
toClient.Spec.Rules[0].From.Extends[0].Key)
+       assert.Equal(t, policy.Spec.Rules[0].From.Extends[0].Value, 
toClient.Spec.Rules[0].From.Extends[0].Value)
+       assert.Equal(t, policy.Spec.Rules[0].From.NotExtends[0].Key, 
toClient.Spec.Rules[0].From.NotExtends[0].Key)
+       assert.Equal(t, policy.Spec.Rules[0].From.NotExtends[0].Value, 
toClient.Spec.Rules[0].From.NotExtends[0].Value)
+
+       assert.Equal(t, policy.Spec.Rules[0].When.Key, 
toClient.Spec.Rules[0].When.Key)
+       assert.Equal(t, policy.Spec.Rules[0].When.Values[0].Type, 
toClient.Spec.Rules[0].When.Values[0].Type)
+       assert.Equal(t, policy.Spec.Rules[0].When.Values[0].Value, 
toClient.Spec.Rules[0].When.Values[0].Value)
+       assert.Equal(t, policy.Spec.Rules[0].When.NotValues[0].Type, 
toClient.Spec.Rules[0].When.NotValues[0].Type)
+       assert.Equal(t, policy.Spec.Rules[0].When.NotValues[0].Value, 
toClient.Spec.Rules[0].When.NotValues[0].Value)
+}
diff --git a/pkg/authority/rule/authorization/rule.go 
b/pkg/authority/rule/authorization/rule.go
index 92091ea6..ecb7d99c 100644
--- a/pkg/authority/rule/authorization/rule.go
+++ b/pkg/authority/rule/authorization/rule.go
@@ -17,6 +17,11 @@ package authorization
 
 import (
        "encoding/json"
+       "net/netip"
+       "strings"
+
+       "github.com/apache/dubbo-admin/pkg/logger"
+       "github.com/tidwall/gjson"
 
        "github.com/apache/dubbo-admin/pkg/authority/rule"
 )
@@ -53,20 +58,206 @@ func (o *Origin) Revision() int64 {
        return o.revision
 }
 
-func (o *Origin) Exact(endpoint *rule.Endpoint) (rule.ToClient, error) { 
//nolint:ireturn
-       matchedRule := make([]*Policy, 0, len(o.data))
+func (o *Origin) Exact(endpoint *rule.Endpoint) (rule.ToClient, error) {
+       matchedRule := make([]*PolicyToClient, 0, len(o.data))
 
        for _, v := range o.data {
-               matchedRule = append(matchedRule, v)
+               if v.Spec == nil {
+                       continue
+               }
+
+               if v.Spec.Rules != nil {
+                       match := true
+                       for _, policyRule := range v.Spec.Rules {
+                               if !matchSelector(policyRule.To, endpoint) {
+                                       match = false
+                                       break
+                               }
+                       }
+                       if !match {
+                               continue
+                       }
+               }
+
+               toClient := v.CopyToClient()
+               matchedRule = append(matchedRule, toClient)
        }
 
-       allRules, err := json.Marshal(matchedRule)
+       allRule, err := json.Marshal(matchedRule)
        if err != nil {
                return nil, err
        }
 
        return &ToClient{
                revision: o.revision,
-               data:     string(allRules),
+               data:     string(allRule),
        }, nil
 }
+
+func matchSelector(target *Target, endpoint *rule.Endpoint) bool {
+       if endpoint == nil {
+               return true
+       }
+
+       if !matchNamespace(target, endpoint) {
+               return false
+       }
+
+       if !matchNotNamespace(target, endpoint) {
+               return false
+       }
+
+       if !matchIPBlocks(target, endpoint) {
+               return false
+       }
+
+       if !matchNotIPBlocks(target, endpoint) {
+               return false
+       }
+
+       if !matchPrincipals(target, endpoint) {
+               return false
+       }
+
+       if !matchNotPrincipals(target, endpoint) {
+               return false
+       }
+
+       endpointJSON, err := json.Marshal(endpoint)
+       if err != nil {
+               logger.Sugar().Warnf("marshal endpoint failed, %v", err)
+               return false
+       }
+
+       if !matchExtends(target, endpointJSON) {
+               return false
+       }
+
+       return matchNotExtends(target, endpointJSON)
+}
+
+func matchNotExtends(target *Target, endpointJSON []byte) bool {
+       if len(target.NotExtends) == 0 {
+               return true
+       }
+       for _, extend := range target.NotExtends {
+               if gjson.Get(string(endpointJSON), extend.Key).String() == 
extend.Value {
+                       return false
+               }
+       }
+       return true
+}
+
+func matchExtends(target *Target, endpointJSON []byte) bool {
+       if len(target.Extends) == 0 {
+               return true
+       }
+       for _, extend := range target.Extends {
+               if gjson.Get(string(endpointJSON), extend.Key).String() == 
extend.Value {
+                       return true
+               }
+       }
+       return false
+}
+
+func matchNotPrincipals(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.NotPrincipals) == 0 {
+               return true
+       }
+       for _, principal := range target.NotPrincipals {
+               if principal == endpoint.SpiffeID {
+                       return false
+               }
+               if strings.ReplaceAll(endpoint.SpiffeID, "spiffe://", "") == 
principal {
+                       return false
+               }
+       }
+       return true
+}
+
+func matchPrincipals(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.Principals) == 0 {
+               return true
+       }
+       for _, principal := range target.Principals {
+               if principal == endpoint.SpiffeID {
+                       return true
+               }
+               if strings.ReplaceAll(endpoint.SpiffeID, "spiffe://", "") == 
principal {
+                       return true
+               }
+       }
+       return false
+}
+
+func matchNotIPBlocks(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.NotIpBlocks) == 0 {
+               return true
+       }
+       for _, ipBlock := range target.NotIpBlocks {
+               prefix, err := netip.ParsePrefix(ipBlock)
+               if err != nil {
+                       logger.Sugar().Warnf("parse ip block %s failed, %v", 
ipBlock, err)
+                       continue
+               }
+               for _, ip := range endpoint.Ips {
+                       addr, err := netip.ParseAddr(ip)
+                       if err != nil {
+                               logger.Sugar().Warnf("parse ip %s failed, %v", 
ip, err)
+                               continue
+                       }
+                       if prefix.Contains(addr) {
+                               return false
+                       }
+               }
+       }
+       return true
+}
+
+func matchIPBlocks(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.IpBlocks) == 0 {
+               return true
+       }
+       for _, ipBlock := range target.IpBlocks {
+               prefix, err := netip.ParsePrefix(ipBlock)
+               if err != nil {
+                       logger.Sugar().Warnf("parse ip block %s failed, %v", 
ipBlock, err)
+                       continue
+               }
+               for _, ip := range endpoint.Ips {
+                       addr, err := netip.ParseAddr(ip)
+                       if err != nil {
+                               logger.Sugar().Warnf("parse ip %s failed, %v", 
ip, err)
+                               continue
+                       }
+                       if prefix.Contains(addr) {
+                               return true
+                       }
+               }
+       }
+       return false
+}
+
+func matchNotNamespace(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.NotNamespaces) == 0 {
+               return true
+       }
+       for _, namespace := range target.NotNamespaces {
+               if endpoint.KubernetesEnv != nil && namespace == 
endpoint.KubernetesEnv.Namespace {
+                       return false
+               }
+       }
+       return true
+}
+
+func matchNamespace(target *Target, endpoint *rule.Endpoint) bool {
+       if len(target.Namespaces) == 0 {
+               return true
+       }
+       for _, namespace := range target.Namespaces {
+               if endpoint.KubernetesEnv != nil && namespace == 
endpoint.KubernetesEnv.Namespace {
+                       return true
+               }
+       }
+       return false
+}
diff --git a/pkg/authority/rule/authorization/rule_test.go 
b/pkg/authority/rule/authorization/rule_test.go
index c336b464..17af761d 100644
--- a/pkg/authority/rule/authorization/rule_test.go
+++ b/pkg/authority/rule/authorization/rule_test.go
@@ -13,7 +13,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package authorization_test
+package authorization
 
 import (
        "encoding/json"
@@ -22,7 +22,6 @@ import (
        "github.com/stretchr/testify/assert"
 
        "github.com/apache/dubbo-admin/pkg/authority/rule"
-       "github.com/apache/dubbo-admin/pkg/authority/rule/authorization"
        "github.com/apache/dubbo-admin/pkg/authority/rule/connection"
 )
 
@@ -30,17 +29,17 @@ func TestRule(t *testing.T) {
        t.Parallel()
 
        storage := connection.NewStorage()
-       handler := authorization.NewHandler(storage)
+       handler := NewHandler(storage)
 
-       handler.Add("test", &authorization.Policy{})
+       handler.Add("test", &Policy{})
 
-       originRule := storage.LatestRules[authorization.RuleType]
+       originRule := storage.LatestRules[RuleType]
 
        if originRule == nil {
                t.Error("expected origin rule to be added")
        }
 
-       if originRule.Type() != authorization.RuleType {
+       if originRule.Type() != RuleType {
                t.Error("expected origin rule type to be authorization/v1beta1")
        }
 
@@ -56,7 +55,7 @@ func TestRule(t *testing.T) {
                t.Error(err)
        }
 
-       if toClient.Type() != authorization.RuleType {
+       if toClient.Type() != RuleType {
                t.Error("expected toClient type to be authorization/v1beta1")
        }
 
@@ -64,26 +63,26 @@ func TestRule(t *testing.T) {
                t.Error("expected toClient revision to be 1")
        }
 
-       if toClient.Data() != `[{"spec":null}]` {
-               t.Error("expected toClient data to be [{\"spec\":null}], got " 
+ toClient.Data())
+       if toClient.Data() != `[]` {
+               t.Error("expected toClient data to be [], got " + 
toClient.Data())
        }
 
-       policy := &authorization.Policy{
+       policy := &Policy{
                Name: "test2",
-               Spec: &authorization.PolicySpec{
+               Spec: &PolicySpec{
                        Action: "ALLOW",
                },
        }
 
        handler.Add("test2", policy)
 
-       originRule = storage.LatestRules[authorization.RuleType]
+       originRule = storage.LatestRules[RuleType]
 
        if originRule == nil {
                t.Error("expected origin rule to be added")
        }
 
-       if originRule.Type() != authorization.RuleType {
+       if originRule.Type() != RuleType {
                t.Error("expected origin rule type to be authorization/v1beta1")
        }
 
@@ -100,7 +99,7 @@ func TestRule(t *testing.T) {
                t.Error(err)
        }
 
-       if toClient.Type() != authorization.RuleType {
+       if toClient.Type() != RuleType {
                t.Error("expected toClient type to be authorization/v1beta1")
        }
 
@@ -108,12 +107,837 @@ func TestRule(t *testing.T) {
                t.Error("expected toClient revision to be 2")
        }
 
-       target := []*authorization.Policy{}
+       target := []*Policy{}
 
        err = json.Unmarshal([]byte(toClient.Data()), &target)
        assert.Nil(t, err)
-       assert.Equal(t, 2, len(target))
+       assert.Equal(t, 1, len(target))
 
-       assert.Contains(t, target, &authorization.Policy{})
        assert.Contains(t, target, policy)
 }
+
+func TestRule_Empty(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {},
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       generated, err := origin.Exact(nil)
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}
+
+func TestRule_Namespace(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               Namespaces: 
[]string{"test"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       Namespace: "test",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       Namespace: "test-new",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+}
+
+func TestRule_NotNamespace(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               NotNamespaces: 
[]string{"test"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       Namespace: "test-new",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       Namespace: "test",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}
+
+func TestRule_IPBlocks(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               IpBlocks: 
[]string{"127.0.0.1/24"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.0.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.1.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+}
+
+func TestRule_IPBlocks_ErrFmt(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               IpBlocks: 
[]string{"127"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // failed
+       generated, err := origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.0.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.1.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+}
+
+func TestRule_NotIPBlocks(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               NotIpBlocks: 
[]string{"127.0.0.1/24"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.1.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.0.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}
+
+func TestRule_NotIPBlocks_ErrFmt(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               NotIpBlocks: 
[]string{"127"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.0.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{
+               Ips: []string{"127.0.1.1"},
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}
+
+func TestRule_Principals(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               Principals: 
[]string{"cluster.local/ns/default/sa/default"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               SpiffeID: "cluster.local/ns/default/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{
+               SpiffeID: "spiffe://cluster.local/ns/default/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               SpiffeID: "cluster.local/ns/test/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+}
+
+func TestRule_NotPrincipals(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               NotPrincipals: 
[]string{"cluster.local/ns/default/sa/default"},
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               SpiffeID: "cluster.local/ns/test/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{
+               SpiffeID: "spiffe://cluster.local/ns/test/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               SpiffeID: "cluster.local/ns/default/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               SpiffeID: "spiffe://cluster.local/ns/default/sa/default",
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}
+
+func TestRule_Extends(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               Extends: 
[]*Extend{
+                                                                       {
+                                                                               
Key:   "kubernetesEnv.podName",
+                                                                               
Value: "test",
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       PodName: "test",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       PodName: "test-new",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+}
+
+func TestRule_NotExtends(t *testing.T) {
+       t.Parallel()
+
+       origin := &Origin{
+               revision: 1,
+               data: map[string]*Policy{
+                       "test": {
+                               Spec: &PolicySpec{
+                                       Action: "ALLOW",
+                                       Rules: []*PolicyRule{
+                                               {
+                                                       To: &Target{
+                                                               NotExtends: 
[]*Extend{
+                                                                       {
+                                                                               
Key:   "kubernetesEnv.podName",
+                                                                               
Value: "test",
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       "demo": {},
+               },
+       }
+
+       // success
+       generated, err := origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       PodName: "test-new",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       var decoded []*PolicyToClient
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+
+       // failed
+       generated, err = origin.Exact(&rule.Endpoint{
+               KubernetesEnv: &rule.KubernetesEnv{
+                       PodName: "test",
+               },
+       })
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 0, len(decoded))
+
+       // success
+       generated, err = origin.Exact(&rule.Endpoint{})
+       assert.Nil(t, err)
+
+       assert.NotNil(t, generated)
+       assert.Equal(t, generated.Type(), RuleType)
+       assert.Equal(t, generated.Revision(), int64(1))
+
+       err = json.Unmarshal([]byte(generated.Data()), &decoded)
+       assert.Nil(t, err)
+
+       assert.Equal(t, 1, len(decoded))
+       assert.Equal(t, "ALLOW", decoded[0].Spec.Action)
+}

Reply via email to