Skip to content

Commit 71e5e0a

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 71e5e0a

23 files changed

+891
-21
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-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

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.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Router Pods
2+
# No egress
3+
# Ingress to http on port 8888 and https on port 8443 (TCP)
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: 8888
15+
- protocol: TCP
16+
port: 8443
17+
policyTypes:
18+
- Ingress
19+
- 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-canary-deny-all
6+
namespace: openshift-ingress-canary
7+
spec:
8+
podSelector: {}
9+
policyTypes:
10+
- Ingress
11+
- Egress
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Istio Pods for Gateway API
2+
# Egress to api server and everything (routes set endpoints, so can be literally anything)
3+
# Ingress need to be wildcarded as well since the ports are configurable
4+
apiVersion: networking.k8s.io/v1
5+
kind: NetworkPolicy
6+
metadata:
7+
name: gateway-api-allow
8+
namespace: openshift-ingress
9+
spec:
10+
podSelector:
11+
matchLabels:
12+
istio.io/rev: "openshift-gateway"
13+
ingress:
14+
- from:
15+
- ipBlock:
16+
cidr: 0.0.0.0/0
17+
egress:
18+
- to:
19+
- ipBlock:
20+
cidr: 0.0.0.0/0
21+
policyTypes:
22+
- Ingress
23+
- Egress
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: 74 additions & 19 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,31 +25,36 @@ 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"
3740
MetricsRoleAsset = "assets/router/metrics/role.yaml"
3841
MetricsRoleBindingAsset = "assets/router/metrics/role-binding.yaml"
3942

40-
CanaryNamespaceAsset = "assets/canary/namespace.yaml"
41-
CanaryDaemonSetAsset = "assets/canary/daemonset.yaml"
42-
CanaryServiceAsset = "assets/canary/service.yaml"
43-
CanaryRouteAsset = "assets/canary/route.yaml"
44-
45-
GatewayClassCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml"
46-
GatewayCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml"
47-
GRPCRouteCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_grpcroutes.yaml"
48-
HTTPRouteCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml"
49-
ReferenceGrantCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml"
50-
GatewayAPIAdminClusterRoleAsset = "assets/gateway-api/aggregated-cluster-roles/admin-cluster-role.yaml"
51-
GatewayAPIViewClusterRoleAsset = "assets/gateway-api/aggregated-cluster-roles/view-cluster-role.yaml"
43+
CanaryNamespaceAsset = "assets/canary/namespace.yaml"
44+
CanaryDaemonSetAsset = "assets/canary/daemonset.yaml"
45+
CanaryServiceAsset = "assets/canary/service.yaml"
46+
CanaryRouteAsset = "assets/canary/route.yaml"
47+
CanaryNetworkPolicyDenyAllAsset = "assets/canary/networkpolicy-deny-all.yaml"
48+
CanaryNetworkPolicyAllowAsset = "assets/canary/networkpolicy-allow.yaml"
49+
50+
GatewayClassCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml"
51+
GatewayCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml"
52+
GRPCRouteCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_grpcroutes.yaml"
53+
HTTPRouteCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml"
54+
ReferenceGrantCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml"
55+
GatewayAPIAdminClusterRoleAsset = "assets/gateway-api/aggregated-cluster-roles/admin-cluster-role.yaml"
56+
GatewayAPIViewClusterRoleAsset = "assets/gateway-api/aggregated-cluster-roles/view-cluster-role.yaml"
57+
GatewayAPIAllowNetworkPolicyAsset = "assets/gateway-api/gateway-networkpolicy-allow.yaml"
5258

5359
// Annotation used to inform the certificate generation service to
5460
// generate a cluster-signed certificate and populate the secret.
@@ -258,6 +264,22 @@ func CanaryRoute() *routev1.Route {
258264
return route
259265
}
260266

267+
func CanaryNetworkPolicyDenyAll() *networkingv1.NetworkPolicy {
268+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(CanaryNetworkPolicyDenyAllAsset))
269+
if err != nil {
270+
panic(err)
271+
}
272+
return networkPolicy
273+
}
274+
275+
func CanaryNetworkPolicyAllow() *networkingv1.NetworkPolicy {
276+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(CanaryNetworkPolicyAllowAsset))
277+
if err != nil {
278+
panic(err)
279+
}
280+
return networkPolicy
281+
}
282+
261283
func GatewayClassCRD() *apiextensionsv1.CustomResourceDefinition {
262284
crd, err := NewCustomResourceDefinition(MustAssetReader(GatewayClassCRDAsset))
263285
if err != nil {
@@ -314,6 +336,30 @@ func GatewayAPIViewClusterRole() *rbacv1.ClusterRole {
314336
return clusterRole
315337
}
316338

339+
func GatewayAPIAllowNetworkPolicy() *networkingv1.NetworkPolicy {
340+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(GatewayAPIAllowNetworkPolicyAsset))
341+
if err != nil {
342+
panic(err)
343+
}
344+
return networkPolicy
345+
}
346+
347+
func RouterNetworkPolicyDenyAll() *networkingv1.NetworkPolicy {
348+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(RouterNetworkPolicyDenyAllAsset))
349+
if err != nil {
350+
panic(err)
351+
}
352+
return networkPolicy
353+
}
354+
355+
func RouterNetworkPolicyAllow() *networkingv1.NetworkPolicy {
356+
networkPolicy, err := NewNetworkPolicy(MustAssetReader(RouterNetworkPolicyAllowAsset))
357+
if err != nil {
358+
panic(err)
359+
}
360+
return networkPolicy
361+
}
362+
317363
func NewServiceAccount(manifest io.Reader) (*corev1.ServiceAccount, error) {
318364
sa := corev1.ServiceAccount{}
319365
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&sa); err != nil {
@@ -404,6 +450,15 @@ func NewRoute(manifest io.Reader) (*routev1.Route, error) {
404450
return &o, nil
405451
}
406452

453+
func NewNetworkPolicy(manifest io.Reader) (*networkingv1.NetworkPolicy, error) {
454+
o := networkingv1.NetworkPolicy{}
455+
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&o); err != nil {
456+
return nil, err
457+
}
458+
459+
return &o, nil
460+
}
461+
407462
func NewCustomResourceDefinition(manifest io.Reader) (*apiextensionsv1.CustomResourceDefinition, error) {
408463
o := apiextensionsv1.CustomResourceDefinition{}
409464
if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&o); err != nil {

pkg/manifests/manifests_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ func TestManifests(t *testing.T) {
3535
RouterClusterRole()
3636
RouterClusterRoleBinding()
3737
RouterStatsSecret(ci)
38-
38+
RouterNetworkPolicyDenyAll()
39+
RouterNetworkPolicyAllow()
3940
MetricsClusterRole()
4041
MetricsClusterRoleBinding()
4142
MetricsRole()
@@ -51,6 +52,14 @@ func TestManifests(t *testing.T) {
5152
GRPCRouteCRD()
5253
HTTPRouteCRD()
5354
ReferenceGrantCRD()
55+
GatewayAPIAllowNetworkPolicy()
56+
57+
CanaryNamespace()
58+
CanaryDaemonSet()
59+
CanaryService()
60+
CanaryRoute()
61+
CanaryNetworkPolicyDenyAll()
62+
CanaryNetworkPolicyAllow()
5463

5564
adminOnlyVerbs := []string{"create", "update", "patch", "delete", "deletecollection"}
5665
GatewayAPIAdminClusterRole()

0 commit comments

Comments
 (0)