Skip to content

Commit 9a40cd0

Browse files
committed
NE-1476: Added network policies for the router
Added the framework for network policies for the router. The operator has a deny all network policy that for the openshift-ingress-operator namespace and an allow policy for egress to the apiserver and dns ports at any IP. The operator installs a deny all network policy for the openshift-ingress namespace. Then for each ingresscontroller that it manages it installs an allow policy for ingress for http and https traffic and metrics. It has to allow ingress from the router pods to any IP because the route endpoints can be at any ip or pod. It also needs access to the api server, but that is covered by the wildcard allow policy. https://issues.redhat.com/browse/NE-1476
1 parent 0c57689 commit 9a40cd0

14 files changed

+363
-7
lines changed

manifests/00-cluster-role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ rules:
155155
- networking.k8s.io
156156
resources:
157157
- ingressclasses
158+
- networkpolicies
158159
verbs:
159160
- '*'
160161

manifests/01-role.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ rules:
3737
- services
3838
verbs:
3939
- "*"
40+
41+
- apiGroups:
42+
- networking.k8s.io
43+
resources:
44+
- networkpolicies
45+
verbs:
46+
- "*"
4047
---
4148
# Role for the operator to delete Role and RoleBindings
4249
# in the openshift-config namespace.

manifests/02-network-policy.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# We control the namespace, deny anything we do not explicitly allow
2+
apiVersion: networking.k8s.io/v1
3+
kind: NetworkPolicy
4+
metadata:
5+
name: ingress-operator-deny-all
6+
namespace: openshift-ingress-operator
7+
annotations:
8+
capability.openshift.io/name: Ingress
9+
include.release.openshift.io/self-managed-high-availability: "true"
10+
include.release.openshift.io/single-node-developer: "true"
11+
spec:
12+
podSelector: {}
13+
policyTypes:
14+
- Ingress
15+
- Egress
16+
---
17+
### Allow the operator needs to talk to the apiserver and dns,
18+
### but it also needs to be able to configure external DNS and the endpoints
19+
### are only known at run time. So it needs wildcard egress.
20+
### Allow access to the metrics ports on the operators
21+
apiVersion: networking.k8s.io/v1
22+
kind: NetworkPolicy
23+
metadata:
24+
name: ingress-operator-allow
25+
namespace: openshift-ingress-operator
26+
annotations:
27+
include.release.openshift.io/self-managed-high-availability: "true"
28+
include.release.openshift.io/single-node-developer: "true"
29+
spec:
30+
podSelector:
31+
matchLabels:
32+
name: ingress-operator
33+
policyTypes:
34+
- Egress
35+
- Ingress
36+
egress:
37+
- to:
38+
- ipBlock:
39+
cidr: 0.0.0.0/0
40+
ingress:
41+
- ports:
42+
- protocol: TCP
43+
port: 9393
File renamed without changes.
File renamed without changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Router Pods
2+
# Egress to api server and everything (routes set endpoints, so can be literally anything)
3+
# Ingress to http on port 80 and https on port 443 (TCP) and to metrics (1936)
4+
apiVersion: networking.k8s.io/v1
5+
kind: NetworkPolicy
6+
# name, namespace,labels and annotations are set at runtime
7+
spec:
8+
podSelector:
9+
# matchLabels are set at runtime
10+
matchLabels: {}
11+
ingress:
12+
- ports:
13+
- protocol: TCP
14+
port: 80
15+
- protocol: TCP
16+
port: 443
17+
- protocol: TCP
18+
port: 1936
19+
egress:
20+
- to:
21+
- ipBlock:
22+
cidr: 0.0.0.0/0
23+
policyTypes:
24+
- Ingress
25+
- Egress
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Default deny all policy for all pods in the namespace
2+
apiVersion: networking.k8s.io/v1
3+
kind: NetworkPolicy
4+
metadata:
5+
name: openshift-ingress-deny-all
6+
namespace: openshift-ingress
7+
spec:
8+
podSelector: {}
9+
policyTypes:
10+
- Ingress
11+
- Egress

pkg/manifests/manifests.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
appsv1 "k8s.io/api/apps/v1"
1515
corev1 "k8s.io/api/core/v1"
16+
networkingv1 "k8s.io/api/networking/v1"
1617
rbacv1 "k8s.io/api/rbac/v1"
1718
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1819

@@ -24,13 +25,15 @@ import (
2425
)
2526

