Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
cache: false

- name: Lint Go
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9

- name: Build
run: |
Expand Down
27 changes: 27 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,32 @@ var (
Value: "metal-stack",
Usage: "ensures a provider tenant on startup (used for bootstrapping and technical tokens). can be disabled by setting to empty string.",
}
// Headscale
headscaleAddressFlag = &cli.StringFlag{
Name: "headscale-addr",
Value: "headscale:50443",
Usage: "address of headscale grpc server endpoint",
EnvVars: []string{"HEADSCALE_ADDRESS"},
}
headscaleControlplaneAddressFlag = &cli.StringFlag{
Name: "headscale-cp-addr",
Value: "",
Usage: "controlplane address of headscale server reachable from the nodes to join",
EnvVars: []string{"HEADSCALE_CONTROLPLANE_ADDRESS"},
}
headscaleApikeyFlag = &cli.StringFlag{
Name: "headscale-api-key",
Value: "",
Usage: "initial api key to connect to the headscale grpc server",
EnvVars: []string{"HEADSCALE_API_KEY"},
}
headscaleEnabledFlag = &cli.BoolFlag{
Name: "headscale-enabled",
Value: false,
Usage: "toggle if headscale should be enabled",
EnvVars: []string{"HEADSCALE_ENABLED"},
}
// End Headscale
)

