Skip to content

Commit

Permalink
#47: Added documentation entry about admin API
Browse files Browse the repository at this point in the history
  • Loading branch information
glothriel committed Jun 21, 2024
1 parent 4a198b4 commit 86a60d6
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 11 deletions.
54 changes: 51 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ If you'll use DNS, you can install the server in one step (replace 0.0.0.0 with
kubectl create namespace wormhole
# Replace 1.0.0 with latest version from the releases page
helm install -n wormhole wh oci://ghcr.io/glothriel/wormhole/wormhole --version 1.0.0 --set server.enabled=true --set server.service.type=LoadBalancer --set server.wg.publicHost="0.0.0.0"
helm install -n wormhole wh oci://ghcr.io/glothriel/wormhole/wormhole --version 1.1.0 --set server.enabled=true --set server.service.type=LoadBalancer --set server.wg.publicHost="0.0.0.0"
# Wait for the LoadBalancer to get an IP
kubectl get svc -n wormhole
# Update the server with the IP
helm upgrade -n wormhole wh oci://ghcr.io/glothriel/wormhole/wormhole --version 1.0.0 --set server.enabled=true --set server.service.type=LoadBalancer --set server.wg.publicHost="<the new IP>"
helm upgrade -n wormhole wh oci://ghcr.io/glothriel/wormhole/wormhole --version 1.1.0 --reuse-values --set server.wg.publicHost="<the new IP>"
```

### Install client
Expand Down Expand Up @@ -134,6 +134,54 @@ Such policies allow communication from any pod in any namespace, providing, that

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.

## HTTP API

Wormhole exposes API, that allows querying apps exposed by remote peers. The API does not require authentication. The API by default listens on port 8082.

### GET /api/apps/v1

This endpoint returns the list of apps exposed locally by the remote peers.

#### Request

No body or query parameters are required.

#### Response

| Property | Required | Type | Description |
|:---------|:---------|:-----|:------------|
| **name** | yes | String | Name of the exposed app |
| **address** | yes | String | `{hostname}:{port}` of the app exposed on the local cluster |
| **peer** | yes | String | Name of the remote peer, that exposed the app |


| Code | Description |
|:-----|:------------|
|200 Ok | Returned when request was successful |
|500 Internal server error | Returned when the apps could not be fetched for unknown reasons. |

### GET /api/peers/v1

This endpoint is only available on the server. It returns the list of remote peers that are connected to the server.

#### Request

No body or query parameters are required.

#### Response

| Property | Required | Type | Description |
|:---------|:---------|:-----|:------------|
| **name** | yes | String | Name of the remote peer |
| **ip** | yes | String | IP of the peer in wireguard network |
| **public_key** | yes | String | Wireguard public key of the peer |


| Code | Description |
|:-----|:------------|
|200 Ok | Returned when request was successful |
|500 Internal server error | Returned when the peers could not be fetched for unknown reasons. |

## Local development

### Development environment
Expand All @@ -158,7 +206,7 @@ The development environment deploys a server, two clients and a mock service, th
kubectl annotate --overwrite svc --namespace nginx nginx wormhole.glothriel.github.com/exposed=yes
```

The additional services should be immediately created. Please note, that all three workloads are deployed on the same (and by extension are monitoring the same services for annotations), so the nginx will be exposed 4 times - client1 to server, client2 to server, server to client1 and server to client2.
The additional services should be immediately created. Please note, that all three workloads are deployed on the same cluster (and by extension are monitoring the same services for annotations), so the nginx will be exposed 4 times - client1 to server, client2 to server, server to client1 and server to client2.

### Integration tests

Expand Down
2 changes: 2 additions & 0 deletions kubernetes/helm/templates/client-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ spec:

