/
rule.go
189 lines (166 loc) · 5.72 KB
/
rule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright 2016-2020 Authors of Cilium
//
// Licensed 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 api
import (
"context"
"encoding/json"
"github.com/cilium/cilium/pkg/labels"
)
// Rule is a policy rule which must be applied to all endpoints which match the
// labels contained in the endpointSelector
//
// Each rule is split into an ingress section which contains all rules
// applicable at ingress, and an egress section applicable at egress. For rule
// types such as `L4Rule` and `CIDR` which can be applied at both ingress and
// egress, both ingress and egress side have to either specifically allow the
// connection or one side has to be omitted.
//
// Either ingress, egress, or both can be provided. If both ingress and egress
// are omitted, the rule has no effect.
// +deepequal-gen:private-method=true
type Rule struct {
// EndpointSelector selects all endpoints which should be subject to
// this rule. EndpointSelector and NodeSelector cannot be both empty and
// are mutually exclusive.
//
// +optional
EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"`
// NodeSelector selects all nodes which should be subject to this rule.
// EndpointSelector and NodeSelector cannot be both empty and are mutually
// exclusive. Can only be used in CiliumClusterwideNetworkPolicies.
//
// +optional
NodeSelector EndpointSelector `json:"nodeSelector,omitempty"`
// Ingress is a list of IngressRule which are enforced at ingress.
// If omitted or empty, this rule does not apply at ingress.
//
// +optional
Ingress []IngressRule `json:"ingress,omitempty"`
// Egress is a list of EgressRule which are enforced at egress.
// If omitted or empty, this rule does not apply at egress.
//
// +optional
Egress []EgressRule `json:"egress,omitempty"`
// Labels is a list of optional strings which can be used to
// re-identify the rule or to store metadata. It is possible to lookup
// or delete strings based on labels. Labels are not required to be
// unique, multiple rules can have overlapping or identical labels.
//
// +optional
Labels labels.LabelArray `json:"labels,omitempty"`
// Description is a free form string, it can be used by the creator of
// the rule to store human readable explanation of the purpose of this
// rule. Rules cannot be identified by comment.
//
// +optional
Description string `json:"description,omitempty"`
}
// MarshalJSON returns the JSON encoding of Rule r. We need to overwrite it to
// enforce omitempty on the EndpointSelector nested structures.
func (r *Rule) MarshalJSON() ([]byte, error) {
type common struct {
Ingress []IngressRule `json:"ingress,omitempty"`
Egress []EgressRule `json:"egress,omitempty"`
Labels labels.LabelArray `json:"labels,omitempty"`
Description string `json:"description,omitempty"`
}
var a interface{}
ruleCommon := common{
Ingress: r.Ingress,
Egress: r.Egress,
Labels: r.Labels,
Description: r.Description,
}
// Only one of endpointSelector or nodeSelector is permitted.
switch {
case r.EndpointSelector.LabelSelector != nil:
a = struct {
EndpointSelector EndpointSelector `json:"endpointSelector,omitempty"`
common
}{
EndpointSelector: r.EndpointSelector,
common: ruleCommon,
}
case r.NodeSelector.LabelSelector != nil:
a = struct {
NodeSelector EndpointSelector `json:"nodeSelector,omitempty"`
common
}{
NodeSelector: r.NodeSelector,
common: ruleCommon,
}
}
return json.Marshal(a)
}
func (r *Rule) DeepEqual(o *Rule) bool {
switch {
case (r == nil) != (o == nil):
return false
case (r == nil) && (o == nil):
return true
}
return r.deepEqual(o)
}
// NewRule builds a new rule with no selector and no policy.
func NewRule() *Rule {
return &Rule{}
}
// WithEndpointSelector configures the Rule with the specified selector.
func (r *Rule) WithEndpointSelector(es EndpointSelector) *Rule {
r.EndpointSelector = es
return r
}
// WithIngressRules configures the Rule with the specified rules.
func (r *Rule) WithIngressRules(rules []IngressRule) *Rule {
r.Ingress = rules
return r
}
// WithEgressRules configures the Rule with the specified rules.
func (r *Rule) WithEgressRules(rules []EgressRule) *Rule {
r.Egress = rules
return r
}
// WithLabels configures the Rule with the specified labels metadata.
func (r *Rule) WithLabels(labels labels.LabelArray) *Rule {
r.Labels = labels
return r
}
// WithDescription configures the Rule with the specified description metadata.
func (r *Rule) WithDescription(desc string) *Rule {
r.Description = desc
return r
}
// RequiresDerivative it return true if the rule has a derivative rule.
func (r *Rule) RequiresDerivative() bool {
for _, rule := range r.Egress {
if rule.RequiresDerivative() {
return true
}
}
return false
}
// CreateDerivative will return a new Rule with the new data based gather
// by the rules that autogenerated new Rule
func (r *Rule) CreateDerivative(ctx context.Context) (*Rule, error) {
newRule := r.DeepCopy()
newRule.Egress = []EgressRule{}
for _, egressRule := range r.Egress {
derivativeEgressRule, err := egressRule.CreateDerivative(ctx)
if err != nil {
return newRule, err
}
newRule.Egress = append(newRule.Egress, *derivativeEgressRule)
}
return newRule, nil
}