From 193547d916b9f61c3e9bf51dadb1b0132d3bffd7 Mon Sep 17 00:00:00 2001 From: Francesco Cheinasso Date: Thu, 28 Sep 2023 12:32:11 +0200 Subject: [PATCH] Wireguard Tunnel Container --- Makefile | 1 + apis/networking/v1alpha1/publickey_types.go | 7 +- build/gateway/tunnel/wireguard/Dockerfile | 20 +++ cmd/gateway/tunnel/wireguard/main.go | 138 ++++++++++++++++++ .../crds/networking.liqo.io_publickeies.yaml | 47 ++++++ .../liqo/files/liqo-gateway-ClusterRole.yaml | 49 +------ pkg/gateway/tunnel/wireguard/doc.go | 16 ++ pkg/gateway/tunnel/wireguard/flags.go | 80 ++++++++++ pkg/gateway/tunnel/wireguard/keys.go | 85 +++++++++++ pkg/gateway/tunnel/wireguard/labels.go | 30 ++++ pkg/gateway/tunnel/wireguard/netlink.go | 42 ++++++ pkg/gateway/tunnel/wireguard/options.go | 63 ++++++++ .../tunnel/wireguard/publickeys-controller.go | 73 +++++++++ pkg/gateway/tunnel/wireguard/wireguard.go | 15 ++ 14 files changed, 618 insertions(+), 48 deletions(-) create mode 100644 build/gateway/tunnel/wireguard/Dockerfile create mode 100644 cmd/gateway/tunnel/wireguard/main.go create mode 100644 deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_publickeies.yaml create mode 100644 pkg/gateway/tunnel/wireguard/doc.go create mode 100644 pkg/gateway/tunnel/wireguard/flags.go create mode 100644 pkg/gateway/tunnel/wireguard/keys.go create mode 100644 pkg/gateway/tunnel/wireguard/labels.go create mode 100644 pkg/gateway/tunnel/wireguard/netlink.go create mode 100644 pkg/gateway/tunnel/wireguard/options.go create mode 100644 pkg/gateway/tunnel/wireguard/publickeys-controller.go create mode 100644 pkg/gateway/tunnel/wireguard/wireguard.go diff --git a/Makefile b/Makefile index 9a7a4cca73..d47036974e 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,7 @@ rbacs: controller-gen $(CONTROLLER_GEN) paths="./cmd/uninstaller" rbac:roleName=liqo-pre-delete output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-pre-delete-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-pre-delete-ClusterRole.yaml $(CONTROLLER_GEN) paths="./cmd/metric-agent" rbac:roleName=liqo-metric-agent output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-metric-agent-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-metric-agent-ClusterRole.yaml $(CONTROLLER_GEN) paths="./cmd/telemetry" rbac:roleName=liqo-telemetry output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-telemetry-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-telemetry-ClusterRole.yaml + $(CONTROLLER_GEN) paths="./cmd/gateway/..." rbac:roleName=liqo-gateway output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-gateway-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-gateway-ClusterRole.yaml # Install gci if not available gci: diff --git a/apis/networking/v1alpha1/publickey_types.go b/apis/networking/v1alpha1/publickey_types.go index 92468efd77..c6055fbbc5 100644 --- a/apis/networking/v1alpha1/publickey_types.go +++ b/apis/networking/v1alpha1/publickey_types.go @@ -23,7 +23,7 @@ import ( // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. // PublicKeyResource the name of the publickey resources. -var PublicKeyResource = "publickeys" +var PublicKeyResource = "publickeies" // PublicKeyKind is the kind name used to register the PublicKey CRD. var PublicKeyKind = "PublicKey" @@ -40,8 +40,11 @@ type PublicKeySpec struct { PublicKey []byte `json:"publicKey,omitempty"` } +// publickeies is used for resource name pluralization because k8s api do not manage false friends. +// Waiting for this fix https://github.com/kubernetes-sigs/kubebuilder/pull/3408 + // +kubebuilder:object:root=true -// +kubebuilder:resource:categories=liqo +// +kubebuilder:resource:categories=liqo,path=publickeies // PublicKey contains a public key data required by some interconnection technologies. type PublicKey struct { diff --git a/build/gateway/tunnel/wireguard/Dockerfile b/build/gateway/tunnel/wireguard/Dockerfile new file mode 100644 index 0000000000..d956845ea7 --- /dev/null +++ b/build/gateway/tunnel/wireguard/Dockerfile @@ -0,0 +1,20 @@ +FROM golang:1.21 as goBuilder +WORKDIR /tmp/builder + +COPY go.mod ./go.mod +COPY go.sum ./go.sum +RUN go mod download + +COPY . ./ +RUN CGO_ENABLED=0 GOOS=linux GOARCH=$(go env GOARCH) go build -ldflags="-s -w" ./cmd/gateway/tunnel/wireguard + + +FROM alpine:3.18 + +RUN apk update && \ + apk add iptables bash wireguard-tools tcpdump conntrack-tools curl && \ + rm -rf /var/cache/apk/* + +COPY --from=goBuilder /tmp/builder/wireguard /usr/bin/liqo-wireguard + +CMD [ "/usr/bin/wireguard" ] diff --git a/cmd/gateway/tunnel/wireguard/main.go b/cmd/gateway/tunnel/wireguard/main.go new file mode 100644 index 0000000000..5f82f3f010 --- /dev/null +++ b/cmd/gateway/tunnel/wireguard/main.go @@ -0,0 +1,138 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "os" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/leaderelection/resourcelock" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + "sigs.k8s.io/controller-runtime/pkg/log" + + ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" + "github.com/liqotech/liqo/pkg/gateway/tunnel/wireguard" + "github.com/liqotech/liqo/pkg/utils/mapper" + "github.com/liqotech/liqo/pkg/utils/restcfg" +) + +// cluster-role +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;create;delete;update +// +kubebuilder:rbac:groups=networking.liqo.io,resources=publickeys,verbs=get;list;create;delete;update + +var ( + addToSchemeFunctions = []func(*runtime.Scheme) error{ + networkingv1alpha1.AddToScheme, + ipamv1alpha1.AddToScheme, + } +) + +func main() { + var err error + ctx := ctrl.SetupSignalHandler() + options := wireguard.Options{} + scheme := runtime.NewScheme() + + // Init flags and check mandatory ones. + restcfg.InitFlags(nil) + klog.InitFlags(nil) + wireguard.InitFlags(&options) + flag.Parse() + if err = wireguard.CheckMandatoryFlags(wireguard.MandatoryFlags); err != nil { + klog.Errorf("Mandatory flags: %v", err) + os.Exit(1) + } + + // Adds the APIs to the scheme. + for _, addToScheme := range addToSchemeFunctions { + if err = addToScheme(scheme); err != nil { + klog.Errorf("unable to add scheme: %v", err) + os.Exit(1) + } + } + + // Set controller-runtime logger. + log.SetLogger(klog.NewKlogr()) + + // Get the rest config. + cfg := config.GetConfigOrDie() + + // Create the client. This cliend should be used only outside the reconciler. + cl, err := client.New(cfg, client.Options{ + Cache: nil, + }) + if err != nil { + klog.Errorf("unable to create client: %v", err) + os.Exit(1) + } + + // Create the manager. + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + MapperProvider: mapper.LiqoMapperProvider(scheme), + Scheme: scheme, + MetricsBindAddress: options.MetricsAddress, + HealthProbeBindAddress: options.ProbeAddr, + LeaderElection: options.LeaderElection, + LeaderElectionID: "66cf253f.wgtunnel.liqo.io", + LeaderElectionNamespace: options.Namespace, + LeaderElectionReleaseOnCancel: true, + LeaderElectionResourceLock: resourcelock.LeasesResourceLock, + }) + if err != nil { + klog.Error(err) + os.Exit(1) + } + + // Setup the controller. + pkr, err := wireguard.NewPublicKeysReconciler( + mgr.GetClient(), + mgr.GetScheme(), + mgr.GetEventRecorderFor("wireguard-controller"), + ) + if err != nil { + klog.Error(err) + os.Exit(1) + } + + // Setup the controller. + if err = pkr.SetupWithManager(mgr); err != nil { + klog.Error(err) + os.Exit(1) + } + + // Ensure presence of Secret with private and public keys. + if err = wireguard.EnsureKeysSecret(ctx, cl, &options); err != nil { + klog.Error(err) + os.Exit(1) + } + + // Create the wg-liqo interface. + err = wireguard.CreateLink(&options) + if err != nil { + klog.Errorf("unable to create wireguard interface: %v", err) + os.Exit(1) + } + + // Start the manager. + if err = mgr.Start(ctx); err != nil { + klog.Error(err) + os.Exit(1) + } +} diff --git a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_publickeies.yaml b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_publickeies.yaml new file mode 100644 index 0000000000..8a30f2bda4 --- /dev/null +++ b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_publickeies.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: publickeies.networking.liqo.io +spec: + group: networking.liqo.io + names: + categories: + - liqo + kind: PublicKey + listKind: PublicKeyList + plural: publickeies + singular: publickey + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: PublicKey contains a public key data required by some interconnection + technologies. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: PublicKeySpec defines the desired state of PublicKey. + properties: + publicKey: + description: PublicKey contains the public key. + format: byte + type: string + type: object + type: object + served: true + storage: true diff --git a/deployments/liqo/files/liqo-gateway-ClusterRole.yaml b/deployments/liqo/files/liqo-gateway-ClusterRole.yaml index 1cbb3a349e..61aa35e3fd 100644 --- a/deployments/liqo/files/liqo-gateway-ClusterRole.yaml +++ b/deployments/liqo/files/liqo-gateway-ClusterRole.yaml @@ -2,63 +2,20 @@ rules: - apiGroups: - "" resources: - - events + - secrets verbs: - create - delete - get - list - - patch - update - - watch - apiGroups: - - "" - resources: - - pods - verbs: - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - services - verbs: - - list - - patch - - update - - watch -- apiGroups: - - net.liqo.io + - networking.liqo.io resources: - - natmappings + - publickeys verbs: - create - delete - get - list - - patch - - update - - watch -- apiGroups: - - net.liqo.io - resources: - - tunnelendpoints - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - net.liqo.io - resources: - - tunnelendpoints/status - verbs: - - get - - patch - update diff --git a/pkg/gateway/tunnel/wireguard/doc.go b/pkg/gateway/tunnel/wireguard/doc.go new file mode 100644 index 0000000000..81baec8e31 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/doc.go @@ -0,0 +1,16 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package wireguard contains the implementation of the wireguard tunnel. +package wireguard diff --git a/pkg/gateway/tunnel/wireguard/flags.go b/pkg/gateway/tunnel/wireguard/flags.go new file mode 100644 index 0000000000..f6cfeafe79 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/flags.go @@ -0,0 +1,80 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +import ( + "flag" + "fmt" +) + +type FlagName string + +func (fn FlagName) String() string { + return string(fn) +} + +const ( + // FlagNameName is the name of the WgGateway resource. + FlagNameName FlagName = "name" + // FlagNameNamespace is the namespace WgGateway resource. + FlagNameNamespace FlagName = "namespace" + + // FlagNameMode is the mode in which the wireguard interface is configured. + FlagNameMode FlagName = "mode" + // FlagNameMTU is the MTU for the wireguard interface. + FlagNameMTU FlagName = "mtu" + // FlagNameMetricsAddress is the address for the metrics endpoint. + FlagNameMetricsAddress FlagName = "metrics-address" + + // FlagNameLeaderElection is the flag to enable leader election. + FlagNameLeaderElection FlagName = "leader-election" + // FlagNameProbeAddr is the address for the health probe endpoint. + FlagNameProbeAddr FlagName = "health-probe-bind-address" +) + +// MandatoryFlags contains the list of the mandatory flags. +var MandatoryFlags = []FlagName{ + FlagNameName, + FlagNameNamespace, + FlagNameMode, +} + +// InitFlags initializes the flags for the wireguard tunnel. +func InitFlags(options *Options) { + flag.StringVar(&options.Name, FlagNameName.String(), "", "Name for the wireguard interface") + flag.StringVar(&options.Namespace, FlagNameNamespace.String(), "", "Namespace for the wireguard interface") + + flag.Var(&options.Mode, FlagNameMode.String(), "Mode for the wireguard interface") + flag.IntVar(&options.MTU, FlagNameMTU.String(), 1420, "MTU for the wireguard interface") + + flag.StringVar(&options.MetricsAddress, FlagNameMetricsAddress.String(), ":8080", "Address for the metrics endpoint") + flag.BoolVar(&options.LeaderElection, FlagNameLeaderElection.String(), false, "Enable leader election") + flag.StringVar(&options.ProbeAddr, FlagNameProbeAddr.String(), ":8081", "Address for the health probe endpoint") +} + +// CheckMandatoryFlags checks if the mandatory flags are set. +// This function must be called after flag.Parse(). +func CheckMandatoryFlags(flags []FlagName) error { + for _, fn := range flags { + f := flag.Lookup(fn.String()) + if f == nil { + return fmt.Errorf("flag %s not found", fn) + } + if f.Value.String() == "" { + return fmt.Errorf("flag %s cannot be empty", fn) + } + } + return nil +} diff --git a/pkg/gateway/tunnel/wireguard/keys.go b/pkg/gateway/tunnel/wireguard/keys.go new file mode 100644 index 0000000000..3356881a6a --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/keys.go @@ -0,0 +1,85 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +import ( + "context" + + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + corev1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +const ( + // WireguardInterfaceName is the name of the wireguard interface. + WireguardInterfaceName = "liqo-wg" + + // SecretPrivateKeyField is the name of the field inside the Secret resource that contains the private key. + SecretPrivateKeyField = "private-key" + // SecretPublicKeyField is the name of the field inside the Secret resource that contains the public key. + SecretPublicKeyField = "public-key" +) + +// EnsureKeysSecret ensure the presence of the private and public keys for the Wireguard interface and save them inside a Secret resource and Options. +func EnsureKeysSecret(ctx context.Context, cl client.Client, opts *Options) error { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: opts.Name, + Namespace: opts.Namespace, + }, + } + + err := cl.Get(ctx, client.ObjectKey{Name: opts.Name, Namespace: opts.Namespace}, secret) + + switch { + case kerrors.IsNotFound(err): + if err := createKeysSecret(ctx, cl, secret); err != nil { + return err + } + case err != nil: + return err + } + + opts.PrivateKey = wgtypes.Key(secret.Data[SecretPrivateKeyField]) + opts.PublicKey = wgtypes.Key(secret.Data[SecretPublicKeyField]) + + return nil +} + +// createKeysSecret creates the private and public keys for the Wireguard interface and save them inside a Secret resource. +func createKeysSecret(ctx context.Context, cl client.Client, secret *corev1.Secret) error { + pri, err := wgtypes.GeneratePrivateKey() + if err != nil { + return err + } + pub := pri.PublicKey() + + if _, err = ctrlutil.CreateOrUpdate(ctx, cl, secret, func() error { + secret.SetLabels(map[string]string{ + string(WireguardLabelsServer): WireguardLabelsValue, + }) + secret.Data = map[string][]byte{ + SecretPrivateKeyField: pri[:], + SecretPublicKeyField: pub[:], + } + return nil + }); err != nil { + return err + } + return nil +} diff --git a/pkg/gateway/tunnel/wireguard/labels.go b/pkg/gateway/tunnel/wireguard/labels.go new file mode 100644 index 0000000000..9cdefa2b1b --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/labels.go @@ -0,0 +1,30 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +// WireguardLabels is the type used to identify the wireguard labels. +type WireguardLabels string + +const ( + // WireguardLabelsServer is the label used to identify the wireguard server. + WireguardLabelsServer WireguardLabels = "networking.liqo.io/wireguard-server" + // WireguardLabelsClient is the label used to identify the wireguard client. + WireguardLabelsClient WireguardLabels = "networking.liqo.io/wireguard-client" + // WireguardLabelsSecret is the label used to identify the wireguard secret. + WireguardLabelsSecret WireguardLabels = "networking.liqo.io/wireguard-secret" + + // WireguardLabelsValue is the value used for the wireguard labels. + WireguardLabelsValue = "true" +) diff --git a/pkg/gateway/tunnel/wireguard/netlink.go b/pkg/gateway/tunnel/wireguard/netlink.go new file mode 100644 index 0000000000..45a829bfe4 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/netlink.go @@ -0,0 +1,42 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +import "github.com/vishvananda/netlink" + +const ( + // WireguardInterfaceName is the name of the wireguard interface. + WireguardInterfaceName = "liqo-wg" +) + +// CreateLink creates a new Wireguard interface. +func CreateLink(options *Options) error { + link := netlink.Wireguard{ + LinkAttrs: netlink.LinkAttrs{ + MTU: options.MTU, + Name: WireguardInterfaceName, + }, + } + err := netlink.LinkAdd(&link) + if err != nil { + return err + } + return nil +} + +// GetLink returns the Wireguard interface. +func GetLink() (netlink.Link, error) { + return netlink.LinkByName(WireguardInterfaceName) +} diff --git a/pkg/gateway/tunnel/wireguard/options.go b/pkg/gateway/tunnel/wireguard/options.go new file mode 100644 index 0000000000..f4d5fd9117 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/options.go @@ -0,0 +1,63 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +import ( + "fmt" + + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +// Mode is the mode in which the wireguard interface is configured. +type Mode string + +const ( + // ModeServer is the mode in which the wireguard interface is configured as a server. + ModeServer Mode = "server" + // ModeClient is the mode in which the wireguard interface is configured as a client. + ModeClient Mode = "client" +) + +// String returns the string representation of the mode. +func (m Mode) String() string { + return string(m) +} + +// Set sets the value of the mode. +func (m *Mode) Set(value string) error { + if value == "" { + return fmt.Errorf("mode cannot be empty") + } + if value != ModeServer.String() && value != ModeClient.String() { + return fmt.Errorf("invalid mode %q", value) + } + *m = Mode(value) + return nil +} + +// Options contains the options for the wireguard interface. +type Options struct { + Name string + Namespace string + + Mode Mode + MTU int + PrivateKey wgtypes.Key + PublicKey wgtypes.Key + + LeaderElection bool + MetricsAddress string + ProbeAddr string +} diff --git a/pkg/gateway/tunnel/wireguard/publickeys-controller.go b/pkg/gateway/tunnel/wireguard/publickeys-controller.go new file mode 100644 index 0000000000..cebd257a92 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/publickeys-controller.go @@ -0,0 +1,73 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard + +import ( + "context" + "fmt" + + "golang.zx2c4.com/wireguard/wgctrl" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" +) + +// PublicKeysReconciler updates the PublicKey resource used to establish the Wireguard connection. +type PublicKeysReconciler struct { + Wgcl *wgctrl.Client + Client client.Client + Scheme *runtime.Scheme + EventsRecorder record.EventRecorder +} + +// NewPublicKeysReconciler returns a new PublicKeysReconciler. +func NewPublicKeysReconciler(cl client.Client, s *runtime.Scheme, er record.EventRecorder) (*PublicKeysReconciler, error) { + wgcl, err := wgctrl.New() + if err != nil { + return nil, fmt.Errorf("unable to create wireguard client: %w", err) + } + return &PublicKeysReconciler{ + Wgcl: wgcl, + Client: cl, + Scheme: s, + EventsRecorder: er, + }, nil +} + +// Reconcile manage PublicKey resources. +func (r *PublicKeysReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + publicKey := &networkingv1alpha1.PublicKey{} + if err := r.Client.Get(ctx, req.NamespacedName, publicKey); err != nil { + if apierrors.IsNotFound(err) { + klog.Infof("There is no publicKey %s", req.String()) + return ctrl.Result{}, nil + } + return ctrl.Result{}, fmt.Errorf("unable to get the publicKey %q: %w", req.NamespacedName, err) + } + + return ctrl.Result{}, nil +} + +// SetupWithManager register the ConfigurationReconciler to the manager. +func (r *PublicKeysReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&networkingv1alpha1.PublicKey{}). + Complete(r) +} diff --git a/pkg/gateway/tunnel/wireguard/wireguard.go b/pkg/gateway/tunnel/wireguard/wireguard.go new file mode 100644 index 0000000000..7bef0539c4 --- /dev/null +++ b/pkg/gateway/tunnel/wireguard/wireguard.go @@ -0,0 +1,15 @@ +// Copyright 2019-2023 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package wireguard