Skip to content

Commit fc051f4

Browse files
committed
Determine webhook-traffic-netpol granulation based on configuration
We want to determine whether the webhook-traffic-netpol rule will allow network traffic with or without `From` section based on configuration. When adding the `From` section, it means that the policy would be more strict (Will allow traffic only from IPs recognized as control-plane addresses).
1 parent 3b9702d commit fc051f4

File tree

5 files changed

+122
-48
lines changed

5 files changed

+122
-48
lines changed

src/operator/controllers/webhook_traffic/network_policy_handler.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,22 @@ type NetworkPolicyHandler struct {
5454
injectablerecorder.InjectableRecorder
5555
policy automate_third_party_network_policy.Enum
5656
controlPlaneCIDRPrefixLength int
57+
allowAllIncomingTraffic bool
5758
}
5859

5960
func NewNetworkPolicyHandler(
6061
client client.Client,
6162
scheme *runtime.Scheme,
6263
policy automate_third_party_network_policy.Enum,
6364
controlPlaneCIDRPrefixLength int,
65+
allowAllIncomingTraffic bool,
6466
) *NetworkPolicyHandler {
6567
return &NetworkPolicyHandler{
6668
client: client,
6769
scheme: scheme,
6870
policy: policy,
6971
controlPlaneCIDRPrefixLength: controlPlaneCIDRPrefixLength,
72+
allowAllIncomingTraffic: allowAllIncomingTraffic,
7073
}
7174
}
7275

