From 924170f5f295951a779ed24b921a75f76012692d Mon Sep 17 00:00:00 2001 From: kaiyou <dev@kaiyou.fr> Date: Fri, 15 Jul 2022 19:09:07 +0200 Subject: [PATCH] Implement sml as go type parameters --- cmd/hepto/config.go | 2 +- go.mod | 39 +++++------ go.sum | 37 +++++++++++ pkg/cluster/cluster.go | 64 ++++++++++++++++-- pkg/cluster/config.go | 2 +- pkg/cluster/meta.go | 24 +++++-- pkg/cluster/pki.go | 23 +++++++ pkg/pki/cert.go | 121 +++++++++++++++++++++++++++++++++++ pkg/pki/pki.go | 75 ++-------------------- pkg/selfcontain/container.go | 2 +- pkg/sml/delegate.go | 18 +++--- pkg/sml/memberlist.go | 62 +++++++++--------- pkg/sml/node.go | 33 ++++++---- test.go | 42 ++++++++++++ 14 files changed, 390 insertions(+), 154 deletions(-) create mode 100644 pkg/pki/cert.go create mode 100644 test.go diff --git a/cmd/hepto/config.go b/cmd/hepto/config.go index 3ad960e..93e7747 100644 --- a/cmd/hepto/config.go +++ b/cmd/hepto/config.go @@ -63,6 +63,6 @@ func init() { // Node settings rootCmd.Flags().IntVar(&config.Node.Port, "discovery-port", 7123, "TCP port used for discovering the cluster") rootCmd.Flags().StringVar(&config.Node.Name, "name", "", "Hepto node name") - rootCmd.Flags().Var(&config.Node.Anchors, "anchors", "List of cluster anchors") + rootCmd.Flags().StringSliceVar(&config.Node.Anchors, "anchors", []string{}, "List of cluster anchors") rootCmd.Flags().StringVar(&config.Node.Role, "role", "node", "Node role inside the cluster") } diff --git a/go.mod b/go.mod index 5be6b93..fb61918 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module forge.tedomum.net/acides/hepto/hepto -go 1.17 +go 1.18 require ( github.com/containerd/containerd v1.5.10 @@ -9,15 +9,15 @@ require ( github.com/docker/docker v20.10.8+incompatible github.com/google/cadvisor v0.39.3 github.com/hashicorp/memberlist v0.3.1 - github.com/opencontainers/runc v1.0.2 + github.com/opencontainers/runc v1.1.3 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.8.1 + github.com/sirupsen/logrus v1.9.0 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.11.0 - github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 + github.com/vishvananda/netlink v1.2.1-beta.2 go.etcd.io/etcd/server/v3 v3.5.0 - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad + golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b k8s.io/api v0.22.7 k8s.io/apiextensions-apiserver v0.0.0 @@ -61,16 +61,16 @@ require ( github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/aws/aws-sdk-go v1.38.49 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.2.0 // indirect + github.com/bits-and-blooms/bitset v1.3.0 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/checkpoint-restore/go-criu/v5 v5.0.0 // indirect - github.com/cilium/ebpf v0.6.2 // indirect + github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect + github.com/cilium/ebpf v0.9.1 // indirect github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 // indirect github.com/container-storage-interface/spec v1.5.0 // indirect github.com/containerd/cgroups v1.0.1 // indirect - github.com/containerd/console v1.0.2 // indirect + github.com/containerd/console v1.0.3 // indirect github.com/containerd/continuity v0.1.0 // indirect github.com/containerd/fifo v1.0.0 // indirect github.com/containerd/go-cni v1.0.2 // indirect @@ -84,8 +84,8 @@ require ( github.com/coreos/go-iptables v0.5.0 // indirect github.com/coreos/go-oidc v2.1.0+incompatible // indirect github.com/coreos/go-semver v0.3.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect - github.com/cyphar/filepath-securejoin v0.2.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -104,7 +104,7 @@ require ( github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect - github.com/godbus/dbus/v5 v5.0.4 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect github.com/gogo/googleapis v1.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -156,7 +156,7 @@ require ( github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.4.1 // indirect + github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/symlink v0.1.0 // indirect github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -169,7 +169,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect - github.com/opencontainers/selinux v1.8.2 // indirect + github.com/opencontainers/selinux v1.10.1 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -184,7 +184,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/seccomp/libseccomp-golang v0.9.1 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.4.1 // indirect @@ -197,8 +197,8 @@ require ( github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tchap/go-patricia v2.2.6+incompatible // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect - github.com/urfave/cli v1.22.2 // indirect - github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect + github.com/urfave/cli v1.22.9 // indirect + github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect github.com/vmware/govmomi v0.20.3 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.6 // indirect @@ -225,7 +225,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 // indirect + golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect @@ -239,7 +239,7 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect google.golang.org/grpc v1.45.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/gcfg.v1 v1.2.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.4 // indirect @@ -267,6 +267,7 @@ require ( replace ( // These pinned dependencies are documented in HACKS.md github.com/containernetworking/plugins => github.com/rancher/plugins v0.9.1-k3s1 + github.com/opencontainers/runc => ./runc google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2 // Kubernetes dependencies are pinned to override v0.0.0 inside the staged kubernetes root diff --git a/go.sum b/go.sum index 7db8219..56bc28b 100644 --- a/go.sum +++ b/go.sum @@ -158,6 +158,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.3.0 h1:h7mv5q31cthBTd7V4kLAZaIThj1e8vPGcSqpPue9KVI= +github.com/bits-and-blooms/bitset v1.3.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -184,6 +186,8 @@ github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1 github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0 h1:TW8f/UvntYoVDMN1K2HlT82qH1rb0sOjpGw3m6Ym+i4= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -194,6 +198,8 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -236,6 +242,8 @@ github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4g github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -334,11 +342,15 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= @@ -444,10 +456,13 @@ github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6m github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= @@ -744,6 +759,8 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/symlink v0.1.0 h1:MTFZ74KtNI6qQQpuBxU+uKCim4WtOMokr03hCfJcazE= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= @@ -821,6 +838,8 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGqQpoHsF8w= +github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= @@ -905,6 +924,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -916,6 +937,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -985,14 +1008,20 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= +github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= +github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3 h1:gpw/0Ku+6RgF3jsi7fnCLmlcikBHfKBCUcu1qgc16OU= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -1201,6 +1230,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 h1:6mzvA99KwZxbOrxww4EvWVQUnN1+xEu9tafK5ZxkYeA= golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= +golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1339,6 +1370,10 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1539,6 +1574,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 6132aef..16c2070 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -5,6 +5,7 @@ package cluster import ( "net" + "forge.tedomum.net/acides/hepto/hepto/pkg/pki" "forge.tedomum.net/acides/hepto/hepto/pkg/sml" "forge.tedomum.net/acides/hepto/hepto/pkg/wg" "github.com/sirupsen/logrus" @@ -12,10 +13,11 @@ import ( type Cluster struct { settings *ClusterSettings - ml *sml.Memberlist + ml *sml.Memberlist[HeptoMeta] vpn *wg.Wireguard networking *ClusterNetworking node *NodeSettings + certs *NodeCerts pki *ClusterPKI } @@ -26,14 +28,14 @@ func New(settings *ClusterSettings, node *NodeSettings) (*Cluster, error) { networking: NewClusterNetworking(settings.Name, node.Name), } // Prepare memberlist - c.ml = sml.New(node.Name, node.IP, node.Port, node.Anchors.IPSlice(), settings.Key, newMeta) + c.ml = sml.New(node.Name, node.IP, node.Port, node.Anchors, settings.Key, HeptoMeta{}) // Prepare wireguard vpn, err := wg.New("wg0", 7124, c.networking.NodeAddress.IPNet()) if err != nil { return nil, err } c.vpn = vpn - // Initialize cluster PKI if necessary + // Initialize cluster PKI and local keys if node.Role == "master" { pki, err := NewClusterPKI("pki") if err != nil { @@ -41,9 +43,17 @@ func New(settings *ClusterSettings, node *NodeSettings) (*Cluster, error) { } c.pki = pki } + certs, err := NewNodeCerts("certs", node.Name) + if err != nil { + return nil, err + } + c.certs = certs // Initialize cluster meta - meta := c.ml.Meta.(*HeptoMeta) + meta := c.ml.Meta meta.VpnKey = vpn.PubKey.String() + meta.Role = node.Role + meta.Certs = make(map[string]NodePKIBytes) + meta.CSR.APIClient = certs.APIClient.CSR return c, nil } @@ -59,6 +69,7 @@ func (c *Cluster) Run() error { for { select { case <-events: + c.handlePKI() c.updateVPN() case <-instrUpdates: c.networking.MTU = instr.MinMTU() @@ -67,13 +78,56 @@ func (c *Cluster) Run() error { } } +func (c *Cluster) handlePKI() { + logrus.Debug("handling possible PKI messages") + for _, node := range c.ml.Nodes() { + meta := node.NodeMeta + if meta.Role == "master" { + logrus.Debug("found master node, checking certs") + logrus.Debug(string(node.Meta)) + if certs, ok := meta.Certs[c.node.Name]; ok { + if len(certs.APIClient) > 0 { + logrus.Debug("certificate is signed") + err := c.certs.APIClient.SetCert(certs.APIClient) + if err != nil { + logrus.Warn("cannot load certificate") + } + } + } + } + } + if c.pki != nil { + logrus.Debug("this is the master, generating required certificates") + for _, node := range c.ml.Nodes() { + meta := node.NodeMeta + if len(meta.CSR.APIClient) > 0 { + template := pki.NewClientTemplate(node.Name, "") + cert, err := c.pki.APIServer.Sign(meta.CSR.APIClient, template) + if err != nil { + logrus.Warn("cannot sign certificate") + continue + } + logrus.Debug("signed for ", node.Name, cert) + this := c.ml.Meta + var certs NodePKIBytes + if certs, ok := this.Certs[node.Name]; !ok { + this.Certs[node.Name] = certs + } + certs.APIClient = cert + this.Certs[node.Name] = certs + c.ml.Update() + } + } + } +} + func (c *Cluster) updateVPN() { peers := []wg.Peer{} for _, node := range c.ml.Nodes() { if node.Name == c.node.Name { continue } - meta := node.NodeMeta.(*HeptoMeta) + meta := node.NodeMeta peerAddr := c.networking.NodeNet.DeriveAddress(node.Name).IP peer, err := c.vpn.MakePeer(node.Addr, meta.VpnKey, peerAddr, []net.IPNet{}) if err != nil { diff --git a/pkg/cluster/config.go b/pkg/cluster/config.go index 3850cad..a7e5332 100644 --- a/pkg/cluster/config.go +++ b/pkg/cluster/config.go @@ -23,7 +23,7 @@ type NodeSettings struct { // Public IPv6 address for the node IP net.IP // Anchors for this node to join - Anchors types.AddressSlice + Anchors []string } type ClusterNetworking struct { diff --git a/pkg/cluster/meta.go b/pkg/cluster/meta.go index 69b97a9..d12bfa6 100644 --- a/pkg/cluster/meta.go +++ b/pkg/cluster/meta.go @@ -6,18 +6,34 @@ import ( "forge.tedomum.net/acides/hepto/hepto/pkg/sml" ) +// Represents a node CSRs and returned certs +type NodePKIBytes struct { + // APIclient certificate + APIClient []byte `json:"apiclient"` +} + // Represents a node metadata type HeptoMeta struct { // Public key for the wireguard mesh VPN VpnKey string `json:"vpnKey"` + // Node role inside the cluster + Role string `json:"role"` + // Certificate CSRs + CSR NodePKIBytes `json:"csr"` + // Only on master, signed certificates + Certs map[string]NodePKIBytes `json:"certs"` +} + +func (m HeptoMeta) Encode() ([]byte, error) { + return json.Marshal(&m) } -func (m *HeptoMeta) Encode() ([]byte, error) { - return json.Marshal(m) +func (m HeptoMeta) Decode(b []byte) error { + return json.Unmarshal(b, &m) } -func (m *HeptoMeta) Decode(b []byte) error { - return json.Unmarshal(b, m) +func (m HeptoMeta) String() string { + return m.Role } func newMeta() sml.NodeMeta { diff --git a/pkg/cluster/pki.go b/pkg/cluster/pki.go index 795d842..b4988c8 100644 --- a/pkg/cluster/pki.go +++ b/pkg/cluster/pki.go @@ -1,6 +1,7 @@ package cluster import ( + "os" "path/filepath" "forge.tedomum.net/acides/hepto/hepto/pkg/pki" @@ -13,6 +14,10 @@ type ClusterPKI struct { } func NewClusterPKI(path string) (*ClusterPKI, error) { + err := os.MkdirAll(path, 0755) + if err != nil { + return nil, err + } servicesCA, err := pki.GetCA(filepath.Join(path, "services")) if err != nil { return nil, err @@ -27,3 +32,21 @@ func NewClusterPKI(path string) (*ClusterPKI, error) { } return &ClusterPKI{servicesCA, kubeletCA, apiserverCA}, nil } + +type NodeCerts struct { + APIClient *pki.CertKey +} + +func NewNodeCerts(path string, nodeName string) (*NodeCerts, error) { + err := os.MkdirAll(path, 0755) + if err != nil { + return nil, err + } + apiClientCert, err := pki.LoadWithCSR(filepath.Join(path, "apiclient"), pki.NewClientTemplate(nodeName, "")) + if err != nil { + return nil, err + } + return &NodeCerts{ + APIClient: apiClientCert, + }, nil +} diff --git a/pkg/pki/cert.go b/pkg/pki/cert.go new file mode 100644 index 0000000..c39f238 --- /dev/null +++ b/pkg/pki/cert.go @@ -0,0 +1,121 @@ +package pki + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" +) + +const KEY_EXT = ".key" +const CERT_EXT = ".pem" + +// Certificate (request) and associated keypair +// Only supports ECDSA certificates for sign and auth +type CertKey struct { + Key *ecdsa.PrivateKey + keyPath string + Cert *x509.Certificate + certPath string + CSR []byte +} + +// Get a cert signer +func (c *CertKey) Signer() crypto.Signer { + return c.Key +} + +// Load and generate a CSR if necessary +func LoadWithCSR(path string, template *x509.Certificate) (*CertKey, error) { + ck, err := loadOrGenerateKey(path) + if err != nil { + return nil, err + } + // Generate a fresh CSR if required + if ck.Cert == nil { + csrTemplate := &x509.CertificateRequest{ + SignatureAlgorithm: template.SignatureAlgorithm, + Subject: template.Subject, + DNSNames: template.DNSNames, + EmailAddresses: template.EmailAddresses, + IPAddresses: template.IPAddresses, + URIs: template.URIs, + ExtraExtensions: template.ExtraExtensions, + } + csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, ck.Signer()) + if err != nil { + return nil, err + } + ck.CSR = csr + } + return ck, nil +} + +// Load and generate a self-signed cert if necessary (for CA mostly) +func LoadSelfSigned(path string, template *x509.Certificate) (*CertKey, error) { + ck, err := loadOrGenerateKey(path) + if err != nil { + return nil, err + } + // Self-sign a certificate if required + if ck.Cert == nil { + signer := ck.Signer() + certBytes, err := x509.CreateCertificate(rand.Reader, template, template, signer.Public(), signer) + if err != nil { + return nil, err + } + err = ck.SetCert(certBytes) + if err != nil { + return nil, err + } + } + return ck, nil +} + +// Parse and save a certificate +func (ck *CertKey) SetCert(certBytes []byte) error { + cert, err := x509.ParseCertificate(certBytes) + if err != nil { + return err + } + err = SaveCert(ck.certPath, cert) + if err != nil { + return err + } + ck.Cert = cert + return nil +} + +// Load a CertKey, generate the key if necessary +func loadOrGenerateKey(path string) (*CertKey, error) { + keyPath := path + KEY_EXT + certPath := path + CERT_EXT + // Try to load the certificate first, so we do not create a key if + // this raises an error + cert, err := LoadCert(certPath) + if err != nil { + return nil, err + } + key, err := LoadKey(keyPath) + if err != nil { + return nil, err + } + // Create the key if necessary + if key == nil { + key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, err + } + err = SaveKey(keyPath, key) + if err != nil { + return nil, err + } + } + return &CertKey{ + Key: key, + keyPath: keyPath, + Cert: cert, + certPath: certPath, + }, nil +} diff --git a/pkg/pki/pki.go b/pkg/pki/pki.go index 5a1b002..c76aa4c 100644 --- a/pkg/pki/pki.go +++ b/pkg/pki/pki.go @@ -1,45 +1,21 @@ package pki import ( - "crypto" - "crypto/ecdsa" - "crypto/elliptic" "crypto/rand" "crypto/x509" - "os" - "path/filepath" ) -const CA_NAME = "_ca" -const KEY_EXT = ".key" -const CERT_EXT = ".pem" - type CA struct { - path string - signer crypto.Signer - cert *x509.Certificate + certKey *CertKey } func GetCA(path string) (*CA, error) { - err := os.MkdirAll(path, 0755) - if err != nil { - return nil, err - } - - signer, err := getSigner(filepath.Join(path, CA_NAME+KEY_EXT)) + ck, err := LoadSelfSigned(path, NewCATemplate()) if err != nil { return nil, err } - - cert, err := getCaCert(signer, filepath.Join(path, CA_NAME+CERT_EXT)) - if err != nil { - return nil, err - } - return &CA{ - path: path, - signer: signer, - cert: cert, + certKey: ck, }, nil } @@ -58,48 +34,5 @@ func (c *CA) Sign(csrBytes []byte, template *x509.Certificate) ([]byte, error) { template.PublicKey = csr.PublicKey template.PublicKeyAlgorithm = csr.PublicKeyAlgorithm // Actually sign the certificate - return x509.CreateCertificate(rand.Reader, template, c.cert, template.PublicKey, c.signer) -} - -func getSigner(path string) (crypto.Signer, error) { - key, err := LoadKey(path) - if err != nil { - return nil, err - } - // Create the key if necessary - if key == nil { - key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return nil, err - } - err = SaveKey(path, key) - if err != nil { - return nil, err - } - } - return key, nil -} - -func getCaCert(signer crypto.Signer, path string) (*x509.Certificate, error) { - cert, err := LoadCert(path) - if err != nil { - return nil, err - } - // Self-sign a certificate if required - if cert == nil { - template := NewCATemplate() - certBytes, err := x509.CreateCertificate(rand.Reader, template, template, signer.Public(), signer) - if err != nil { - return nil, err - } - cert, err = x509.ParseCertificate(certBytes) - if err != nil { - return nil, err - } - err = SaveCert(path, cert) - if err != nil { - return nil, err - } - } - return cert, nil + return x509.CreateCertificate(rand.Reader, template, c.certKey.Cert, template.PublicKey, c.certKey.Signer()) } diff --git a/pkg/selfcontain/container.go b/pkg/selfcontain/container.go index a92deb6..e4bf4e3 100644 --- a/pkg/selfcontain/container.go +++ b/pkg/selfcontain/container.go @@ -45,7 +45,7 @@ func New(name string, dataPath string, newRoot string, newArgs []string) (*Conta factoryConfig := func(f *libcontainer.LinuxFactory) error { f.InitPath = self f.InitArgs = []string{os.Args[0], argInit} - return libcontainer.Cgroupfs(f) + return nil } factory, err := libcontainer.New(dataPath, factoryConfig) if err != nil { diff --git a/pkg/sml/delegate.go b/pkg/sml/delegate.go index 78e1c0a..6120bba 100644 --- a/pkg/sml/delegate.go +++ b/pkg/sml/delegate.go @@ -6,11 +6,11 @@ import ( ) // Cluster implements the memberlist.Delegate interface -func (m *Memberlist) NotifyConflict(node, other *memberlist.Node) { +func (m *Memberlist[M, MP]) NotifyConflict(node, other *memberlist.Node) { } // Cluter implements the memberlist.Delegate interface -func (m *Memberlist) NodeMeta(limit int) []byte { +func (m *Memberlist[M, MP]) NodeMeta(limit int) []byte { n, err := m.Meta.Encode() if err != nil { logrus.Warn("could not encode node metadata") @@ -20,35 +20,35 @@ func (m *Memberlist) NodeMeta(limit int) []byte { } // Clutser implements the memberlist.Delegate interface -func (m *Memberlist) NotifyMsg([]byte) { +func (m *Memberlist[M, MP]) NotifyMsg([]byte) { } // Cluster implements the memberlist.Delegate interface -func (m *Memberlist) GetBroadcasts(overhead, limit int) [][]byte { +func (m *Memberlist[M, MP]) GetBroadcasts(overhead, limit int) [][]byte { return nil } // Cluster implements the memberlist.Delegate interface -func (m *Memberlist) LocalState(join bool) []byte { +func (m *Memberlist[M, MP]) LocalState(join bool) []byte { return nil } // Clutser implements the memberlist.Delegate interface -func (m *Memberlist) MergeRemoteState(buf []byte, join bool) { +func (m *Memberlist[M, MP]) MergeRemoteState(buf []byte, join bool) { } // Cluster implements the EventDelegate interface -func (m *Memberlist) NotifyJoin(n *memberlist.Node) { +func (m *Memberlist[M, MP]) NotifyJoin(n *memberlist.Node) { logrus.Debug("node joined: ", n.Name) go m.updateCache() } // Node implements the EventDelegate interface -func (m *Memberlist) NotifyLeave(n *memberlist.Node) { +func (m *Memberlist[M, MP]) NotifyLeave(n *memberlist.Node) { go m.updateCache() } // Node implements the EventDelegate interface -func (m *Memberlist) NotifyUpdate(n *memberlist.Node) { +func (m *Memberlist[M, MP]) NotifyUpdate(n *memberlist.Node) { go m.updateCache() } diff --git a/pkg/sml/memberlist.go b/pkg/sml/memberlist.go index 7dd5da4..6d15580 100644 --- a/pkg/sml/memberlist.go +++ b/pkg/sml/memberlist.go @@ -13,23 +13,21 @@ import ( "github.com/sirupsen/logrus" ) -type Memberlist struct { - Meta NodeMeta - +type Memberlist[M any, MP MetaPointer[M]] struct { + Meta MP name string nodeName string - anchors []net.IP + anchors []string key []byte config *memberlist.Config ml *memberlist.Memberlist - newMeta func() NodeMeta - nodeCache []Node + nodeCache []Node[M, MP] nodeChanges chan struct{} chans []chan struct{} transport *instrumentedTransport } -func New(nodeName string, nodeIP net.IP, port int, anchors []net.IP, key []byte, newMeta func() NodeMeta) *Memberlist { +func New[M any, MP MetaPointer[M]](nodeName string, nodeIP net.IP, port int, anchors []string, key []byte, meta MP) *Memberlist[M, MP] { config := memberlist.DefaultLANConfig() config.LogOutput = logrus.StandardLogger().WriterLevel(logrus.DebugLevel) config.SecretKey = key @@ -40,14 +38,13 @@ func New(nodeName string, nodeIP net.IP, port int, anchors []net.IP, key []byte, config.Name = nodeName config.SecretKey = key - m := &Memberlist{ + m := &Memberlist[M, MP]{ nodeName: nodeName, nodeChanges: make(chan struct{}, 100), anchors: anchors, key: key, config: config, - newMeta: newMeta, - Meta: newMeta(), + Meta: meta, } // Memberlist is its own memberlist delegate implementation @@ -59,7 +56,7 @@ func New(nodeName string, nodeIP net.IP, port int, anchors []net.IP, key []byte, } // Start the memberlist cluster by listening on main sockets -func (m *Memberlist) Start() error { +func (m *Memberlist[M, MP]) Start() error { logrus.Info("starting the cluster transport") tc := &memberlist.NetTransportConfig{ BindAddrs: []string{m.config.BindAddr}, @@ -82,7 +79,7 @@ func (m *Memberlist) Start() error { // Run the memberlist cluster main loop, that awaits cluster changes, maintains // the cluster state and propagates information to channels -func (m *Memberlist) Run() error { +func (m *Memberlist[M, MP]) Run() error { ticker := time.Tick(10 * time.Second) for { select { @@ -91,7 +88,7 @@ func (m *Memberlist) Run() error { case <-m.nodeChanges: logrus.Debug("network topology changed, a node just joined, left or was updated") for _, node := range m.Nodes() { - logrus.Debugf("* %s: %s ; %v\n", node.Name, string(node.Meta), node.NodeMeta) + logrus.Debugf("* %s [%s]\n", node.Name, node.NodeMeta.String()) } for _, c := range m.chans { c <- struct{}{} @@ -101,7 +98,7 @@ func (m *Memberlist) Run() error { } // Get a channel for notifications of network changes -func (m *Memberlist) Events() <-chan struct{} { +func (m *Memberlist[M, MP]) Events() <-chan struct{} { // Buffer to avoid blocking later // TODO: be more organized about channels we deliver c := make(chan struct{}, 100) @@ -110,24 +107,24 @@ func (m *Memberlist) Events() <-chan struct{} { } // Get the list of current cluster nodes -func (m *Memberlist) Nodes() []Node { +func (m *Memberlist[M, MP]) Nodes() []Node[M, MP] { return m.nodeCache } // Get the instrumentation interface -func (m *Memberlist) Instr() Instrumentation { +func (m *Memberlist[M, MP]) Instr() Instrumentation { return m.transport } -// Build a local node representation from an upstream memberlist node, using -// empty metadata (before decoding) -func (m *Memberlist) newNode(mlNode *memberlist.Node) Node { - return Node{mlNode, m.newMeta()} +// Update the current node +func (m *Memberlist[M, MP]) Update() { + logrus.Debug("updating the memberlist cluster") + m.ml.UpdateNode(1 * time.Second) } // Update the node cache after a network change, goes through all the // nodes and decodes metadata -func (m *Memberlist) updateCache() { +func (m *Memberlist[M, MP]) updateCache() { // Do not update the node cache until memberlist is setup if m.ml == nil { logrus.Debug("not updating the node cache before memberlist is ready") @@ -135,22 +132,29 @@ func (m *Memberlist) updateCache() { } members := m.ml.Members() logrus.Debugf("updating the node cache with %d members", len(members)) - cache := make([]Node, len(members)) - for i, mlNode := range members { - cache[i] = m.newNode(mlNode) - cache[i].Decode() + var cache []Node[M, MP] + for _, mlNode := range members { + meta := new(M) + pointer := MP(meta) + err := pointer.Decode(mlNode.Meta) + if err == nil { + cache = append(cache, Node[M, MP]{mlNode, pointer}) + } else { + logrus.Warnf("could not decode meta for node %s", mlNode.Name) + } } m.nodeCache = cache m.nodeChanges <- struct{}{} } // Try and join any anchor that is not currently a cluster member -func (m *Memberlist) join() error { +func (m *Memberlist[M, MP]) join() error { addrs := []string{} + members := m.ml.Members() for _, candidate := range m.anchors { found := false - for _, node := range m.ml.Members() { - if node.Addr.Equal(candidate) { + for _, node := range members { + if node.Address() == candidate { found = true break } @@ -158,7 +162,7 @@ func (m *Memberlist) join() error { if found { continue } - addrs = append(addrs, candidate.String()) + addrs = append(addrs, candidate) } if len(addrs) > 0 { logrus.Info("joining cluster nodes: ", addrs) diff --git a/pkg/sml/node.go b/pkg/sml/node.go index defa243..9b5c20c 100644 --- a/pkg/sml/node.go +++ b/pkg/sml/node.go @@ -4,27 +4,32 @@ import ( "github.com/hashicorp/memberlist" ) -// Node meta can be encoded and decoded to bytes, required +// Cluster data can be encoded and decoded to bytes, required // by Memberlist wire protocol -type NodeMeta interface { +type ClusterData interface { Encode() ([]byte, error) Decode([]byte) error + String() string } -// Represents a full node for easy browsing -type Node struct { - *memberlist.Node - NodeMeta NodeMeta +type NodeMeta interface { + ClusterData } -func (n *Node) Encode() (*memberlist.Node, error) { - node := n.Node - b, err := n.NodeMeta.Encode() - node.Meta = b - return node, err +// Node meta is plain node data, manipulated as a pointer +type MetaPointer[M any] interface { + NodeMeta + *M } -// Decode a raw node -func (n *Node) Decode() error { - return n.NodeMeta.Decode(n.Meta) +// Cluster state is node data that can be merged, crdt-style +type NodeState interface { + ClusterData + Merge(*ClusterData) error +} + +// Represents a full node for easy browsing +type Node[M any, MP MetaPointer[M]] struct { + *memberlist.Node + NodeMeta MP } diff --git a/test.go b/test.go new file mode 100644 index 0000000..38c12d9 --- /dev/null +++ b/test.go @@ -0,0 +1,42 @@ +package main + +import ( + "net" + "os" + "strconv" + + "forge.tedomum.net/acides/hepto/hepto/pkg/sml" + "github.com/sirupsen/logrus" +) + +type Meta struct { + name string +} + +func (m *Meta) Encode() ([]byte, error) { + logrus.Debug("encoding node meta ", m.name) + return []byte(m.name), nil +} + +func (m *Meta) Decode(b []byte) error { + logrus.Debug("decoding node meta ", b) + m.name = string(b) + logrus.Debug("decoded node meta ", m.name) + return nil +} + +func (m *Meta) String() string { + logrus.Debug("debugging node meta ", m.name) + return m.name +} + +func main() { + logrus.SetLevel(logrus.DebugLevel) + ip := net.ParseIP(os.Args[2]) + logrus.Info(ip) + port, _ := strconv.Atoi(os.Args[3]) + meta := Meta{name: os.Args[1]} + m := sml.New(os.Args[1], ip, port, os.Args[4:], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, &meta) + logrus.Error(m.Start()) + logrus.Error(m.Run()) +} -- GitLab