2627
const (
27-
RouterNamespaceAsset = "assets/router/namespace.yaml"
28-
RouterServiceAccountAsset = "assets/router/service-account.yaml"
29-
RouterClusterRoleAsset = "assets/router/cluster-role.yaml"
30-
RouterClusterRoleBindingAsset = "assets/router/cluster-role-binding.yaml"
31-
RouterDeploymentAsset = "assets/router/deployment.yaml"
32-
RouterServiceInternalAsset = "assets/router/service-internal.yaml"
33-
RouterServiceCloudAsset = "assets/router/service-cloud.yaml"
28+
RouterNamespaceAsset = "assets/router/namespace.yaml"
29+
RouterServiceAccountAsset = "assets/router/service-account.yaml"
30+
RouterClusterRoleAsset = "assets/router/cluster-role.yaml"
31+
RouterClusterRoleBindingAsset = "assets/router/cluster-role-binding.yaml"
32+
RouterDeploymentAsset = "assets/router/deployment.yaml"
33+
RouterServiceInternalAsset = "assets/router/service-internal.yaml"
34+
RouterServiceCloudAsset = "assets/router/service-cloud.yaml"
35+
RouterNetworkPolicyDenyAllAsset = "assets/router/networkpolicy-deny-all.yaml"
36+
RouterNetworkPolicyAllowAsset = "assets/router/networkpolicy-allow.yaml"
3437

3538
MetricsClusterRoleAsset = "assets/router/metrics/cluster-role.yaml"
3639
MetricsClusterRoleBindingAsset = "assets/router/metrics/cluster-role-binding.yaml"
@@ -314,6 +317,22 @@ func GatewayAPIViewClusterRole() *rbacv1.ClusterRole {
314317
return clusterRole
315318
}
316319

320+
func RouterNetworkPolicyDenyAll() *networkingv1.NetworkPolicy {
321+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(RouterNetworkPolicyDenyAllAsset))
322+
if err != nil {
323+
panic(err)
324+
}
325+
return networkPolicy
326+
}
327+
328+
func RouterNetworkPolicyAllow() *networkingv1.NetworkPolicy {
329+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(RouterNetworkPolicyAllowAsset))
330+
if err != nil {
331+
panic(err)
332+
}
333+
return networkPolicy
334+
}
335+
317336
func NewServiceAccount(manifest io.Reader) (*corev1.ServiceAccount, error) {
318337
sa := corev1.ServiceAccount{}
319338
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&sa); err != nil {
@@ -404,6 +423,15 @@ func NewRoute(manifest io.Reader) (*routev1.Route, error) {
404423
return &o, nil
405424
}
406425

426+
func NewNetworkPolicy(manifest io.Reader) (*networkingv1.NetworkPolicy, error) {
427+
o := networkingv1.NetworkPolicy{}
428+
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&o); err != nil {
429+
return nil, err
430+
}
431+
432+
return &o, nil
433+
}
434+
407435
func NewCustomResourceDefinition(manifest io.Reader) (*apiextensionsv1.CustomResourceDefinition, error) {
408436
o := apiextensionsv1.CustomResourceDefinition{}
409437
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&o); err != nil {

pkg/operator/controller/ingress/controller.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
appsv1 "k8s.io/api/apps/v1"
2626
corev1 "k8s.io/api/core/v1"
27+
networkingv1 "k8s.io/api/networking/v1"
2728

2829
"k8s.io/client-go/tools/record"
2930

@@ -114,6 +115,9 @@ func New(mgr manager.Manager, config Config) (controller.Controller, error) {
114115
if err := c.Watch(source.Kind[client.Object](operatorCache, &corev1.Service{}, enqueueRequestForOwningIngressController(config.Namespace))); err != nil {
115116
return nil, err
116117
}
118+
if err := c.Watch(source.Kind[client.Object](operatorCache, &networkingv1.NetworkPolicy{}, enqueueRequestForOwningIngressController(config.Namespace))); err != nil {
119+
return nil, err
120+
}
117121
// Add watch for deleted pods specifically for ensuring ingress deletion.
118122
if err := c.Watch(source.Kind[client.Object](operatorCache, &corev1.Pod{}, enqueueRequestForOwningIngressController(config.Namespace), predicate.Funcs{
119123
CreateFunc: func(e event.CreateEvent) bool { return false },
@@ -1078,6 +1082,10 @@ func (r *reconciler) ensureIngressController(ci *operatorv1.IngressController, d
10781082
return fmt.Errorf("failed to ensure namespace: %v", err)
10791083
}
10801084

1085+
if _, _, err := r.ensureRouterNamespaceNetworkPolicy(ci); err != nil {
1086+
return fmt.Errorf("failed to ensure default namespacenetwork policy: %v", err)
1087+
}
1088+
10811089
if err := r.ensureRouterServiceAccount(); err != nil {
10821090
return fmt.Errorf("failed to ensure service account: %v", err)
10831091
}
@@ -1086,6 +1094,10 @@ func (r *reconciler) ensureIngressController(ci *operatorv1.IngressController, d
10861094
return fmt.Errorf("failed to ensure cluster role binding: %v", err)
10871095
}
10881096

1097+
if err := r.ensureRouterNetworkPolicy(ci); err != nil {
1098+
return fmt.Errorf("failed to ensure network policy: %v", err)
1099+
}
1100+
10891101
var errs []error
10901102
if _, _, err := r.ensureServiceCAConfigMap(); err != nil {
10911103
// Even if we were unable to create the configmap at this time,

0 commit comments

Comments
 (0)