- image: {{ $.Values.docker.registry }}{{ if $.Values.docker.registry }}/{{ end }}{{ $.Values.docker.image }}:{{ $.Values.docker.version }}
name: wormhole
ports:
- containerPort: 8082
envFrom:
- secretRef:
name: {{ template "name-client" . }}-env
Expand Down
19 changes: 19 additions & 0 deletions kubernetes/helm/templates/client-svc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if .Values.client.enabled }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "name-client" . }}-api
namespace: {{ $.Release.Namespace }}
labels:
application: {{ template "name-client" . }}
spec:
ports:
- name: api
port: 8082
targetPort: 8082
selector:
application: {{ template "name-client" . }}
sessionAffinity: None
type: ClusterIP
{{ end }}
17 changes: 17 additions & 0 deletions kubernetes/helm/templates/server-svc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,21 @@ spec:
application: {{ template "name-server" . }}
sessionAffinity: None
type: {{ $.Values.server.service.type }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "name-server" . }}-api
namespace: {{ $.Release.Namespace }}
labels:
application: {{ template "name-server" . }}
spec:
ports:
- name: api
port: 8082
targetPort: 8082
selector:
application: {{ template "name-server" . }}
sessionAffinity: None
type: ClusterIP
{{ end }}
4 changes: 4 additions & 0 deletions pkg/api/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"github.com/gin-gonic/gin"
"github.com/glothriel/wormhole/pkg/hello"
"github.com/glothriel/wormhole/pkg/peers"
)

type appsController struct {
Expand All @@ -18,6 +19,9 @@ func (ac *appsController) registerRoutes(r *gin.Engine) {
})
return
}
if apps == nil {
apps = []peers.App{}
}
c.JSON(200, apps)
})
}
Expand Down
15 changes: 12 additions & 3 deletions pkg/api/peers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

type peerController struct {
peers hello.PeerStorage
wgConfig *wg.Config
watcher *wg.Watcher
peers hello.PeerStorage
wgConfig *wg.Config
watcher *wg.Watcher
enablePeerDeletion bool
}

func (p *peerController) deletePeer(name string) error {
Expand Down Expand Up @@ -46,6 +47,12 @@ func (p *peerController) registerRoutes(r *gin.Engine) {
})

r.DELETE("/api/peers/v1/:name", func(c *gin.Context) {
if !p.enablePeerDeletion {
c.JSON(403, gin.H{
"error": "Peer deletion is disabled",
})
return
}
name := c.Param("name")
err := p.deletePeer(name)
if err != nil {
Expand All @@ -64,5 +71,7 @@ func NewPeersController(peers hello.PeerStorage, wgConfig *wg.Config, watcher *w
peers: peers,
wgConfig: wgConfig,
watcher: watcher,
// We currently don't have authorization in place, disabling peer deletion
enablePeerDeletion: false,
}
}
12 changes: 12 additions & 0 deletions pkg/cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package cmd
import (
"time"

"github.com/glothriel/wormhole/pkg/api"
"github.com/glothriel/wormhole/pkg/hello"
"github.com/glothriel/wormhole/pkg/k8s"
"github.com/glothriel/wormhole/pkg/listeners"
Expand Down Expand Up @@ -139,6 +140,17 @@ var clientCommand *cli.Command = &cli.Command{
logrus.Fatalf("Failed to create syncing client: %v", scErr)
}

go func() {
err := api.NewAdminAPI([]api.Controller{
api.NewAppsController(
remoteListenerRegistry,
),
}, c.Bool(debugFlag.Name)).Run(":8082")
if err != nil {
logrus.Fatalf("Failed to start admin API: %v", err)
}
}()

return sc.Start()
},
}
2 changes: 1 addition & 1 deletion pkg/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ var serverCommand *cli.Command = &cli.Command{
go ss.Start()
go func() {
err := api.NewAdminAPI([]api.Controller{
api.NewAppsController(appSource),
api.NewAppsController(appsExposedFromRemote),
api.NewPeersController(peerStorage, wgConfig, watcher),
}, c.Bool(debugFlag.Name)).Run(":8082")
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions pkg/hello/if.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ type WireguardConfigReloader interface {

// PeerInfo is a struct that contains information about a peer
type PeerInfo struct {
Name string `json:"name"`
IP string `json:"ip"`
PublicKey string `json:"public_key"`
LastContact int64 `json:"last_contact"`
Name string `json:"name"`
IP string `json:"ip"`
PublicKey string `json:"public_key"`
}

0 comments on commit 86a60d6

Please sign in to comment.