@@ -306,22 +309,24 @@ func (n *NetworkPolicyHandler) getWebhookService(ctx context.Context, webhookSer
306309

307310
func (n *NetworkPolicyHandler) buildNetworkPolicy(ctx context.Context, webhookName string, webhookService *admissionv1.ServiceReference, service *corev1.Service) (v1.NetworkPolicy, error) {
308311
policyName := fmt.Sprintf("webhook-%s-access-to-%s", strings.ToLower(webhookName), strings.ToLower(service.Name))
312+
rule := v1.NetworkPolicyIngressRule{}
309313

310-
controlPlaneIPs, err := n.getControlPlaneIPsAsCIDR(ctx)
311-
if err != nil {
312-
return v1.NetworkPolicy{}, errors.Wrap(err)
313-
}
314-
315-
fromControlPlaneIPs := lo.Map(controlPlaneIPs, func(controlPLaneIP string, _ int) v1.NetworkPolicyPeer {
316-
return v1.NetworkPolicyPeer{
317-
IPBlock: &v1.IPBlock{
318-
CIDR: controlPLaneIP,
319-
},
314+
if !n.allowAllIncomingTraffic {
315+
controlPlaneIPs, err := n.getControlPlaneIPsAsCIDR(ctx)
316+
if err != nil {
317+
return v1.NetworkPolicy{}, errors.Wrap(err)
320318
}
321-
})
322319

323-
rule := v1.NetworkPolicyIngressRule{}
324-
rule.From = append(rule.From, fromControlPlaneIPs...)
320+
fromControlPlaneIPs := lo.Map(controlPlaneIPs, func(controlPLaneIP string, _ int) v1.NetworkPolicyPeer {
321+
return v1.NetworkPolicyPeer{
322+
IPBlock: &v1.IPBlock{
323+
CIDR: controlPLaneIP,
324+
},
325+
}
326+
})
327+
328+
rule.From = append(rule.From, fromControlPlaneIPs...)
329+
}
325330

326331
newPolicy := v1.NetworkPolicy{
327332
ObjectMeta: metav1.ObjectMeta{

src/operator/controllers/webhook_traffic/network_policy_handler_test.go

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ type NetworkPolicyHandlerTestSuite struct {
103103

104104
func (s *NetworkPolicyHandlerTestSuite) SetupTest() {
105105
s.MocksSuiteBase.SetupTest()
106-
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.IfBlockedByOtterize, 32)
106+
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.IfBlockedByOtterize, 32, false)
107107
s.handler.InjectRecorder(s.Recorder)
108108

109109
s.validatingWebhook = ValidatingWebhookConfiguration.DeepCopy()
@@ -154,7 +154,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
154154
s.mockGetControlPlaneIPs()
155155
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
156156

157-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
157+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, false)
158158
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
159159
err := s.handler.HandleAll(context.Background())
160160
s.Require().NoError(err)
@@ -189,7 +189,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
189189

190190
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
191191

192-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
192+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
193193
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
194194
err := s.handler.HandleAll(context.Background())
195195
s.Require().NoError(err)
@@ -225,7 +225,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
225225

226226
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
227227

228-
netpolMatcher := NewNetworkPolicyMatcher([]int32{secondPort, TestServicePort})
228+
netpolMatcher := NewNetworkPolicyMatcher([]int32{secondPort, TestServicePort}, s.handler.allowAllIncomingTraffic)
229229
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
230230
err := s.handler.HandleAll(context.Background())
231231
s.Require().NoError(err)
@@ -238,8 +238,15 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
238238
s.mockReturningWebhookService()
239239
s.mockServiceIsBlockedByOtterize(OtterizeIngressNetpols)
240240
s.mockGetControlPlaneIPs()
241-
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{*getExpectedNetpolWithPorts([]int32{TestServicePort})})
242-
s.mockGetNetworkPolicyForUpdate(*getExpectedNetpolWithPorts([]int32{TestServicePort}))
241+
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{
242+
NewNetworkPolicyBuilder(ExpectedNetpol).
243+
WithPorts([]int32{TestServicePort}).
244+
WithFromIPBlock(s.handler.allowAllIncomingTraffic).
245+
Build()})
246+
s.mockGetNetworkPolicyForUpdate(NewNetworkPolicyBuilder(ExpectedNetpol).
247+
WithPorts([]int32{TestServicePort}).
248+
WithFromIPBlock(s.handler.allowAllIncomingTraffic).
249+
Build())
243250

244251
//netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
245252
//s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
@@ -254,10 +261,18 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
254261
s.mockReturningWebhookService()
255262
s.mockServiceIsBlockedByOtterize(OtterizeIngressNetpols)
256263
s.mockGetControlPlaneIPs()
257-
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{*getExpectedNetpolWithPorts([]int32{12129})})
258-
s.mockGetNetworkPolicyForUpdate(*getExpectedNetpolWithPorts([]int32{12129}))
259-
260-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
264+
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{
265+
NewNetworkPolicyBuilder(ExpectedNetpol).
266+
WithPorts([]int32{12129}).
267+
WithFromIPBlock(s.handler.allowAllIncomingTraffic).
268+
Build()})
269+
s.mockGetNetworkPolicyForUpdate(
270+
NewNetworkPolicyBuilder(ExpectedNetpol).
271+
WithPorts([]int32{12129}).
272+
WithFromIPBlock(s.handler.allowAllIncomingTraffic).
273+
Build())
274+
275+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
261276
s.Client.EXPECT().Patch(gomock.Any(), gomock.All(netpolMatcher), gomock.Any()).Return(nil)
262277
err := s.handler.HandleAll(context.Background())
263278
s.Require().NoError(err)
@@ -281,7 +296,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleIfBlocked
281296
}
282297

283298
func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleOff_ServiceIsBlockedByOtterize_DoNothing() {
284-
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Off, 32)
299+
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Off, 32, false)
285300

286301
s.mockForReturningValidatingWebhook()
287302
//s.mockReturningWebhookService()
@@ -298,15 +313,19 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleOff_Servi
298313
}
299314

300315
func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleOff_ServiceIsBlockedByOtterize_ExistingWebhookPolicy_DeletePolicy() {
301-
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Off, 32)
316+
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Off, 32, false)
302317

303318
s.mockForReturningValidatingWebhook()
304319
//s.mockReturningWebhookService()
305320
//s.mockServiceIsBlockedByOtterize(OtterizeIngressNetpols)
306321
//s.mockGetControlPlaneIPs()
307-
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{*getExpectedNetpolWithPorts([]int32{TestServicePort})})
322+
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{
323+
NewNetworkPolicyBuilder(ExpectedNetpol).
324+
WithPorts([]int32{TestServicePort}).
325+
WithFromIPBlock(s.handler.allowAllIncomingTraffic).
326+
Build()})
308327

309-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
328+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
310329
s.Client.EXPECT().Delete(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
311330
err := s.handler.HandleAll(context.Background())
312331
s.Require().NoError(err)
@@ -315,7 +334,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleOff_Servi
315334
}
316335

