Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#28: Initial integration with network policies #69

Merged
merged 13 commits into from
Jun 9, 2024
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,40 @@ wormhole.glothriel.github.com/ports=http
wormhole.glothriel.github.com/ports=80,443
```

### Enable creation of network policies

You can secure the services exposed on another end by configuring network policies. Network policies are currently implemented on a per-peer basis, so for example a client may have them enabled and the server may not, or only a subset of clients may have them enabled.

You can enable network policies by setting `--set networkPolicies.enabled=true` helm chart value. Network policies of course in order to work require the cluster that supports them.

When wormhole is deployed with network policies support, each time it exposes a remote service it also creates a matching network policy. The network policy is created in the same namespace as the service and allows filtering of the traffic from other workloads in the cluster to the remote service.

```
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
...
spec:
ingress:
- from:
- namespaceSelector: {}
podSelector:
matchLabels:
wormhole.glothriel.github.com/network-policy-consumes-app: <<APP-NAME>>
ports:
- port: 25001
protocol: TCP
podSelector:
matchLabels:
application: wormhole-client-dev1
policyTypes:
- Ingress
```

Such policies allow communication from any pod in any namespace, providing, that the pod that tries to communicate has a label `wormhole.glothriel.github.com/network-policy-consumes-app` with the value of the name of the service that is exposed. The app name (unless override by `wormhole.glothriel.github.com/name=my-custom-name`) is `<service-namespace-name>-<service-name>` (for example `default-nginx`) of the service exposed from remote cluster.

Effectively this means, that the permission to communicate is granted per application, not per peer. Having permission to communicate with app having given name, allows the pod to communicate with all the apps with given name, no matter the peer the app is exposed from. This is especially important in the context of the server, as it may have multiple clients, all exposing the same app.

## Local development

### Development environment
Expand Down Expand Up @@ -133,3 +167,10 @@ cd tests && python setup.py develop && cd -

pytest tests
```

If you are re-running the tests multiple times, you may want to reuse the K3d cluster, you can do this by setting the `REUSE_CLUSTER` environment variable to a truthy value. It will then abstain from removing the cluster after the tests are done and reuse it for the next run.

```
export REUSE_CLUSTER=1
pytest tests
```
2 changes: 2 additions & 0 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ for server in servers:
"docker.image=wormhole-controller",
"docker.wgImage=wormhole-wireguard",
"docker.nginxImage=wormhole-nginx",
"networkPolicies.enabled=true",
"docker.registry=",
"devMode.enabled=true",
]))
Expand All @@ -70,6 +71,7 @@ for client in clients:
"docker.image=wormhole-controller",
"docker.wgImage=wormhole-wireguard",
"docker.nginxImage=wormhole-nginx",
"networkPolicies.enabled=true",
"docker.registry=",
"devMode.enabled=true",
]))
Expand Down
3 changes: 3 additions & 0 deletions kubernetes/helm/templates/client-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ spec:
- --debug
{{- end }}
- client
{{- if .Values.networkPolicies.enabled }}
- --network-policies
{{- end }}
- --name
- {{ .Values.client.name | required "Please set client.name" }}
- --kubernetes
Expand Down
22 changes: 22 additions & 0 deletions kubernetes/helm/templates/client-networkpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if and .Values.client.enabled .Values.networkPolicies.enabled }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
application: {{ template "name-client" . }}
name: {{ template "name-client" . }}
namespace: {{ $.Release.Namespace }}
spec:
ingress:
- ports:
# metrics
- port: 8090
protocol: TCP
podSelector:
matchLabels:
application: {{ template "name-client" . }}
policyTypes:
- Ingress

