From 0bbbb6f5248330985421e7864d7243dbee35d6e7 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Thu, 14 Aug 2025 13:57:38 -0600 Subject: [PATCH 1/4] DNM OADP-6074: add network policies for OADP Signed-off-by: Wesley Hayutin --- config/networkpolicy/kustomization.yaml | 9 + config/networkpolicy/networkpolicy.yaml | 37 ++++ docs/NetworkPolicies/README.md | 208 +++++++++++++++++++++++ docs/NetworkPolicies/network_policy.yaml | 33 ++++ 4 files changed, 287 insertions(+) create mode 100644 config/networkpolicy/kustomization.yaml create mode 100644 config/networkpolicy/networkpolicy.yaml create mode 100644 docs/NetworkPolicies/README.md create mode 100644 docs/NetworkPolicies/network_policy.yaml diff --git a/config/networkpolicy/kustomization.yaml b/config/networkpolicy/kustomization.yaml new file mode 100644 index 0000000000..4142019753 --- /dev/null +++ b/config/networkpolicy/kustomization.yaml @@ -0,0 +1,9 @@ +resources: +- networkpolicy.yaml + +namespace: openshift-adp + +# Add common labels to all NetworkPolicy resources +commonLabels: + app.kubernetes.io/name: oadp-operator + app.kubernetes.io/part-of: oadp-operator diff --git a/config/networkpolicy/networkpolicy.yaml b/config/networkpolicy/networkpolicy.yaml new file mode 100644 index 0000000000..119db6eac8 --- /dev/null +++ b/config/networkpolicy/networkpolicy.yaml @@ -0,0 +1,37 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: oadp-default-deny-labelled + namespace: system + labels: + app.kubernetes.io/name: oadp-networkpolicy + app.kubernetes.io/component: network-security + app.kubernetes.io/part-of: oadp-operator + app.kubernetes.io/managed-by: olm +spec: + podSelector: + matchLabels: + app.kubernetes.io/managed-by: "oadp-operator" + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: {} + egress: + - to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - protocol: TCP + port: 443 + - to: + - namespaceSelector: + matchLabels: + # This label is standard on the openshift-dns namespace + kubernetes.io/metadata.name: openshift-dns + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 diff --git a/docs/NetworkPolicies/README.md b/docs/NetworkPolicies/README.md new file mode 100644 index 0000000000..53613876c5 --- /dev/null +++ b/docs/NetworkPolicies/README.md @@ -0,0 +1,208 @@ +# NetworkPolicies for OADP (OpenShift API for Data Protection) + +This directory contains NetworkPolicy configurations for securing OADP components in your Kubernetes cluster. NetworkPolicies provide a way to control network traffic flow between pods and other network endpoints at the application layer. + +## What are NetworkPolicies? + +NetworkPolicies are Kubernetes resources that define how groups of pods are allowed to communicate with each other and other network endpoints. They work at the IP address or port level (OSI layer 3 or 4) and provide a way to implement network segmentation and micro-segmentation within your cluster. + +As described in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/), NetworkPolicies use labels to select pods and define rules that specify what traffic is allowed to and from those pods. + +## Prerequisites + +- Your cluster must be using a Container Network Interface (CNI) plugin that supports NetworkPolicies (such as Calico, Cilium, Weave Net, or others) +- NetworkPolicies are namespaced resources and only affect pods in the same namespace + +## OADP NetworkPolicy Configuration + +The `network_policy.yaml` file in this directory defines a NetworkPolicy specifically designed for OADP components. Here's what it does: + +### Policy Overview + +```yaml +name: default-deny-labelled +``` + +This policy implements a **default-deny approach** for pods managed by the OADP operator, meaning that by default, all network traffic is blocked except for explicitly allowed connections. + +### Pod Selection + +```yaml +podSelector: + matchLabels: + app.kubernetes.io/managed-by: "oadp-operator" +``` + +The policy applies to all pods that have the label `app.kubernetes.io/managed-by: "oadp-operator"`. This typically includes: +- Velero pods +- OADP operator pods +- Other OADP-related components + +### Traffic Rules + +#### Ingress Rules (Incoming Traffic) + +```yaml +ingress: +- from: + - podSelector: {} +``` + +**What this allows:** +- Allows incoming traffic from **any pod within the same namespace** +- This enables inter-pod communication for OADP components that need to communicate with each other + +#### Egress Rules (Outgoing Traffic) + +The policy defines two egress rules: + +**1. HTTPS Internet Access** +```yaml +- to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - protocol: TCP + port: 443 +``` + +**What this allows:** +- Outbound HTTPS traffic (port 443) to any IP address on the internet +- Essential for OADP components to communicate with cloud storage providers (AWS S3, Azure Blob, Google Cloud Storage, etc.) +- Allows downloading container images and accessing external APIs + +**2. DNS Resolution** +```yaml +- to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-dns + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 +``` + +**What this allows:** +- DNS queries to the OpenShift DNS service (both UDP and TCP on port 53) +- Essential for resolving domain names for cloud storage endpoints and other external services +- Uses the standard OpenShift DNS namespace label + +## Why These Rules Matter for OADP + +### Security Benefits + +1. **Principle of Least Privilege**: Only allows the minimum network access required for OADP to function +2. **Attack Surface Reduction**: Limits potential network-based attacks on OADP components +3. **Compliance**: Helps meet security compliance requirements for network segmentation + +### OADP-Specific Requirements + +OADP components need specific network access to function properly: + +- **Cloud Storage Access**: HTTPS (443) for communicating with cloud storage APIs +- **DNS Resolution**: Required to resolve cloud storage endpoint names +- **Inter-Component Communication**: OADP pods may need to communicate with each other within the namespace + +## Applying the NetworkPolicy + +To apply this NetworkPolicy to your cluster: + +```bash +kubectl apply -f network_policy.yaml -n +``` + +Replace `` with the namespace where OADP is installed (typically `openshift-adp`). + +## Monitoring and Troubleshooting + +### Verifying the Policy + +Check if the NetworkPolicy is applied: +```bash +kubectl get networkpolicy -n +kubectl describe networkpolicy default-deny-labelled -n +``` + +### Common Issues + +1. **DNS Resolution Failures**: If OADP components can't resolve domain names, verify the DNS egress rule +2. **Cloud Storage Connection Issues**: Ensure the HTTPS egress rule allows traffic to your storage provider +3. **Inter-Pod Communication Problems**: Check that pods have the correct labels and the ingress rule is configured properly + +### Debugging Network Connectivity + +If you suspect NetworkPolicy issues: + +1. Check pod labels: + ```bash + kubectl get pods -n --show-labels + ``` + +2. Test connectivity from within a pod: + ```bash + kubectl exec -it -n -- nslookup + kubectl exec -it -n -- curl -I https:// + ``` + +## Customizing the Policy + +You may need to modify the NetworkPolicy based on your specific requirements: + +### Adding Additional Egress Rules + +If your OADP setup requires access to additional services, add more egress rules: + +```yaml +egress: +- to: + - ipBlock: + cidr: 10.0.0.0/8 # Private network range + ports: + - protocol: TCP + port: 9000 # MinIO or other S3-compatible storage +``` + +### Restricting Cloud Access + +To limit access to specific cloud provider IP ranges instead of allowing all internet traffic: + +```yaml +egress: +- to: + - ipBlock: + cidr: 52.219.0.0/16 # AWS S3 IP range example + ports: + - protocol: TCP + port: 443 +``` + +## Important Considerations + +### Pod Lifecycle + +As noted in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/), when a NetworkPolicy is first applied, there may be a brief period where pods are started without full network isolation. OADP pods should be resilient to temporary network connectivity issues during startup. + +### CNI Plugin Compatibility + +Ensure your CNI plugin fully supports NetworkPolicies. Some features (like `endPort` ranges) may not be supported by all plugins. + +### Default Behavior + +Remember that NetworkPolicies implement a "default deny" model. If no NetworkPolicy selects a pod, all traffic is allowed. Once a pod is selected by any NetworkPolicy, only traffic explicitly allowed by those policies will be permitted. + +## Additional Resources + +- [Kubernetes NetworkPolicy Documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) +- [OADP Documentation](https://docs.openshift.com/container-platform/latest/backup_and_restore/application_backup_and_restore/oadp-features-plugins.html) +- [OpenShift Network Security](https://docs.openshift.com/container-platform/latest/networking/network_policy/about-network-policy.html) + +## Contributing + +When modifying NetworkPolicies for OADP: + +1. Test thoroughly in a development environment +2. Verify that all OADP functionality continues to work +3. Document any changes and the reasoning behind them +4. Consider the security implications of any new rules diff --git a/docs/NetworkPolicies/network_policy.yaml b/docs/NetworkPolicies/network_policy.yaml new file mode 100644 index 0000000000..61c46f1923 --- /dev/null +++ b/docs/NetworkPolicies/network_policy.yaml @@ -0,0 +1,33 @@ +# tested w/ an oadp datamover backup and restore w/ sample app 3cscsvol + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: default-deny-labelled +spec: + podSelector: + matchLabels: + app.kubernetes.io/managed-by: "oadp-operator" + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: {} + egress: + - to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - protocol: TCP + port: 443 + - to: + - namespaceSelector: + matchLabels: + # This label is standard on the openshift-dns namespace + kubernetes.io/metadata.name: openshift-dns + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 \ No newline at end of file From 846e6ea3560ec814667e8a75963740fcb1f9a3b4 Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 3 Dec 2025 11:45:46 -0700 Subject: [PATCH 2/4] first pass at hardening, install is manual --- config/networkpolicy/networkpolicy.yaml | 23 +++++++++++++- docs/NetworkPolicies/README.md | 39 ++++++++++++++++++++++-- docs/NetworkPolicies/network_policy.yaml | 33 -------------------- 3 files changed, 59 insertions(+), 36 deletions(-) delete mode 100644 docs/NetworkPolicies/network_policy.yaml diff --git a/config/networkpolicy/networkpolicy.yaml b/config/networkpolicy/networkpolicy.yaml index 119db6eac8..04d2ec4b64 100644 --- a/config/networkpolicy/networkpolicy.yaml +++ b/config/networkpolicy/networkpolicy.yaml @@ -2,7 +2,6 @@ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: oadp-default-deny-labelled - namespace: system labels: app.kubernetes.io/name: oadp-networkpolicy app.kubernetes.io/component: network-security @@ -18,6 +17,21 @@ spec: ingress: - from: - podSelector: {} + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-user-workload-monitoring + ports: + - protocol: TCP + port: 8085 + - protocol: TCP + port: 8443 + - ports: + - protocol: TCP + port: 9443 egress: - to: - ipBlock: @@ -35,3 +49,10 @@ spec: port: 53 - protocol: TCP port: 53 + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: default + ports: + - protocol: TCP + port: 443 diff --git a/docs/NetworkPolicies/README.md b/docs/NetworkPolicies/README.md index 53613876c5..4bbd9e191c 100644 --- a/docs/NetworkPolicies/README.md +++ b/docs/NetworkPolicies/README.md @@ -46,11 +46,29 @@ The policy applies to all pods that have the label `app.kubernetes.io/managed-by ingress: - from: - podSelector: {} +# Allow OpenShift Monitoring +- from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-user-workload-monitoring + ports: + - protocol: TCP + port: 8085 # Velero Metrics + - protocol: TCP + port: 8443 # Controller Metrics +# Allow API Server Webhooks +- ports: + - protocol: TCP + port: 9443 # Webhook ``` **What this allows:** -- Allows incoming traffic from **any pod within the same namespace** -- This enables inter-pod communication for OADP components that need to communicate with each other +- **Internal Communication**: Allows incoming traffic from **any pod within the same namespace**. +- **Monitoring**: Allows OpenShift Monitoring stack to scrape metrics from OADP components (ports 8085, 8443). +- **Webhooks**: Allows the Kubernetes API server to communicate with OADP validation/mutation webhooks (port 9443). #### Egress Rules (Outgoing Traffic) @@ -89,6 +107,21 @@ The policy defines two egress rules: - Essential for resolving domain names for cloud storage endpoints and other external services - Uses the standard OpenShift DNS namespace label +**3. Kubernetes API Access** +```yaml +- to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: default + ports: + - protocol: TCP + port: 443 +``` + +**What this allows:** +- Traffic to the Kubernetes API server (service `kubernetes` in `default` namespace). +- Essential for the OADP operator to manage resources (DPAs, Backups, Restores). + ## Why These Rules Matter for OADP ### Security Benefits @@ -104,6 +137,8 @@ OADP components need specific network access to function properly: - **Cloud Storage Access**: HTTPS (443) for communicating with cloud storage APIs - **DNS Resolution**: Required to resolve cloud storage endpoint names - **Inter-Component Communication**: OADP pods may need to communicate with each other within the namespace +- **Monitoring**: The OpenShift Monitoring stack needs to reach OADP metrics endpoints +- **Webhooks**: The Kubernetes API server needs to reach the OADP operator for CR validation ## Applying the NetworkPolicy diff --git a/docs/NetworkPolicies/network_policy.yaml b/docs/NetworkPolicies/network_policy.yaml deleted file mode 100644 index 61c46f1923..0000000000 --- a/docs/NetworkPolicies/network_policy.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# tested w/ an oadp datamover backup and restore w/ sample app 3cscsvol - -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default-deny-labelled -spec: - podSelector: - matchLabels: - app.kubernetes.io/managed-by: "oadp-operator" - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: {} - egress: - - to: - - ipBlock: - cidr: 0.0.0.0/0 - ports: - - protocol: TCP - port: 443 - - to: - - namespaceSelector: - matchLabels: - # This label is standard on the openshift-dns namespace - kubernetes.io/metadata.name: openshift-dns - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 \ No newline at end of file From 08ca8c0eb8466ba53c662b75ea2b7215887eb6da Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 3 Dec 2025 13:16:58 -0700 Subject: [PATCH 3/4] bsl comes up now --- config/networkpolicy/networkpolicy.yaml | 21 ++++++++++++ docs/NetworkPolicies/README.md | 44 ++++++++++++++++++------- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/config/networkpolicy/networkpolicy.yaml b/config/networkpolicy/networkpolicy.yaml index 04d2ec4b64..2def77dd2e 100644 --- a/config/networkpolicy/networkpolicy.yaml +++ b/config/networkpolicy/networkpolicy.yaml @@ -39,6 +39,8 @@ spec: ports: - protocol: TCP port: 443 + - protocol: TCP + port: 6443 - to: - namespaceSelector: matchLabels: @@ -49,6 +51,7 @@ spec: port: 53 - protocol: TCP port: 53 + # Explicitly allow access to Kubernetes API Server - to: - namespaceSelector: matchLabels: @@ -56,3 +59,21 @@ spec: ports: - protocol: TCP port: 443 + # Explicitly allow access to OpenShift API Server + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-apiserver + ports: + - protocol: TCP + port: 443 + # Explicitly allow access to Kubernetes API Server (OpenShift Namespace) + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-kube-apiserver + ports: + - protocol: TCP + port: 443 + - protocol: TCP + port: 6443 diff --git a/docs/NetworkPolicies/README.md b/docs/NetworkPolicies/README.md index 4bbd9e191c..fa776c3ae7 100644 --- a/docs/NetworkPolicies/README.md +++ b/docs/NetworkPolicies/README.md @@ -72,9 +72,9 @@ ingress: #### Egress Rules (Outgoing Traffic) -The policy defines two egress rules: +The policy defines multiple egress rules to ensure comprehensive connectivity: -**1. HTTPS Internet Access** +**1. General Network Access** ```yaml - to: - ipBlock: @@ -82,12 +82,14 @@ The policy defines two egress rules: ports: - protocol: TCP port: 443 + - protocol: TCP + port: 6443 ``` **What this allows:** -- Outbound HTTPS traffic (port 443) to any IP address on the internet -- Essential for OADP components to communicate with cloud storage providers (AWS S3, Azure Blob, Google Cloud Storage, etc.) -- Allows downloading container images and accessing external APIs +- Outbound HTTPS traffic (port 443) to any IP address. +- Outbound traffic to Kubernetes API servers (port 6443). +- This covers cloud storage providers, external APIs, container registries, and external/host-networked API servers. **2. DNS Resolution** ```yaml @@ -103,12 +105,11 @@ The policy defines two egress rules: ``` **What this allows:** -- DNS queries to the OpenShift DNS service (both UDP and TCP on port 53) -- Essential for resolving domain names for cloud storage endpoints and other external services -- Uses the standard OpenShift DNS namespace label +- DNS queries to the OpenShift DNS service. -**3. Kubernetes API Access** +**3. Kubernetes API Access (Explicit)** ```yaml +# Allow access to Kubernetes API Server - to: - namespaceSelector: matchLabels: @@ -116,11 +117,32 @@ The policy defines two egress rules: ports: - protocol: TCP port: 443 + +# Allow access to OpenShift API Server +- to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-apiserver + ports: + - protocol: TCP + port: 443 + +# Allow access to Kubernetes API Server (OpenShift Namespace) +- to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-kube-apiserver + ports: + - protocol: TCP + port: 443 + - protocol: TCP + port: 6443 ``` **What this allows:** -- Traffic to the Kubernetes API server (service `kubernetes` in `default` namespace). -- Essential for the OADP operator to manage resources (DPAs, Backups, Restores). +- Explicitly allows traffic to the Kubernetes API server (in `default` and `openshift-kube-apiserver` namespaces) and OpenShift API server (in `openshift-apiserver` namespace). +- Ensures internal Service Network traffic is permitted even if broader rules don't apply to cluster services in some CNI configurations. +- Covers both port 443 (Service) and 6443 (Pod/Endpoint) for the API server. ## Why These Rules Matter for OADP From deababf328adfd47622c7d4e99c23439c42e4fbe Mon Sep 17 00:00:00 2001 From: Wesley Hayutin Date: Wed, 3 Dec 2025 13:38:18 -0700 Subject: [PATCH 4/4] fix dns issues --- config/networkpolicy/networkpolicy.yaml | 13 ++++++++++++- docs/NetworkPolicies/README.md | 10 +++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/config/networkpolicy/networkpolicy.yaml b/config/networkpolicy/networkpolicy.yaml index 2def77dd2e..52cd9d2864 100644 --- a/config/networkpolicy/networkpolicy.yaml +++ b/config/networkpolicy/networkpolicy.yaml @@ -8,6 +8,10 @@ metadata: app.kubernetes.io/part-of: oadp-operator app.kubernetes.io/managed-by: olm spec: + # Limited Default Deny Policy: + # This policy selects pods managed by oadp-operator and blocks all traffic by default, + # except for the specific ingress/egress rules defined below. + # It allows OADP to coexist with other workloads in the same namespace. podSelector: matchLabels: app.kubernetes.io/managed-by: "oadp-operator" @@ -41,16 +45,23 @@ spec: port: 443 - protocol: TCP port: 6443 + # Explicitly allow access to DNS - to: - namespaceSelector: matchLabels: - # This label is standard on the openshift-dns namespace kubernetes.io/metadata.name: openshift-dns + podSelector: + matchLabels: + dns.operator.openshift.io/daemonset-dns: default ports: - protocol: UDP port: 53 - protocol: TCP port: 53 + - protocol: UDP + port: 5353 + - protocol: TCP + port: 5353 # Explicitly allow access to Kubernetes API Server - to: - namespaceSelector: diff --git a/docs/NetworkPolicies/README.md b/docs/NetworkPolicies/README.md index fa776c3ae7..947320b67b 100644 --- a/docs/NetworkPolicies/README.md +++ b/docs/NetworkPolicies/README.md @@ -97,15 +97,23 @@ The policy defines multiple egress rules to ensure comprehensive connectivity: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-dns + podSelector: + matchLabels: + dns.operator.openshift.io/daemonset-dns: default ports: - protocol: UDP port: 53 - protocol: TCP port: 53 + - protocol: UDP + port: 5353 + - protocol: TCP + port: 5353 ``` **What this allows:** -- DNS queries to the OpenShift DNS service. +- DNS queries to the OpenShift DNS service (ports 53 and 5353). +- Uses specific selectors for the `openshift-dns` namespace and `dns-default` pods. **3. Kubernetes API Access (Explicit)** ```yaml