func main() {
Expand All @@ -227,6 +253,7 @@ func main() {
newServeCmd(),
newTokenCmd(),
newDatastoreCmd(),
newVPNCmd(),
},
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/server/serve-cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
ipamv1connect "github.com/metal-stack/go-ipam/api/v1/apiv1connect"
mdm "github.com/metal-stack/masterdata-api/pkg/client"
"github.com/metal-stack/metal-apiserver/pkg/db/generic"
"github.com/metal-stack/metal-apiserver/pkg/headscale"
"github.com/metal-stack/metal-apiserver/pkg/repository"
"github.com/metal-stack/metal-apiserver/pkg/service"
"github.com/metal-stack/metal-apiserver/pkg/test"
Expand Down Expand Up @@ -70,6 +71,10 @@ func newServeCmd() *cli.Command {
oidcEndSessionUrlFlag,
oidcUniqueUserKeyFlag,
oidcTLSSkipVerifyFlag,
headscaleAddressFlag,
headscaleControlplaneAddressFlag,
headscaleApikeyFlag,
headscaleEnabledFlag,
},
Action: func(ctx *cli.Context) error {
log, err := createLogger(ctx)
Expand Down Expand Up @@ -97,6 +102,16 @@ func newServeCmd() *cli.Command {
return fmt.Errorf("unable to create masterdata.client: %w", err)
}

hc, err := headscale.NewClient(headscale.Config{
Log: log,
Disabled: !ctx.Bool(headscaleEnabledFlag.Name),
Apikey: ctx.String(headscaleApikeyFlag.Name),
Endpoint: ctx.String(headscaleAddressFlag.Name),
})
if err != nil {
return err
}

connectOpts := rethinkdb.ConnectOpts{
Addresses: ctx.StringSlice(rethinkdbAddressesFlag.Name),
Database: ctx.String(rethinkdbDBNameFlag.Name),
Expand Down Expand Up @@ -140,6 +155,8 @@ func newServeCmd() *cli.Command {
OIDCUniqueUserKey: ctx.String(oidcUniqueUserKeyFlag.Name),
OIDCTLSSkipVerify: ctx.Bool(oidcTLSSkipVerifyFlag.Name),
IsStageDev: strings.EqualFold(stage, stageDEV),
HeadscaleControlplaneAddress: ctx.String(headscaleControlplaneAddressFlag.Name),
HeadscaleClient: hc,
}

if providerTenant := ctx.String(ensureProviderTenantFlag.Name); providerTenant != "" {
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func Test_newServeCmd(t *testing.T) {
args := []string{"-h"}

cmd := newServeCmd()
require.Len(t, cmd.Flags, 37)
require.Len(t, cmd.Flags, 41)

app.Commands = []*cli.Command{cmd}
err := app.Run(args)
Expand Down
80 changes: 80 additions & 0 deletions cmd/server/vpn-cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"fmt"

"github.com/metal-stack/metal-apiserver/pkg/db/generic"
"github.com/metal-stack/metal-apiserver/pkg/headscale"
"github.com/metal-stack/metal-apiserver/pkg/repository"
vpnadmin "github.com/metal-stack/metal-apiserver/pkg/service/vpn/admin"
"github.com/urfave/cli/v2"
"gopkg.in/rethinkdb/rethinkdb-go.v6"
)

func newVPNCmd() *cli.Command {
return &cli.Command{
Name: "vpn",
Flags: []cli.Flag{
rethinkdbAddressesFlag,
rethinkdbDBNameFlag,
rethinkdbPasswordFlag,
rethinkdbUserFlag,
headscaleAddressFlag,
headscaleApikeyFlag,
headscaleEnabledFlag,
},
Subcommands: []*cli.Command{
{
Name: "connected-machines",
Description: "evaluates whether machines connected to vpn and detects their vpn ip addresses",
Action: func(ctx *cli.Context) error {
log, err := createLogger(ctx)
if err != nil {
return fmt.Errorf("unable to create logger %w", err)
}

hc, err := headscale.NewClient(headscale.Config{
Log: log,
Disabled: !ctx.Bool(headscaleEnabledFlag.Name),
Apikey: ctx.String(headscaleApikeyFlag.Name),
Endpoint: ctx.String(headscaleAddressFlag.Name),
})
if err != nil {
return err
}
if hc == nil || !ctx.Bool(headscaleEnabledFlag.Name) {
log.Info("headscale is disabled, not checking for connected machines")
}

connectOpts := rethinkdb.ConnectOpts{
Addresses: ctx.StringSlice(rethinkdbAddressesFlag.Name),
Database: ctx.String(rethinkdbDBNameFlag.Name),
Username: ctx.String(rethinkdbUserFlag.Name),
Password: ctx.String(rethinkdbPasswordFlag.Name),
MaxIdle: 10,
MaxOpen: 20,
}

ds, err := generic.New(log.WithGroup("datastore"), connectOpts)
if err != nil {
return fmt.Errorf("unable to create datastore: %w", err)
}

repo, err := repository.New(log, nil, ds, nil, nil)
if err != nil {
return fmt.Errorf("unable to create repository: %w", err)
}

vpnService := vpnadmin.New(vpnadmin.Config{
Log: log,
Repo: repo,
HeadscaleClient: hc,
})

_, err = vpnService.EvaluateVPNConnected(ctx.Context)
return err
},
},
},
}
}
38 changes: 36 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/metal-stack/metal-apiserver

go 1.25
go 1.25.5

require (
buf.build/go/protovalidate v1.1.0
Expand All @@ -20,6 +20,7 @@ require (
github.com/gorilla/sessions v1.4.0
github.com/hibiken/asynq v0.25.1
github.com/jmoiron/sqlx v1.4.0
github.com/juanfont/headscale v0.27.1
github.com/klauspost/connect-compress/v2 v2.1.0
github.com/lestrrat-go/jwx/v3 v3.0.13
github.com/looplab/fsm v1.0.3
Expand Down Expand Up @@ -47,6 +48,7 @@ require (
google.golang.org/grpc v1.78.0
google.golang.org/protobuf v1.36.11
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.2
tailscale.com v1.92.5
)

replace github.com/markbates/goth => github.com/metal-stack/goth v0.1.0
Expand All @@ -55,14 +57,17 @@ require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 // indirect
cel.dev/expr v0.25.1 // indirect
dario.cat/mergo v1.0.2 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coder/websocket v1.8.14 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
Expand All @@ -72,7 +77,9 @@ require (
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/creachadair/msync v0.7.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dblohm7/wingoes v0.0.0-20240801171404-fc12d7c70140 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/distribution/reference v0.6.0 // indirect
Expand All @@ -83,8 +90,11 @@ require (
github.com/emicklei/go-restful-openapi/v2 v2.11.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gaissmai/bart v0.18.0 // indirect
github.com/go-chi/chi/v5 v5.2.4 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-json-experiment/json v0.0.0-20250813024750-ebf49471dced // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
Expand All @@ -104,17 +114,22 @@ require (
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/cel-go v0.26.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/icza/dyno v0.0.0-20230330125955-09f820a8d9c0 // indirect
github.com/jackc/pgtype v1.14.4 // indirect
github.com/jackc/pgx/v4 v4.18.3 // indirect
github.com/jackc/pgx/v5 v5.8.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.3 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
Expand All @@ -128,7 +143,10 @@ require (
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mdelapenya/tlscert v0.2.0 // indirect
github.com/mdlayher/netlink v1.8.0 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/minio/minlz v1.0.1 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.2.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
Expand All @@ -145,23 +163,34 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus-community/pro-bing v0.7.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/otlptranslator v1.0.0 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/safchain/ethtool v0.7.0 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/shirou/gopsutil/v4 v4.25.12 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
github.com/tailscale/hujson v0.0.0-20250226034555-ec1d1c113d33 // indirect
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
github.com/tailscale/wireguard-go v0.0.0-20250716170648-1d0488a3d7da // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.2.0 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
Expand All @@ -184,16 +213,21 @@ require (
go.uber.org/zap v1.27.1 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
golang.org/x/crypto v0.47.0 // indirect
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260114163908-3f89685c29c3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3 // indirect
gopkg.in/cenkalti/backoff.v2 v2.2.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
Loading