From 433c8f4957d7bf297113c4d99f85fc1bcfe514e5 Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Wed, 21 Aug 2024 14:11:06 +1100 Subject: [PATCH 1/6] Add an ability to choose IPAM policy for NSE Signed-off-by: NikitaSkrynnik --- main.go | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index f535553..31ca514 100644 --- a/main.go +++ b/main.go @@ -29,10 +29,12 @@ import ( "context" "crypto/tls" "fmt" + "net" "net/url" "os" "os/signal" "path/filepath" + "strings" "sync/atomic" "syscall" "time" @@ -65,6 +67,8 @@ import ( "github.com/networkservicemesh/sdk/pkg/networkservice/common/policyroute" "github.com/networkservicemesh/sdk/pkg/networkservice/connectioncontext/dnscontext" "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/groupipam" + "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/point2pointipam" + "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/strictipam" registryclient "github.com/networkservicemesh/sdk/pkg/registry/chains/client" registryauthorize "github.com/networkservicemesh/sdk/pkg/registry/common/authorize" "github.com/networkservicemesh/sdk/pkg/registry/common/clientinfo" @@ -90,6 +94,7 @@ type Config struct { ConnectTo url.URL `default:"unix:///var/lib/networkservicemesh/nsm.io.sock" desc:"url to connect to" split_words:"true"` MaxTokenLifetime time.Duration `default:"10m" desc:"maximum lifetime of tokens" split_words:"true"` RegistryClientPolicies []string `default:"etc/nsm/opa/common/.*.rego,etc/nsm/opa/registry/.*.rego,etc/nsm/opa/client/.*.rego" desc:"paths to files and directories that contain registry client policies" split_words:"true"` + IPAMPolicy IPAMPolicy `default:"default" desc:"defines NSE's IPAM Policy. Possible values: default, strict" split_words:"true"` ServiceNames []string `default:"icmp-responder" desc:"Name of provided services" split_words:"true"` Payload string `default:"ETHERNET" desc:"Name of provided service payload" split_words:"true"` Labels map[string]string `default:"" desc:"Endpoint labels"` @@ -106,6 +111,29 @@ type Config struct { PprofListenOn string `default:"localhost:6060" desc:"pprof URL to ListenAndServe" split_words:"true"` } +type IPAMPolicy uint8 + +// Decode takes a string IPAM Policy and returns the IPAM Policy constant. +func (p *IPAMPolicy) Decode(policy string) error { + switch strings.ToLower(policy) { + case "strict": + *p = StrictIPAMPolicy + return nil + case "default": + *p = DefaultIPAMPolicy + return nil + } + return errors.Errorf("not a valid IPAM Policy: %s", policy) +} + +const ( + // DefaultIPAMPolicy - uses the default point2point IPAM without any policies. + DefaultIPAMPolicy IPAMPolicy = iota + // StrictIPAMPolicy - uses a strictipam wrapper for the default point2point IPAM that + // resets connetion's ip_context if any of the addresses are invalid. + StrictIPAMPolicy +) + // Process prints and processes env to config func (c *Config) Process() error { if err := envconfig.Usage("nsm", c); err != nil { @@ -217,13 +245,19 @@ func main() { tokenServer := getSriovTokenServerChainElement(ctx) + ipamFunc := point2pointipam.NewServer + if config.IPAMPolicy == StrictIPAMPolicy { + ipamFunc = func(prefixes ...*net.IPNet) networkservice.NetworkServiceServer { + return strictipam.NewServer(point2pointipam.NewServer, prefixes...) + } + } responderEndpoint := endpoint.NewServer(ctx, spiffejwt.TokenGeneratorFunc(source, config.MaxTokenLifetime), endpoint.WithName(config.Name), endpoint.WithAuthorizeServer(authorize.NewServer()), endpoint.WithAdditionalFunctionality( onidle.NewServer(ctx, cancel, config.IdleTimeout), - groupipam.NewServer(config.CidrPrefix), + groupipam.NewServer(config.CidrPrefix, groupipam.WithCustomIPAMServer(ipamFunc)), policyroute.NewServer(newPolicyRoutesGetter(ctx, config.PBRConfigPath).Get), mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{ kernelmech.MECHANISM: kernel.NewServer(), From 47ad2d01998fbdbc6377dd534003c74dbf53c991 Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Wed, 21 Aug 2024 14:16:32 +1100 Subject: [PATCH 2/6] fix CI issues Signed-off-by: NikitaSkrynnik --- go.mod | 4 ++-- go.sum | 8 ++++---- internal/pkg/imports/imports_linux.go | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 447d478..9ef246b 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( github.com/edwarnicke/grpcfd v1.1.4 github.com/kelseyhightower/envconfig v1.4.0 github.com/networkservicemesh/api v1.13.4-0.20240815101554-fdbfcd84fd0e - github.com/networkservicemesh/sdk v0.5.1-0.20240819093036-ae25bb43f39a - github.com/networkservicemesh/sdk-sriov v0.0.0-20240819093621-8447a4a3f199 + github.com/networkservicemesh/sdk v0.5.1-0.20240820090035-6fad31a9f0aa + github.com/networkservicemesh/sdk-sriov v0.0.0-20240117141758-43f62c9df101 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.0 github.com/spiffe/go-spiffe/v2 v2.1.7 diff --git a/go.sum b/go.sum index 10407c4..f8d9890 100644 --- a/go.sum +++ b/go.sum @@ -105,10 +105,10 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/networkservicemesh/api v1.13.4-0.20240815101554-fdbfcd84fd0e h1:Fs34ZZN+bujq5OQEQUpxm0gYQ3g7uSCkcKcoUt70Be0= github.com/networkservicemesh/api v1.13.4-0.20240815101554-fdbfcd84fd0e/go.mod h1:B8FmS3XZ7NZY7ZEtdcNg2NHYppDHlr4kl4eecdZN9eI= -github.com/networkservicemesh/sdk v0.5.1-0.20240819093036-ae25bb43f39a h1:yGa3JaE4yLKzKTefxu/5sT7ESFmIxj2Ai0VnxvQ69co= -github.com/networkservicemesh/sdk v0.5.1-0.20240819093036-ae25bb43f39a/go.mod h1:nz2VJ3l/UDvsEusdIZf7OMxC7zLrRCV1PuziPjxJeVE= -github.com/networkservicemesh/sdk-sriov v0.0.0-20240819093621-8447a4a3f199 h1:wUo1fWJAZ5RkW0FaZ1DekwOKKCe6zhjJrBcQdGGfUBw= -github.com/networkservicemesh/sdk-sriov v0.0.0-20240819093621-8447a4a3f199/go.mod h1:pMxDdhmCcfwQFrtcljU5CmSFyrCMsbAlH6dZjb5BjGU= +github.com/networkservicemesh/sdk v0.5.1-0.20240820090035-6fad31a9f0aa h1:+/bYBzySJJLgnCSjR8SLHsA+r6PYmAusUbka/W/bw5w= +github.com/networkservicemesh/sdk v0.5.1-0.20240820090035-6fad31a9f0aa/go.mod h1:nz2VJ3l/UDvsEusdIZf7OMxC7zLrRCV1PuziPjxJeVE= +github.com/networkservicemesh/sdk-sriov v0.0.0-20240117141758-43f62c9df101 h1:W5+jo/V7S24ll+GYyE6H+3pegDGyH1UYIAwRdbFRlq0= +github.com/networkservicemesh/sdk-sriov v0.0.0-20240117141758-43f62c9df101/go.mod h1:Pc/BcobqUlQ6XhiirKc4d5biBLL8+BF2TAAFsjZWRXA= github.com/open-policy-agent/opa v0.44.0 h1:sEZthsrWBqIN+ShTMJ0Hcz6a3GkYsY4FaB2S/ou2hZk= github.com/open-policy-agent/opa v0.44.0/go.mod h1:YpJaFIk5pq89n/k72c1lVvfvR5uopdJft2tMg1CW/yU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/internal/pkg/imports/imports_linux.go b/internal/pkg/imports/imports_linux.go index 2151d0b..1c9204c 100644 --- a/internal/pkg/imports/imports_linux.go +++ b/internal/pkg/imports/imports_linux.go @@ -25,6 +25,8 @@ import ( _ "github.com/networkservicemesh/sdk/pkg/networkservice/common/policyroute" _ "github.com/networkservicemesh/sdk/pkg/networkservice/connectioncontext/dnscontext" _ "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/groupipam" + _ "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/point2pointipam" + _ "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/strictipam" _ "github.com/networkservicemesh/sdk/pkg/registry/chains/client" _ "github.com/networkservicemesh/sdk/pkg/registry/common/authorize" _ "github.com/networkservicemesh/sdk/pkg/registry/common/begin" @@ -64,10 +66,12 @@ import ( _ "google.golang.org/grpc/credentials" _ "google.golang.org/grpc/health/grpc_health_v1" _ "gopkg.in/yaml.v2" + _ "net" _ "net/url" _ "os" _ "os/signal" _ "path/filepath" + _ "strings" _ "sync/atomic" _ "syscall" _ "testing" From 336881c0d5fefd8af63eb406262c69735081c777 Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Wed, 21 Aug 2024 14:20:30 +1100 Subject: [PATCH 3/6] fix go linter issues Signed-off-by: NikitaSkrynnik --- .golangci.yml | 2 +- main.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 4b047d1..f5746a1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -37,7 +37,7 @@ linters-settings: threshold: 150 funlen: Lines: 175 - Statements: 85 + Statements: 90 goconst: min-len: 2 min-occurrences: 2 diff --git a/main.go b/main.go index 31ca514..581d70c 100644 --- a/main.go +++ b/main.go @@ -94,7 +94,7 @@ type Config struct { ConnectTo url.URL `default:"unix:///var/lib/networkservicemesh/nsm.io.sock" desc:"url to connect to" split_words:"true"` MaxTokenLifetime time.Duration `default:"10m" desc:"maximum lifetime of tokens" split_words:"true"` RegistryClientPolicies []string `default:"etc/nsm/opa/common/.*.rego,etc/nsm/opa/registry/.*.rego,etc/nsm/opa/client/.*.rego" desc:"paths to files and directories that contain registry client policies" split_words:"true"` - IPAMPolicy IPAMPolicy `default:"default" desc:"defines NSE's IPAM Policy. Possible values: default, strict" split_words:"true"` + IPAMPolicy ipamPolicy `default:"default" desc:"defines NSE's IPAM Policy. Possible values: default, strict" split_words:"true"` ServiceNames []string `default:"icmp-responder" desc:"Name of provided services" split_words:"true"` Payload string `default:"ETHERNET" desc:"Name of provided service payload" split_words:"true"` Labels map[string]string `default:"" desc:"Endpoint labels"` @@ -111,16 +111,16 @@ type Config struct { PprofListenOn string `default:"localhost:6060" desc:"pprof URL to ListenAndServe" split_words:"true"` } -type IPAMPolicy uint8 +type ipamPolicy uint8 // Decode takes a string IPAM Policy and returns the IPAM Policy constant. -func (p *IPAMPolicy) Decode(policy string) error { +func (p *ipamPolicy) Decode(policy string) error { switch strings.ToLower(policy) { case "strict": - *p = StrictIPAMPolicy + *p = strictIPAMPolicy return nil case "default": - *p = DefaultIPAMPolicy + *p = defaultIPAMPolicy return nil } return errors.Errorf("not a valid IPAM Policy: %s", policy) @@ -128,10 +128,10 @@ func (p *IPAMPolicy) Decode(policy string) error { const ( // DefaultIPAMPolicy - uses the default point2point IPAM without any policies. - DefaultIPAMPolicy IPAMPolicy = iota + defaultIPAMPolicy ipamPolicy = iota // StrictIPAMPolicy - uses a strictipam wrapper for the default point2point IPAM that // resets connetion's ip_context if any of the addresses are invalid. - StrictIPAMPolicy + strictIPAMPolicy ) // Process prints and processes env to config @@ -246,7 +246,7 @@ func main() { tokenServer := getSriovTokenServerChainElement(ctx) ipamFunc := point2pointipam.NewServer - if config.IPAMPolicy == StrictIPAMPolicy { + if config.IPAMPolicy == strictIPAMPolicy { ipamFunc = func(prefixes ...*net.IPNet) networkservice.NetworkServiceServer { return strictipam.NewServer(point2pointipam.NewServer, prefixes...) } From f240ce30d9c45e048a3bba2b827fc51dad603d8b Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Wed, 21 Aug 2024 14:31:20 +1100 Subject: [PATCH 4/6] add a new config variable to README file Signed-off-by: NikitaSkrynnik --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5c3560d..81c80f1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ docker build . * `NSM_CONNECT_TO` - url to connect to (default: "unix:///var/lib/networkservicemesh/nsm.io.sock") * `NSM_MAX_TOKEN_LIFETIME` - maximum lifetime of tokens (default: "10m") * `NSM_REGISTRY_CLIENT_POLICIES` - paths to files and directories that contain registry client policies (default: "etc/nsm/opa/common/.*.rego,etc/nsm/opa/registry/.*.rego,etc/nsm/opa/client/.*.rego") +* `NSM_IPAM_POLICY` - defines NSE's IPAM Policy. Possible values: default, strict * `NSM_SERVICE_NAMES` - Name of provided services (default: "icmp-responder") * `NSM_PAYLOAD` - Name of provided service payload (default: "ETHERNET") * `NSM_LABELS` - Endpoint labels From 9fe4a3f6eb39aa745bc2e78f7f42fb45b17e1610 Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Tue, 27 Aug 2024 13:55:08 +1100 Subject: [PATCH 5/6] apply review comments Signed-off-by: NikitaSkrynnik --- main.go | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/main.go b/main.go index 581d70c..33e79e1 100644 --- a/main.go +++ b/main.go @@ -94,7 +94,7 @@ type Config struct { ConnectTo url.URL `default:"unix:///var/lib/networkservicemesh/nsm.io.sock" desc:"url to connect to" split_words:"true"` MaxTokenLifetime time.Duration `default:"10m" desc:"maximum lifetime of tokens" split_words:"true"` RegistryClientPolicies []string `default:"etc/nsm/opa/common/.*.rego,etc/nsm/opa/registry/.*.rego,etc/nsm/opa/client/.*.rego" desc:"paths to files and directories that contain registry client policies" split_words:"true"` - IPAMPolicy ipamPolicy `default:"default" desc:"defines NSE's IPAM Policy. Possible values: default, strict" split_words:"true"` + IPAMPolicy ipamPolicyFunc `default:"polite" desc:"defines NSE's IPAM Policy. Possible values: polite, strict. Polite policy accepts any addresses sent by client. Strict policy resets ip_context if any of the client's addresses doesn't match endpoint's CIDR." split_words:"true"` ServiceNames []string `default:"icmp-responder" desc:"Name of provided services" split_words:"true"` Payload string `default:"ETHERNET" desc:"Name of provided service payload" split_words:"true"` Labels map[string]string `default:"" desc:"Endpoint labels"` @@ -111,29 +111,23 @@ type Config struct { PprofListenOn string `default:"localhost:6060" desc:"pprof URL to ListenAndServe" split_words:"true"` } -type ipamPolicy uint8 +type ipamPolicyFunc func(...*net.IPNet) networkservice.NetworkServiceServer -// Decode takes a string IPAM Policy and returns the IPAM Policy constant. -func (p *ipamPolicy) Decode(policy string) error { +// Decode takes a string IPAM Policy and returns the IPAM Policy func +func (f *ipamPolicyFunc) Decode(policy string) error { switch strings.ToLower(policy) { case "strict": - *p = strictIPAMPolicy + *f = func(prefixes ...*net.IPNet) networkservice.NetworkServiceServer { + return strictipam.NewServer(point2pointipam.NewServer, prefixes...) + } return nil - case "default": - *p = defaultIPAMPolicy + case "polite": + *f = point2pointipam.NewServer return nil } return errors.Errorf("not a valid IPAM Policy: %s", policy) } -const ( - // DefaultIPAMPolicy - uses the default point2point IPAM without any policies. - defaultIPAMPolicy ipamPolicy = iota - // StrictIPAMPolicy - uses a strictipam wrapper for the default point2point IPAM that - // resets connetion's ip_context if any of the addresses are invalid. - strictIPAMPolicy -) - // Process prints and processes env to config func (c *Config) Process() error { if err := envconfig.Usage("nsm", c); err != nil { @@ -245,19 +239,13 @@ func main() { tokenServer := getSriovTokenServerChainElement(ctx) - ipamFunc := point2pointipam.NewServer - if config.IPAMPolicy == strictIPAMPolicy { - ipamFunc = func(prefixes ...*net.IPNet) networkservice.NetworkServiceServer { - return strictipam.NewServer(point2pointipam.NewServer, prefixes...) - } - } responderEndpoint := endpoint.NewServer(ctx, spiffejwt.TokenGeneratorFunc(source, config.MaxTokenLifetime), endpoint.WithName(config.Name), endpoint.WithAuthorizeServer(authorize.NewServer()), endpoint.WithAdditionalFunctionality( onidle.NewServer(ctx, cancel, config.IdleTimeout), - groupipam.NewServer(config.CidrPrefix, groupipam.WithCustomIPAMServer(ipamFunc)), + groupipam.NewServer(config.CidrPrefix, groupipam.WithCustomIPAMServer(config.IPAMPolicy)), policyroute.NewServer(newPolicyRoutesGetter(ctx, config.PBRConfigPath).Get), mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{ kernelmech.MECHANISM: kernel.NewServer(), From da1e5448866b2783708e0d8f142ff528f8a6a76b Mon Sep 17 00:00:00 2001 From: NikitaSkrynnik Date: Tue, 27 Aug 2024 20:51:13 +1100 Subject: [PATCH 6/6] change ENV's description in README.md Signed-off-by: NikitaSkrynnik --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81c80f1..3ddf59a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ docker build . * `NSM_CONNECT_TO` - url to connect to (default: "unix:///var/lib/networkservicemesh/nsm.io.sock") * `NSM_MAX_TOKEN_LIFETIME` - maximum lifetime of tokens (default: "10m") * `NSM_REGISTRY_CLIENT_POLICIES` - paths to files and directories that contain registry client policies (default: "etc/nsm/opa/common/.*.rego,etc/nsm/opa/registry/.*.rego,etc/nsm/opa/client/.*.rego") -* `NSM_IPAM_POLICY` - defines NSE's IPAM Policy. Possible values: default, strict +* `NSM_IPAM_POLICY` - polite, strict. Polite policy accepts any addresses sent by client. Strict policy resets ip_context if any of the client's addresses doesn't match endpoint's CIDR (default: "polite") * `NSM_SERVICE_NAMES` - Name of provided services (default: "icmp-responder") * `NSM_PAYLOAD` - Name of provided service payload (default: "ETHERNET") * `NSM_LABELS` - Endpoint labels