317336
func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleAlways_ServiceIsNotBlockedByOtterize_CreatePolicy() {
318-
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Always, 32)
337+
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Always, 32, false)
319338
s.handler.InjectRecorder(s.Recorder)
320339

321340
s.mockForReturningValidatingWebhook()
@@ -324,7 +343,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleAlways_Se
324343
s.mockGetControlPlaneIPs()
325344
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
326345

327-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
346+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
328347
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
329348
err := s.handler.HandleAll(context.Background())
330349
s.Require().NoError(err)
@@ -339,7 +358,7 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_MutatingWebhook
339358
s.mockGetControlPlaneIPs()
340359
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
341360

342-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
361+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
343362
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
344363
err := s.handler.HandleAll(context.Background())
345364
s.Require().NoError(err)
@@ -354,7 +373,25 @@ func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_CRDsWebhooks_Ha
354373
s.mockGetControlPlaneIPs()
355374
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
356375

357-
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort})
376+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
377+
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
378+
err := s.handler.HandleAll(context.Background())
379+
s.Require().NoError(err)
380+
s.ExpectEvent(ReasonCreatingWebhookTrafficNetpol)
381+
s.ExpectEvent(ReasonCreatingWebhookTrafficNetpolSuccess)
382+
}
383+
384+
func (s *NetworkPolicyHandlerTestSuite) TestNetworkPolicyHandler_HandleAlways_AllowAllIncomingTraffic_CreatingWebhookPolicy() {
385+
s.handler = NewNetworkPolicyHandler(s.Client, &runtime.Scheme{}, automate_third_party_network_policy.Always, 32, true)
386+
s.handler.InjectRecorder(s.Recorder)
387+
388+
s.mockForReturningValidatingWebhook()
389+
s.mockReturningWebhookService()
390+
//s.mockServiceIsBlockedByOtterize(OtterizeIngressNetpols)
391+
//s.mockGetControlPlaneIPs()
392+
s.mockGetExistingOtterizeWebhooksNetpols([]v1.NetworkPolicy{})
393+
394+
netpolMatcher := NewNetworkPolicyMatcher([]int32{TestServicePort}, s.handler.allowAllIncomingTraffic)
358395
s.Client.EXPECT().Create(gomock.Any(), gomock.All(netpolMatcher)).Return(nil)
359396
err := s.handler.HandleAll(context.Background())
360397
s.Require().NoError(err)

src/operator/controllers/webhook_traffic/network_policy_handler_utils_test.go

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,28 @@ var ExpectedNetpol = v1.NetworkPolicy{
2424
},
2525
Ingress: []v1.NetworkPolicyIngressRule{
2626
{
27-
Ports: []v1.NetworkPolicyPort{},
28-
From: []v1.NetworkPolicyPeer{
29-
{
30-
IPBlock: &v1.IPBlock{
31-
CIDR: fmt.Sprintf("%s/32", TestControlPlaneIP),
32-
},
33-
},
34-
},
27+
Ports: nil,
28+
From: nil,
3529
},
3630
},
3731
PolicyTypes: []v1.PolicyType{v1.PolicyTypeIngress},
3832
},
3933
}
4034

35+
type NetworkPolicyBuilder struct {
36+
policy *v1.NetworkPolicy
37+
}
38+
4139
type NetworkPolicyMatcher struct {
42-
ports []int32
40+
ports []int32
41+
allowAllIncomingTraffic bool
4342
}
4443

