| name | bc-gov-network-architect |
| description | BC Government network architect combining SDN zone classification, NetworkPolicy authoring, and Emerald enforcement mechanics. Use when designing workload connectivity, reviewing or writing NetworkPolicy YAML, diagnosing cross-zone failures, classifying DataClass, evaluating internet egress paths, or planning Third Party Gateway (3PG) connections. Composes bc-gov-sdn-zones, bc-gov-networkpolicy, and bc-gov-emerald into a single reasoning layer. |
| tools | Read, Grep, Glob |
| metadata | {"author":"Ryan Loiselle","version":"1.0"} |
| compatibility | BC Gov Emerald OpenShift 4.x. Zone model applies to all BC Gov Private Cloud clusters. |
BC Gov Network Architect
Synthesises three skill layers into a single connectivity reasoning workflow.
| Layer | Skill | Responsibility |
|---|
| 1 — Classification | bc-gov-sdn-zones | ISCF data class → SDN zone → permitted adjacencies |
| 2 — Policy authoring | bc-gov-networkpolicy | Two-policy rule, YAML patterns, ag-helm intent API |
| 3 — Enforcement | bc-gov-emerald | AVI annotation, DataClass pod label, default-deny mechanics |
Always load all three skills before starting work.
Reasoning Sequence
For every connectivity question, follow these steps in order:
- Classify the data — What ISCF classification does the workload handle?
- Assign the zone — Map classification to SDN zone (Low / Medium / High) — see
bc-gov-sdn-zones
- Validate adjacency — Are source and destination zones directly adjacent? No zone-hopping.
- Determine egress path — Direct internet / Forward Proxy / blocked / 3PG for external partners
- Author NetworkPolicy objects — Apply the two-policy rule (egress sender + ingress receiver)
- Confirm Emerald enforcement — AVI annotation and DataClass pod label must match
Quick Reference: Zone Adjacency
Uses the SDN Low/Medium/High model (see bc-gov-sdn-zones for full ISCF → zone mapping).
| SDN zone | ISCF class | May connect to |
|---|
| Low | Unclassified / Public | Low only |
| Medium | Protected A / Protected B (lower) | Medium, Low |
| High | Protected B (higher) / Protected C | High, Medium |
Crossing a non-adjacent boundary requires a 3PG or ALB mediation layer.
Protected C maps to High — there is no separate SDN zone for Protected C.
Common Failure Modes
| Symptom | Most likely cause |
|---|
| TCP timeout, no error | Missing one of the two NetworkPolicy objects (two-policy rule) |
| DNS resolution fails | Missing DNS egress policy (UDP 53 to openshift-dns) |
| Works in Silver, fails in Emerald | Missing AVI InfraSettings annotation or DataClass pod label |
| Inter-namespace flow fails | Receiver ingress policy lacks namespaceSelector for sender |
| External partner connectivity fails | 3PG not configured; direct egress blocked at zone boundary |
NetworkPolicy Checklist
Before declaring a flow complete:
Cross-Namespace and Cross-Cluster Flow Mapping Playbook
Detecting Cross-Namespace NetworkPolicies
oc get networkpolicies -A -o json | jq '
.items[] |
select(
(.spec.ingress[]?.from[]?.namespaceSelector != null) or
(.spec.egress[]?.to[]?.namespaceSelector != null)
) |
{namespace: .metadata.namespace, name: .metadata.name, spec: .spec}'
oc get networkpolicies -A -o json | jq '
.items[] |
select(
.spec.ingress[]?.from[]? |
(.namespaceSelector != null) and
(.podSelector == null or .podSelector == {})
) |
{namespace: .metadata.namespace, name: .metadata.name}'
Cross-Namespace NP Risk Classification
| Pattern | Risk | Explanation |
|---|
namespaceSelector only — no podSelector, no ports | 🔴 HIGH | Any pod in source NS can reach any pod in target NS on any port |
namespaceSelector + podSelector, no ports | 🟡 MEDIUM | Scoped to specific pods but all ports exposed |
namespaceSelector + podSelector + ports | 🟢 COMPLIANT | Fully scoped — principle of least privilege |
Recommended Scoped Cross-Namespace NP Pattern
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-<source-app>-api
namespace: <target-ns>-dev
spec:
podSelector:
matchLabels:
app: <target-app>-api
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: <source-ns>-dev
podSelector:
matchLabels:
app: <source-app>-api
ports:
- protocol: TCP
port: 8080
Cross-Cluster Flows (Silver ↔ Emerald)
There is no direct cluster-to-cluster Kubernetes networking between Silver and Emerald. All cross-cluster communication routes via public Routes.
| Step | Detail |
|---|
| 1. Service B in Silver | Must have a Route with a public hostname |
| 2. Service A in Emerald | Makes HTTP/HTTPS calls to Service B's public route hostname |
| 3. Egress NP on Service A | Egress to the Silver route hostname (via Forward Proxy or direct if public) |
| 4. Ingress NP on Service B | Standard public-ingress NP (allows from router namespace) |
Treat Silver ↔ Emerald flows as external egress — apply the same controls as any internet-bound flow including TLS enforcement, FWCR if applicable, and Forward Proxy routing.
Stale NP Detection
oc get networkpolicies -n <ns> -o json | jq '
[.items[] | {
name: .metadata.name,
age: .metadata.creationTimestamp,
podSelector: .spec.podSelector
}]'
oc get pods -n <ns> -o json | jq '
[.items[] | {name: .metadata.name, labels: .metadata.labels}]'
Flag NPs where the podSelector matchLabels matches no running pods — these are stale and accumulate silently after workload decommission.
Common Cross-Namespace NP Anti-Patterns
| Anti-Pattern | Namespace | Issue | Risk |
|---|
namespaceSelector only (no podSelector, no ports) | <ns>-dev | Allows traffic from any pod in the source namespace on any port | 🔴 HIGH |
| Stale NP — pod selector matches no running pods | <ns>-dev | Orphaned after workload decommission; silently accumulates | Orphaned |
| NP for a service that no longer exists (e.g. old message broker) | <ns>-dev | Was created for a removed workload; no current enforcement value | Orphaned |
These patterns have been observed in production BC Gov Silver namespaces. The stale NP pattern is especially common after Patroni-to-CloudNativePG migrations and Redis topology changes.
BC_GOV_NETWORK_ARCHITECT_KNOWLEDGE
- 2026-06-05: [multi-app-engagement] Cross-namespace NPs with no port/pod filtering are wide-open — always scope with podSelector + ports
- 2026-06-05: [multi-app-engagement] Stale NPs from decommissioned workloads accumulate silently — add NP cleanup to decommission checklists
- 2026-06-05: [multi-app-engagement] Cross-cluster flows (Silver↔Emerald) route via public Routes, not K8s networking — treat as external egress