{{ end }}
11 changes: 11 additions & 0 deletions kubernetes/helm/templates/client-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ metadata:
labels:
application: {{ template "name-client" . }}
rules:
# svcs
- apiGroups:
- ""
resources:
Expand All @@ -58,6 +59,16 @@ rules:
- list
- delete
- watch
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- get
- create
- update
- list
- delete
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
3 changes: 3 additions & 0 deletions kubernetes/helm/templates/server-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ spec:
- --debug
{{- end }}
- server
{{- if .Values.networkPolicies.enabled }}
- --network-policies
{{- end }}
- --name
- {{ .Values.server.name }}
- --kubernetes
Expand Down
28 changes: 28 additions & 0 deletions kubernetes/helm/templates/server-networkpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- if and .Values.server.enabled .Values.networkPolicies.enabled }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
application: {{ template "name-server" . }}
name: {{ template "name-server" . }}
namespace: {{ $.Release.Namespace }}
spec:
ingress:
- ports:
# metrics
- port: 8090
protocol: TCP
# pairing
- port: 8080
protocol: TCP
# vpn
- port: 51820
protocol: UDP
podSelector:
matchLabels:
application: {{ template "name-server" . }}
policyTypes:
- Ingress

{{ end }}
10 changes: 10 additions & 0 deletions kubernetes/helm/templates/server-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ rules:
- list
- delete
- watch
- apiGroups:
- networking.k8s.io
resources:
- networkpolicies
verbs:
- get
- create
- update
- list
- delete
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
2 changes: 2 additions & 0 deletions kubernetes/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ docker:
peering:
psk: defaultPeeringKeyPleaseChangeMe

networkPolicies:
enabled: false

# Dev mode expects dev image with watchexec + go run instead of binary
devMode:
Expand Down
27 changes: 27 additions & 0 deletions kubernetes/raw/curl/all.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
apiVersion: v1
kind: Pod
metadata:
name: curl-with-labels
namespace: default
labels:
wormhole.glothriel.github.com/network-policy-consumes-app: nginx-nginx
spec:
terminationGracePeriodSeconds: 1
containers:
- name: curl-container
image: curlimages/curl
command: ["sleep", "999999"]

---
apiVersion: v1
kind: Pod
metadata:
name: curl-no-labels
namespace: default
spec:
terminationGracePeriodSeconds: 1
containers:
- name: curl-container
image: curlimages/curl
command: ["sleep", "999999"]
2 changes: 2 additions & 0 deletions pkg/cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var clientCommand *cli.Command = &cli.Command{
kubernetesNamespaceFlag,
kubernetesLabelsFlag,
peerNameFlag,
enableNetworkPoliciesFlag,
helloRetryIntervalFlag,
nginxExposerConfdPathFlag,
wireguardConfigFilePathFlag,
Expand Down Expand Up @@ -67,6 +68,7 @@ var clientCommand *cli.Command = &cli.Command{
effectiveExposer = k8s.NewK8sExposer(
c.String(kubernetesNamespaceFlag.Name),
k8s.CSVToMap(c.String(kubernetesLabelsFlag.Name)),
c.Bool(enableNetworkPoliciesFlag.Name),
remoteNginxExposer,
)
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ var peerNameFlag *cli.StringFlag = &cli.StringFlag{
Name: "name",
Required: true,
}

var enableNetworkPoliciesFlag *cli.BoolFlag = &cli.BoolFlag{
Name: "network-policies",
Usage: "Enables dynamic creation of network policies for proxy services",
Value: false,
}
2 changes: 2 additions & 0 deletions pkg/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var serverCommand *cli.Command = &cli.Command{
intServerListenPort,
kubernetesNamespaceFlag,
kubernetesLabelsFlag,
enableNetworkPoliciesFlag,
peerStorageDBFlag,
peerNameFlag,
wgAddressFlag,
Expand Down Expand Up @@ -106,6 +107,7 @@ var serverCommand *cli.Command = &cli.Command{
effectiveExposer = k8s.NewK8sExposer(
c.String(kubernetesNamespaceFlag.Name),
k8s.CSVToMap(c.String(kubernetesLabelsFlag.Name)),
c.Bool(enableNetworkPoliciesFlag.Name),
remoteNginxExposer,
)
}
Expand Down
Loading
Loading