45-
func NewNetworkPolicyMatcher(ports []int32) *NetworkPolicyMatcher {
46-
return &NetworkPolicyMatcher{ports: ports}
44+
func NewNetworkPolicyMatcher(ports []int32, allowAllIncomingTraffic bool) *NetworkPolicyMatcher {
45+
return &NetworkPolicyMatcher{
46+
ports: ports,
47+
allowAllIncomingTraffic: allowAllIncomingTraffic,
48+
}
4749
}
4850

4951
func (m *NetworkPolicyMatcher) String() string {
@@ -56,21 +58,47 @@ func (m *NetworkPolicyMatcher) Matches(other interface{}) bool {
5658
return false
5759
}
5860

59-
expectedNetpol := getExpectedNetpolWithPorts(m.ports)
61+
expectedNetpol := NewNetworkPolicyBuilder(ExpectedNetpol).
62+
WithPorts(m.ports).
63+
WithFromIPBlock(m.allowAllIncomingTraffic).
64+
Build()
6065

6166
return otherAsNetpol.Namespace == TestNamespace &&
6267
otherAsNetpol.Name == expectedNetpol.Name &&
6368
reflect.DeepEqual(otherAsNetpol.Labels, expectedNetpol.Labels) &&
6469
reflect.DeepEqual(otherAsNetpol.Spec, expectedNetpol.Spec)
6570
}
6671

67-
func getExpectedNetpolWithPorts(ports []int32) *v1.NetworkPolicy {
68-
expectedNetpol := ExpectedNetpol.DeepCopy()
69-
expectedNetpol.Spec.Ingress[0].Ports = lo.Map(ports, func(port int32, _ int) v1.NetworkPolicyPort {
72+
func NewNetworkPolicyBuilder(base v1.NetworkPolicy) *NetworkPolicyBuilder {
73+
return &NetworkPolicyBuilder{policy: base.DeepCopy()}
74+
}
75+
76+
func (b *NetworkPolicyBuilder) WithPorts(ports []int32) *NetworkPolicyBuilder {
77+
b.policy.Spec.Ingress[0].Ports = lo.Map(ports, func(port int32, _ int) v1.NetworkPolicyPort {
7078
return v1.NetworkPolicyPort{
7179
Protocol: lo.ToPtr(corev1.ProtocolTCP),
7280
Port: lo.ToPtr(intstr.IntOrString{Type: intstr.Int, IntVal: port}),
7381
}
7482
})
75-
return expectedNetpol
83+
return b
84+
}
85+
86+
func (b *NetworkPolicyBuilder) WithFromIPBlock(allowAll bool) *NetworkPolicyBuilder {
87+
if allowAll {
88+
// leave .From empty
89+
return b
90+
}
91+
92+
b.policy.Spec.Ingress[0].From = []v1.NetworkPolicyPeer{
93+
{
94+
IPBlock: &v1.IPBlock{
95+
CIDR: fmt.Sprintf("%s/32", TestControlPlaneIP),
96+
},
97+
},
98+
}
99+
return b
100+
}
101+
102+
func (b *NetworkPolicyBuilder) Build() v1.NetworkPolicy {
103+
return *b.policy
76104
}

src/operator/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ func main() {
242242
scheme,
243243
automate_third_party_network_policy.Off,
244244
//enforcementConfig.GetAutomateThirdPartyNetworkPolicy(),
245-
viper.GetInt(operatorconfig.ControlPlaneIPv4CidrPrefixLength))
245+
viper.GetInt(operatorconfig.ControlPlaneIPv4CidrPrefixLength),
246+
viper.GetBool(operatorconfig.WebhookTrafficAllowAllKey))
246247
webhookTrafficReconcilerManager := webhook_traffic.NewWebhookTrafficReconcilerManager(mgr.GetClient(), webhooksTrafficNetworkHandler)
247248

248249
if enforcementConfig.EnableLinkerdPolicies {

src/shared/operatorconfig/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ const (
6868
ExternallyManagedPolicyWorkloadsKey = "externallyManagedPolicyWorkloads"
6969
ControlPlaneIPv4CidrPrefixLength = "control-plane-ipv4-cidr-prefix-length"
7070
ControlPlaneIPv4CidrPrefixLengthDefault = 32
71+
WebhookTrafficAllowAllKey = "webhook-traffic-allow-all"
72+
WebhookTrafficAllowAllDefault = true
7173
)
7274

7375
func init() {
@@ -92,6 +94,7 @@ func init() {
9294
viper.SetDefault(EnableGroupInternetIPsByCIDRKey, EnableGroupInternetIPsByCIDRDefault)
9395
viper.SetDefault(EnableGroupInternetIPsByCIDRPeersLimitKey, EnableGroupInternetIPsByCIDRPeersLimitDefault)
9496
viper.SetDefault(ControlPlaneIPv4CidrPrefixLength, ControlPlaneIPv4CidrPrefixLengthDefault)
97+
viper.SetDefault(WebhookTrafficAllowAllKey, WebhookTrafficAllowAllDefault)
9598
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
9699
viper.AutomaticEnv()
97100

0 commit comments

Comments
 (0)