diff --git a/.github/ISSUE_TEMPLATE/bug-issue-report.md b/.github/ISSUE_TEMPLATE/bug-issue-report.md
index 1c63eeaee..0aa6cd77e 100644
--- a/.github/ISSUE_TEMPLATE/bug-issue-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-issue-report.md
@@ -2,7 +2,7 @@
name: Bug/Issue report
about: Create a report to help us improve
title: ''
-labels: ['triage']
+labels: ['triage-needed']
assignees: ''
---
diff --git a/.github/workflows/test-infrastructure-files.yml b/.github/workflows/test-infrastructure-files.yml
index e1261dabc..ee9739e09 100644
--- a/.github/workflows/test-infrastructure-files.yml
+++ b/.github/workflows/test-infrastructure-files.yml
@@ -162,6 +162,13 @@ jobs:
test $count -eq 4
working-directory: infrastructure_files/artifacts
+ - name: test geolocation databases
+ working-directory: infrastructure_files/artifacts
+ run: |
+ sleep 30
+ docker compose exec management ls -l /var/lib/netbird/ | grep -i GeoLite2-City.mmdb
+ docker compose exec management ls -l /var/lib/netbird/ | grep -i geonames.db
+
test-getting-started-script:
runs-on: ubuntu-latest
steps:
@@ -199,6 +206,6 @@ jobs:
- name: test script
run: bash -x infrastructure_files/download-geolite2.sh
- name: test mmdb file exists
- run: ls -l GeoLite2-City_*/GeoLite2-City.mmdb
+ run: test -f GeoLite2-City.mmdb
- name: test geonames file exists
run: test -f geonames.db
diff --git a/.golangci.yaml b/.golangci.yaml
index 757a60a39..3c5f4d5b8 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -63,6 +63,14 @@ linters-settings:
enable:
- nilness
+ revive:
+ rules:
+ - name: exported
+ severity: warning
+ disabled: false
+ arguments:
+ - "checkPrivateReceivers"
+ - "sayRepetitiveInsteadOfStutters"
tenv:
# The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.
# Otherwise, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked.
@@ -93,6 +101,7 @@ linters:
- nilerr # finds the code that returns nil even if it checks that the error is not nil
- nilnil # checks that there is no simultaneous return of nil error and an invalid value
- predeclared # predeclared finds code that shadows one of Go's predeclared identifiers
+ - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
- sqlclosecheck # checks that sql.Rows and sql.Stmt are closed
- thelper # thelper detects Go test helpers without t.Helper() call and checks the consistency of test helpers.
- wastedassign # wastedassign finds wasted assignment statements
diff --git a/.goreleaser_ui.yaml b/.goreleaser_ui.yaml
index 66a22ee34..b13085e86 100644
--- a/.goreleaser_ui.yaml
+++ b/.goreleaser_ui.yaml
@@ -54,7 +54,7 @@ nfpms:
contents:
- src: client/ui/netbird.desktop
dst: /usr/share/applications/netbird.desktop
- - src: client/ui/netbird-systemtray-default.png
+ - src: client/ui/netbird-systemtray-connected.png
dst: /usr/share/pixmaps/netbird.png
dependencies:
- netbird
@@ -71,7 +71,7 @@ nfpms:
contents:
- src: client/ui/netbird.desktop
dst: /usr/share/applications/netbird.desktop
- - src: client/ui/netbird-systemtray-default.png
+ - src: client/ui/netbird-systemtray-connected.png
dst: /usr/share/pixmaps/netbird.png
dependencies:
- netbird
diff --git a/README.md b/README.md
index 192377f06..0fa0a7dd2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
- :hatching_chick: New Release! Self-hosting in under 5 min.
-
+ :hatching_chick: New Release! Device Posture Checks.
+
Learn more
@@ -42,25 +42,22 @@
**Secure.** NetBird enables secure remote access by applying granular access policies, while allowing you to manage them intuitively from a single place. Works universally on any infrastructure.
-### Secure peer-to-peer VPN with SSO and MFA in minutes
+### Open-Source Network Security in a Single Platform
-https://user-images.githubusercontent.com/700848/197345890-2e2cded5-7b7a-436f-a444-94e80dd24f46.mov
+![download (2)](https://github.com/netbirdio/netbird/assets/700848/16210ac2-7265-44c1-8d4e-8fae85534dac)
### Key features
-| Connectivity | Management | Automation | Platforms |
-|---------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------------|---------------------------------------|
-| | - - \[x] [Admin Web UI](https://github.com/netbirdio/dashboard)
| - - \[x] [Public API](https://docs.netbird.io/api)
| |
-| - - \[x] Peer-to-peer connections
| - - \[x] Auto peer discovery and configuration
| - - \[x] [Setup keys for bulk network provisioning](https://docs.netbird.io/how-to/register-machines-using-setup-keys)
| |
-| - - \[x] Peer-to-peer encryption
| - - \[x] [IdP integrations](https://docs.netbird.io/selfhosted/identity-providers)
| - - \[x] [Self-hosting quickstart script](https://docs.netbird.io/selfhosted/selfhosted-quickstart)
| |
-| - - \[x] Connection relay fallback
| - - \[x] [SSO & MFA support](https://docs.netbird.io/how-to/installation#running-net-bird-with-sso-login)
| - - \[x] IdP groups sync with JWT
| |
-| - - \[x] [Routes to external networks](https://docs.netbird.io/how-to/routing-traffic-to-private-networks)
| - - \[x] [Access control - groups & rules](https://docs.netbird.io/how-to/manage-network-access)
| | |
-| - - \[x] NAT traversal with BPF
| - - \[x] [Private DNS](https://docs.netbird.io/how-to/manage-dns-in-your-network)
| | |
-| - - \[x] Post-quantum-secure connection through [Rosenpass](https://rosenpass.eu)
| - - \[x] [Multiuser support](https://docs.netbird.io/how-to/add-users-to-your-network)
| | |
-| | - - \[x] [Activity logging](https://docs.netbird.io/how-to/monitor-system-and-network-activity)
| | |
-| | - - \[x] SSH access management
| | |
-
-
+| Connectivity | Management | Security | Automation | Platforms |
+|------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
+| | - - \[x] [Admin Web UI](https://github.com/netbirdio/dashboard)
| - - \[x] [SSO & MFA support](https://docs.netbird.io/how-to/installation#running-net-bird-with-sso-login)
| - - \[x] [Public API](https://docs.netbird.io/api)
| |
+| - - \[x] Peer-to-peer connections
| - - \[x] Auto peer discovery and configuration
| - - \[x] [Access control - groups & rules](https://docs.netbird.io/how-to/manage-network-access)
| - - \[x] [Setup keys for bulk network provisioning](https://docs.netbird.io/how-to/register-machines-using-setup-keys)
| |
+| - - \[x] Connection relay fallback
| - - \[x] [IdP integrations](https://docs.netbird.io/selfhosted/identity-providers)
| - - \[x] [Activity logging](https://docs.netbird.io/how-to/monitor-system-and-network-activity)
| - - \[x] [Self-hosting quickstart script](https://docs.netbird.io/selfhosted/selfhosted-quickstart)
| |
+| - - \[x] [Routes to external networks](https://docs.netbird.io/how-to/routing-traffic-to-private-networks)
| - - \[x] [Private DNS](https://docs.netbird.io/how-to/manage-dns-in-your-network)
| - - \[x] [Device posture checks](https://docs.netbird.io/how-to/manage-posture-checks)
| - - \[x] IdP groups sync with JWT
| |
+| - - \[x] NAT traversal with BPF
| - - \[x] [Multiuser support](https://docs.netbird.io/how-to/add-users-to-your-network)
| - - \[x] Peer-to-peer encryption
| | |
+| | | - - \[x] [Quantum-resistance with Rosenpass](https://netbird.io/knowledge-hub/the-first-quantum-resistant-mesh-vpn)
| | |
+| | | - \[x] [Periodic re-authentication](https://docs.netbird.io/how-to/enforce-periodic-user-authentication) | | - - \[x] [Serverless](https://docs.netbird.io/how-to/netbird-on-faas)
|
+| | | | | |
### Quickstart with NetBird Cloud
- Download and install NetBird at [https://app.netbird.io/install](https://app.netbird.io/install)
diff --git a/client/cmd/testutil.go b/client/cmd/testutil.go
index 40fd86f1d..13a434c7d 100644
--- a/client/cmd/testutil.go
+++ b/client/cmd/testutil.go
@@ -76,10 +76,7 @@ func startManagement(t *testing.T, config *mgmt.Config) (*grpc.Server, net.Liste
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
eventStore := &activity.InMemoryEventStore{}
- if err != nil {
- return nil, nil
- }
- iv := integrations.NewIntegratedApproval()
+ iv, _ := integrations.NewIntegratedApproval(eventStore)
accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil, "", "", eventStore, nil, false, iv)
if err != nil {
t.Fatal(err)
diff --git a/client/internal/auth/oauth.go b/client/internal/auth/oauth.go
index 23bde2be2..7467584a3 100644
--- a/client/internal/auth/oauth.go
+++ b/client/internal/auth/oauth.go
@@ -26,7 +26,7 @@ type HTTPClient interface {
}
// AuthFlowInfo holds information for the OAuth 2.0 authorization flow
-type AuthFlowInfo struct {
+type AuthFlowInfo struct { //nolint:revive
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
diff --git a/client/internal/dns/file_linux.go b/client/internal/dns/file_linux.go
index c62da7016..b427a30e1 100644
--- a/client/internal/dns/file_linux.go
+++ b/client/internal/dns/file_linux.go
@@ -8,6 +8,7 @@ import (
"net/netip"
"os"
"strings"
+ "time"
log "github.com/sirupsen/logrus"
)
@@ -23,10 +24,16 @@ const (
fileMaxNumberOfSearchDomains = 6
)
+const (
+ dnsFailoverTimeout = 4 * time.Second
+ dnsFailoverAttempts = 1
+)
+
type fileConfigurator struct {
repair *repair
- originalPerms os.FileMode
+ originalPerms os.FileMode
+ nbNameserverIP string
}
func newFileConfigurator() (hostManager, error) {
@@ -64,7 +71,7 @@ func (f *fileConfigurator) applyDNSConfig(config HostDNSConfig) error {
}
nbSearchDomains := searchDomains(config)
- nbNameserverIP := config.ServerIP
+ f.nbNameserverIP = config.ServerIP
resolvConf, err := parseBackupResolvConf()
if err != nil {
@@ -73,11 +80,11 @@ func (f *fileConfigurator) applyDNSConfig(config HostDNSConfig) error {
f.repair.stopWatchFileChanges()
- err = f.updateConfig(nbSearchDomains, nbNameserverIP, resolvConf)
+ err = f.updateConfig(nbSearchDomains, f.nbNameserverIP, resolvConf)
if err != nil {
return err
}
- f.repair.watchFileChanges(nbSearchDomains, nbNameserverIP)
+ f.repair.watchFileChanges(nbSearchDomains, f.nbNameserverIP)
return nil
}
@@ -85,10 +92,11 @@ func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP
searchDomainList := mergeSearchDomains(nbSearchDomains, cfg.searchDomains)
nameServers := generateNsList(nbNameserverIP, cfg)
+ options := prepareOptionsWithTimeout(cfg.others, int(dnsFailoverTimeout.Seconds()), dnsFailoverAttempts)
buf := prepareResolvConfContent(
searchDomainList,
nameServers,
- cfg.others)
+ options)
log.Debugf("creating managed file %s", defaultResolvConfPath)
err := os.WriteFile(defaultResolvConfPath, buf.Bytes(), f.originalPerms)
@@ -131,7 +139,12 @@ func (f *fileConfigurator) backup() error {
}
func (f *fileConfigurator) restore() error {
- err := copyFile(fileDefaultResolvConfBackupLocation, defaultResolvConfPath)
+ err := removeFirstNbNameserver(fileDefaultResolvConfBackupLocation, f.nbNameserverIP)
+ if err != nil {
+ log.Errorf("Failed to remove netbird nameserver from %s on backup restore: %s", fileDefaultResolvConfBackupLocation, err)
+ }
+
+ err = copyFile(fileDefaultResolvConfBackupLocation, defaultResolvConfPath)
if err != nil {
return fmt.Errorf("restoring %s from %s: %w", defaultResolvConfPath, fileDefaultResolvConfBackupLocation, err)
}
@@ -157,7 +170,7 @@ func (f *fileConfigurator) restoreUncleanShutdownDNS(storedDNSAddress *netip.Add
currentDNSAddress, err := netip.ParseAddr(resolvConf.nameServers[0])
// not a valid first nameserver -> restore
if err != nil {
- log.Errorf("restoring unclean shutdown: parse dns address %s failed: %s", resolvConf.nameServers[1], err)
+ log.Errorf("restoring unclean shutdown: parse dns address %s failed: %s", resolvConf.nameServers[0], err)
return restoreResolvConfFile()
}
diff --git a/client/internal/dns/file_parser_linux.go b/client/internal/dns/file_parser_linux.go
index 95e1ddb54..02f6d03a5 100644
--- a/client/internal/dns/file_parser_linux.go
+++ b/client/internal/dns/file_parser_linux.go
@@ -5,6 +5,7 @@ package dns
import (
"fmt"
"os"
+ "regexp"
"strings"
log "github.com/sirupsen/logrus"
@@ -14,6 +15,9 @@ const (
defaultResolvConfPath = "/etc/resolv.conf"
)
+var timeoutRegex = regexp.MustCompile(`timeout:\d+`)
+var attemptsRegex = regexp.MustCompile(`attempts:\d+`)
+
type resolvConf struct {
nameServers []string
searchDomains []string
@@ -103,3 +107,62 @@ func parseResolvConfFile(resolvConfFile string) (*resolvConf, error) {
}
return rconf, nil
}
+
+// prepareOptionsWithTimeout appends timeout to existing options if it doesn't exist,
+// otherwise it adds a new option with timeout and attempts.
+func prepareOptionsWithTimeout(input []string, timeout int, attempts int) []string {
+ configs := make([]string, len(input))
+ copy(configs, input)
+
+ for i, config := range configs {
+ if strings.HasPrefix(config, "options") {
+ config = strings.ReplaceAll(config, "rotate", "")
+ config = strings.Join(strings.Fields(config), " ")
+
+ if strings.Contains(config, "timeout:") {
+ config = timeoutRegex.ReplaceAllString(config, fmt.Sprintf("timeout:%d", timeout))
+ } else {
+ config = strings.Replace(config, "options ", fmt.Sprintf("options timeout:%d ", timeout), 1)
+ }
+
+ if strings.Contains(config, "attempts:") {
+ config = attemptsRegex.ReplaceAllString(config, fmt.Sprintf("attempts:%d", attempts))
+ } else {
+ config = strings.Replace(config, "options ", fmt.Sprintf("options attempts:%d ", attempts), 1)
+ }
+
+ configs[i] = config
+ return configs
+ }
+ }
+
+ return append(configs, fmt.Sprintf("options timeout:%d attempts:%d", timeout, attempts))
+}
+
+// removeFirstNbNameserver removes the given nameserver from the given file if it is in the first position
+// and writes the file back to the original location
+func removeFirstNbNameserver(filename, nameserverIP string) error {
+ resolvConf, err := parseResolvConfFile(filename)
+ if err != nil {
+ return fmt.Errorf("parse backup resolv.conf: %w", err)
+ }
+ content, err := os.ReadFile(filename)
+ if err != nil {
+ return fmt.Errorf("read %s: %w", filename, err)
+ }
+
+ if len(resolvConf.nameServers) > 1 && resolvConf.nameServers[0] == nameserverIP {
+ newContent := strings.Replace(string(content), fmt.Sprintf("nameserver %s\n", nameserverIP), "", 1)
+
+ stat, err := os.Stat(filename)
+ if err != nil {
+ return fmt.Errorf("stat %s: %w", filename, err)
+ }
+ if err := os.WriteFile(filename, []byte(newContent), stat.Mode()); err != nil {
+ return fmt.Errorf("write %s: %w", filename, err)
+ }
+
+ }
+
+ return nil
+}
diff --git a/client/internal/dns/file_parser_linux_test.go b/client/internal/dns/file_parser_linux_test.go
index 180ad2f9d..4263d4063 100644
--- a/client/internal/dns/file_parser_linux_test.go
+++ b/client/internal/dns/file_parser_linux_test.go
@@ -6,6 +6,8 @@ import (
"os"
"path/filepath"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func Test_parseResolvConf(t *testing.T) {
@@ -172,3 +174,131 @@ nameserver 192.168.0.1
t.Errorf("unexpected resolv.conf content: %v", cfg)
}
}
+
+func TestPrepareOptionsWithTimeout(t *testing.T) {
+ tests := []struct {
+ name string
+ others []string
+ timeout int
+ attempts int
+ expected []string
+ }{
+ {
+ name: "Append new options with timeout and attempts",
+ others: []string{"some config"},
+ timeout: 2,
+ attempts: 2,
+ expected: []string{"some config", "options timeout:2 attempts:2"},
+ },
+ {
+ name: "Modify existing options to exclude rotate and include timeout and attempts",
+ others: []string{"some config", "options rotate someother"},
+ timeout: 3,
+ attempts: 2,
+ expected: []string{"some config", "options attempts:2 timeout:3 someother"},
+ },
+ {
+ name: "Existing options with timeout and attempts are updated",
+ others: []string{"some config", "options timeout:4 attempts:3"},
+ timeout: 5,
+ attempts: 4,
+ expected: []string{"some config", "options timeout:5 attempts:4"},
+ },
+ {
+ name: "Modify existing options, add missing attempts before timeout",
+ others: []string{"some config", "options timeout:4"},
+ timeout: 4,
+ attempts: 3,
+ expected: []string{"some config", "options attempts:3 timeout:4"},
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := prepareOptionsWithTimeout(tc.others, tc.timeout, tc.attempts)
+ assert.Equal(t, tc.expected, result)
+ })
+ }
+}
+
+func TestRemoveFirstNbNameserver(t *testing.T) {
+ testCases := []struct {
+ name string
+ content string
+ ipToRemove string
+ expected string
+ }{
+ {
+ name: "Unrelated nameservers with comments and options",
+ content: `# This is a comment
+options rotate
+nameserver 1.1.1.1
+# Another comment
+nameserver 8.8.4.4
+search example.com`,
+ ipToRemove: "9.9.9.9",
+ expected: `# This is a comment
+options rotate
+nameserver 1.1.1.1
+# Another comment
+nameserver 8.8.4.4
+search example.com`,
+ },
+ {
+ name: "First nameserver matches",
+ content: `search example.com
+nameserver 9.9.9.9
+# oof, a comment
+nameserver 8.8.4.4
+options attempts:5`,
+ ipToRemove: "9.9.9.9",
+ expected: `search example.com
+# oof, a comment
+nameserver 8.8.4.4
+options attempts:5`,
+ },
+ {
+ name: "Target IP not the first nameserver",
+ // nolint:dupword
+ content: `# Comment about the first nameserver
+nameserver 8.8.4.4
+# Comment before our target
+nameserver 9.9.9.9
+options timeout:2`,
+ ipToRemove: "9.9.9.9",
+ // nolint:dupword
+ expected: `# Comment about the first nameserver
+nameserver 8.8.4.4
+# Comment before our target
+nameserver 9.9.9.9
+options timeout:2`,
+ },
+ {
+ name: "Only nameserver matches",
+ content: `options debug
+nameserver 9.9.9.9
+search localdomain`,
+ ipToRemove: "9.9.9.9",
+ expected: `options debug
+nameserver 9.9.9.9
+search localdomain`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ tempDir := t.TempDir()
+ tempFile := filepath.Join(tempDir, "resolv.conf")
+ err := os.WriteFile(tempFile, []byte(tc.content), 0644)
+ assert.NoError(t, err)
+
+ err = removeFirstNbNameserver(tempFile, tc.ipToRemove)
+ assert.NoError(t, err)
+
+ content, err := os.ReadFile(tempFile)
+ assert.NoError(t, err)
+
+ assert.Equal(t, tc.expected, string(content), "The resulting content should match the expected output.")
+ })
+ }
+}
diff --git a/client/internal/dns/host_linux.go b/client/internal/dns/host_linux.go
index 37d8f704a..cb246bcfe 100644
--- a/client/internal/dns/host_linux.go
+++ b/client/internal/dns/host_linux.go
@@ -65,7 +65,7 @@ func newHostManager(wgInterface string) (hostManager, error) {
return nil, err
}
- log.Debugf("discovered mode is: %s", osManager)
+ log.Infof("System DNS manager discovered: %s", osManager)
return newHostManagerFromType(wgInterface, osManager)
}
diff --git a/client/internal/dns/resolvconf_linux.go b/client/internal/dns/resolvconf_linux.go
index b8f753e28..72db5faf1 100644
--- a/client/internal/dns/resolvconf_linux.go
+++ b/client/internal/dns/resolvconf_linux.go
@@ -53,10 +53,12 @@ func (r *resolvconf) applyDNSConfig(config HostDNSConfig) error {
searchDomainList := searchDomains(config)
searchDomainList = mergeSearchDomains(searchDomainList, r.originalSearchDomains)
+ options := prepareOptionsWithTimeout(r.othersConfigs, int(dnsFailoverTimeout.Seconds()), dnsFailoverAttempts)
+
buf := prepareResolvConfContent(
searchDomainList,
append([]string{config.ServerIP}, r.originalNameServers...),
- r.othersConfigs)
+ options)
// create a backup for unclean shutdown detection before the resolv.conf is changed
if err := createUncleanShutdownIndicator(defaultResolvConfPath, resolvConfManager, config.ServerIP); err != nil {
diff --git a/client/internal/engine_test.go b/client/internal/engine_test.go
index ffcb8fabb..7b8509cc5 100644
--- a/client/internal/engine_test.go
+++ b/client/internal/engine_test.go
@@ -71,10 +71,10 @@ func TestEngine_SSH(t *testing.T) {
defer cancel()
engine := NewEngine(ctx, cancel, &signal.MockClient{}, &mgmt.MockClient{}, &EngineConfig{
- WgIfaceName: "utun101",
- WgAddr: "100.64.0.1/24",
- WgPrivateKey: key,
- WgPort: 33100,
+ WgIfaceName: "utun101",
+ WgAddr: "100.64.0.1/24",
+ WgPrivateKey: key,
+ WgPort: 33100,
ServerSSHAllowed: true,
}, MobileDependency{}, peer.NewRecorder("https://mgm"))
@@ -1048,10 +1048,8 @@ func startManagement(dataDir string) (*grpc.Server, string, error) {
peersUpdateManager := server.NewPeersUpdateManager(nil)
eventStore := &activity.InMemoryEventStore{}
- if err != nil {
- return nil, "", err
- }
- accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "", "", eventStore, nil, false, integrations.NewIntegratedApproval())
+ ia, _ := integrations.NewIntegratedApproval(eventStore)
+ accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "", "", eventStore, nil, false, ia)
if err != nil {
return nil, "", err
}
diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go
index d90156f56..e242a26db 100644
--- a/client/ui/client_ui.go
+++ b/client/ui/client_ui.go
@@ -61,7 +61,7 @@ func main() {
flag.Parse()
- a := app.New()
+ a := app.NewWithID("NetBird")
a.SetIcon(fyne.NewStaticResource("netbird", iconDisconnectedPNG))
client := newServiceClient(daemonAddr, a, showSettings)
@@ -82,17 +82,23 @@ var iconConnectedICO []byte
//go:embed netbird-systemtray-connected.png
var iconConnectedPNG []byte
-//go:embed netbird-systemtray-default.ico
+//go:embed netbird-systemtray-disconnected.ico
var iconDisconnectedICO []byte
-//go:embed netbird-systemtray-default.png
+//go:embed netbird-systemtray-disconnected.png
var iconDisconnectedPNG []byte
-//go:embed netbird-systemtray-update.ico
-var iconUpdateICO []byte
+//go:embed netbird-systemtray-update-disconnected.ico
+var iconUpdateDisconnectedICO []byte
-//go:embed netbird-systemtray-update.png
-var iconUpdatePNG []byte
+//go:embed netbird-systemtray-update-disconnected.png
+var iconUpdateDisconnectedPNG []byte
+
+//go:embed netbird-systemtray-update-connected.ico
+var iconUpdateConnectedICO []byte
+
+//go:embed netbird-systemtray-update-connected.png
+var iconUpdateConnectedPNG []byte
//go:embed netbird-systemtray-update-cloud.ico
var iconUpdateCloudICO []byte
@@ -105,10 +111,11 @@ type serviceClient struct {
addr string
conn proto.DaemonServiceClient
- icConnected []byte
- icDisconnected []byte
- icUpdate []byte
- icUpdateCloud []byte
+ icConnected []byte
+ icDisconnected []byte
+ icUpdateConnected []byte
+ icUpdateDisconnected []byte
+ icUpdateCloud []byte
// systray menu items
mStatus *systray.MenuItem
@@ -123,9 +130,10 @@ type serviceClient struct {
mQuit *systray.MenuItem
// application with main windows.
- app fyne.App
- wSettings fyne.Window
- showSettings bool
+ app fyne.App
+ wSettings fyne.Window
+ showSettings bool
+ sendNotification bool
// input elements for settings form
iMngURL *widget.Entry
@@ -139,6 +147,7 @@ type serviceClient struct {
preSharedKey string
adminURL string
+ connected bool
update *version.Update
daemonVersion string
updateIndicationLock sync.Mutex
@@ -150,9 +159,10 @@ type serviceClient struct {
// This constructor also builds the UI elements for the settings window.
func newServiceClient(addr string, a fyne.App, showSettings bool) *serviceClient {
s := &serviceClient{
- ctx: context.Background(),
- addr: addr,
- app: a,
+ ctx: context.Background(),
+ addr: addr,
+ app: a,
+ sendNotification: false,
showSettings: showSettings,
update: version.NewUpdate(),
@@ -161,13 +171,15 @@ func newServiceClient(addr string, a fyne.App, showSettings bool) *serviceClient
if runtime.GOOS == "windows" {
s.icConnected = iconConnectedICO
s.icDisconnected = iconDisconnectedICO
- s.icUpdate = iconUpdateICO
+ s.icUpdateConnected = iconUpdateConnectedICO
+ s.icUpdateDisconnected = iconUpdateDisconnectedICO
s.icUpdateCloud = iconUpdateCloudICO
} else {
s.icConnected = iconConnectedPNG
s.icDisconnected = iconDisconnectedPNG
- s.icUpdate = iconUpdatePNG
+ s.icUpdateConnected = iconUpdateConnectedPNG
+ s.icUpdateDisconnected = iconUpdateDisconnectedPNG
s.icUpdateCloud = iconUpdateCloudPNG
}
@@ -367,9 +379,18 @@ func (s *serviceClient) updateStatus() error {
s.updateIndicationLock.Lock()
defer s.updateIndicationLock.Unlock()
+ // notify the user when the session has expired
+ if status.Status == string(internal.StatusNeedsLogin) {
+ s.onSessionExpire()
+ }
+
var systrayIconState bool
if status.Status == string(internal.StatusConnected) && !s.mUp.Disabled() {
- if !s.isUpdateIconActive {
+ s.connected = true
+ s.sendNotification = true
+ if s.isUpdateIconActive {
+ systray.SetIcon(s.icUpdateConnected)
+ } else {
systray.SetIcon(s.icConnected)
}
systray.SetTooltip("NetBird (Connected)")
@@ -378,7 +399,10 @@ func (s *serviceClient) updateStatus() error {
s.mDown.Enable()
systrayIconState = true
} else if status.Status != string(internal.StatusConnected) && s.mUp.Disabled() {
- if !s.isUpdateIconActive {
+ s.connected = false
+ if s.isUpdateIconActive {
+ systray.SetIcon(s.icUpdateDisconnected)
+ } else {
systray.SetIcon(s.icDisconnected)
}
systray.SetTooltip("NetBird (Disconnected)")
@@ -605,10 +629,30 @@ func (s *serviceClient) onUpdateAvailable() {
defer s.updateIndicationLock.Unlock()
s.mUpdate.Show()
- s.mAbout.SetIcon(s.icUpdateCloud)
-
s.isUpdateIconActive = true
- systray.SetIcon(s.icUpdate)
+
+ if s.connected {
+ systray.SetIcon(s.icUpdateConnected)
+ } else {
+ systray.SetIcon(s.icUpdateDisconnected)
+ }
+}
+
+// onSessionExpire sends a notification to the user when the session expires.
+func (s *serviceClient) onSessionExpire() {
+ if s.sendNotification {
+ title := "Connection session expired"
+ if runtime.GOOS == "darwin" {
+ title = "NetBird connection session expired"
+ }
+ s.app.SendNotification(
+ fyne.NewNotification(
+ title,
+ "Please re-authenticate to connect to the network",
+ ),
+ )
+ s.sendNotification = false
+ }
}
func openURL(url string) error {
diff --git a/client/ui/netbird-systemtray-connected.ico b/client/ui/netbird-systemtray-connected.ico
index 621afce9f..80550aa37 100644
Binary files a/client/ui/netbird-systemtray-connected.ico and b/client/ui/netbird-systemtray-connected.ico differ
diff --git a/client/ui/netbird-systemtray-connected.png b/client/ui/netbird-systemtray-connected.png
index c5878d018..f4d156da8 100644
Binary files a/client/ui/netbird-systemtray-connected.png and b/client/ui/netbird-systemtray-connected.png differ
diff --git a/client/ui/netbird-systemtray-default.ico b/client/ui/netbird-systemtray-default.ico
deleted file mode 100644
index 5a0252675..000000000
Binary files a/client/ui/netbird-systemtray-default.ico and /dev/null differ
diff --git a/client/ui/netbird-systemtray-default.png b/client/ui/netbird-systemtray-default.png
deleted file mode 100644
index 12e7a2dc1..000000000
Binary files a/client/ui/netbird-systemtray-default.png and /dev/null differ
diff --git a/client/ui/netbird-systemtray-disconnected.ico b/client/ui/netbird-systemtray-disconnected.ico
new file mode 100644
index 000000000..aa75268b0
Binary files /dev/null and b/client/ui/netbird-systemtray-disconnected.ico differ
diff --git a/client/ui/netbird-systemtray-disconnected.png b/client/ui/netbird-systemtray-disconnected.png
new file mode 100644
index 000000000..0e1b7275f
Binary files /dev/null and b/client/ui/netbird-systemtray-disconnected.png differ
diff --git a/client/ui/netbird-systemtray-update-connected.ico b/client/ui/netbird-systemtray-update-connected.ico
new file mode 100644
index 000000000..cc056e68e
Binary files /dev/null and b/client/ui/netbird-systemtray-update-connected.ico differ
diff --git a/client/ui/netbird-systemtray-update-connected.png b/client/ui/netbird-systemtray-update-connected.png
new file mode 100644
index 000000000..a0c453340
Binary files /dev/null and b/client/ui/netbird-systemtray-update-connected.png differ
diff --git a/client/ui/netbird-systemtray-update-disconnected.ico b/client/ui/netbird-systemtray-update-disconnected.ico
new file mode 100644
index 000000000..04c35b058
Binary files /dev/null and b/client/ui/netbird-systemtray-update-disconnected.ico differ
diff --git a/client/ui/netbird-systemtray-update-disconnected.png b/client/ui/netbird-systemtray-update-disconnected.png
new file mode 100644
index 000000000..44a30dc9a
Binary files /dev/null and b/client/ui/netbird-systemtray-update-disconnected.png differ
diff --git a/client/ui/netbird-systemtray-update.ico b/client/ui/netbird-systemtray-update.ico
deleted file mode 100644
index 1a1c4086d..000000000
Binary files a/client/ui/netbird-systemtray-update.ico and /dev/null differ
diff --git a/client/ui/netbird-systemtray-update.png b/client/ui/netbird-systemtray-update.png
deleted file mode 100644
index 1f4651df9..000000000
Binary files a/client/ui/netbird-systemtray-update.png and /dev/null differ
diff --git a/go.mod b/go.mod
index 79862cab2..c69dd248b 100644
--- a/go.mod
+++ b/go.mod
@@ -59,7 +59,7 @@ require (
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/nadoo/ipset v0.5.0
github.com/netbirdio/management-integrations/additions v0.0.0-20240226151841-2e4fe2407450
- github.com/netbirdio/management-integrations/integrations v0.0.0-20240226151841-2e4fe2407450
+ github.com/netbirdio/management-integrations/integrations v0.0.0-20240305130559-469a80446ac7
github.com/okta/okta-sdk-golang/v2 v2.18.0
github.com/oschwald/maxminddb-golang v1.12.0
github.com/patrickmn/go-cache v2.1.0+incompatible
diff --git a/go.sum b/go.sum
index 15c8db563..c2d32a0c1 100644
--- a/go.sum
+++ b/go.sum
@@ -379,8 +379,8 @@ github.com/nadoo/ipset v0.5.0 h1:5GJUAuZ7ITQQQGne5J96AmFjRtI8Avlbk6CabzYWVUc=
github.com/nadoo/ipset v0.5.0/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ=
github.com/netbirdio/management-integrations/additions v0.0.0-20240226151841-2e4fe2407450 h1:qA4S5YFt6/s0kQ8wKLjq8faLxuBSte1WzjWfmQmyJTU=
github.com/netbirdio/management-integrations/additions v0.0.0-20240226151841-2e4fe2407450/go.mod h1:31FhBNvQ+riHEIu6LSTmqr8IeuSIsGfQffqV4LFmbwA=
-github.com/netbirdio/management-integrations/integrations v0.0.0-20240226151841-2e4fe2407450 h1:jEepZRVo60IN+us4E8BvNUbasoViFwqJ7exKix4aQyc=
-github.com/netbirdio/management-integrations/integrations v0.0.0-20240226151841-2e4fe2407450/go.mod h1:B0nMS3es77gOvPYhc0K91fAzTkQLi/jRq5TffUN3klM=
+github.com/netbirdio/management-integrations/integrations v0.0.0-20240305130559-469a80446ac7 h1:YYIQJbRhANmNFClkCmjBa0w33RpTzsF2DpbGAWhul6Y=
+github.com/netbirdio/management-integrations/integrations v0.0.0-20240305130559-469a80446ac7/go.mod h1:B0nMS3es77gOvPYhc0K91fAzTkQLi/jRq5TffUN3klM=
github.com/netbirdio/service v0.0.0-20230215170314-b923b89432b0 h1:hirFRfx3grVA/9eEyjME5/z3nxdJlN9kfQpvWWPk32g=
github.com/netbirdio/service v0.0.0-20230215170314-b923b89432b0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/netbirdio/systray v0.0.0-20231030152038-ef1ed2a27949 h1:xbWM9BU6mwZZLHxEjxIX/V8Hv3HurQt4mReIE4mY4DM=
diff --git a/iface/netstack/tun.go b/iface/netstack/tun.go
index 8c7c3a8ff..c180e4ef5 100644
--- a/iface/netstack/tun.go
+++ b/iface/netstack/tun.go
@@ -8,7 +8,7 @@ import (
"golang.zx2c4.com/wireguard/tun/netstack"
)
-type NetStackTun struct {
+type NetStackTun struct { //nolint:revive
address string
mtu int
listenAddress string
diff --git a/infrastructure_files/download-geolite2.sh b/infrastructure_files/download-geolite2.sh
index e09873627..4a9db5e01 100755
--- a/infrastructure_files/download-geolite2.sh
+++ b/infrastructure_files/download-geolite2.sh
@@ -43,21 +43,18 @@ download_geolite_mmdb() {
mkdir -p "$EXTRACTION_DIR"
tar -xzvf "$DATABASE_FILE" > /dev/null 2>&1
- # Create a SHA256 signature file
MMDB_FILE="GeoLite2-City.mmdb"
- cd "$EXTRACTION_DIR"
- sha256sum "$MMDB_FILE" > "$MMDB_FILE.sha256"
- echo "SHA256 signature created for $MMDB_FILE."
- cd - > /dev/null 2>&1
+ cp "$EXTRACTION_DIR"/"$MMDB_FILE" $MMDB_FILE
# Remove downloaded files
+ rm -r "$EXTRACTION_DIR"
rm "$DATABASE_FILE" "$SIGNATURE_FILE"
# Done. Print next steps
echo ""
echo "Process completed successfully."
- echo "Now you can place $EXTRACTION_DIR/$MMDB_FILE to 'datadir' of management service."
- echo -e "Example:\n\tdocker compose cp $EXTRACTION_DIR/$MMDB_FILE management:/var/lib/netbird/"
+ echo "Now you can place $MMDB_FILE to 'datadir' of management service."
+ echo -e "Example:\n\tdocker compose cp $MMDB_FILE management:/var/lib/netbird/"
}
diff --git a/infrastructure_files/getting-started-with-zitadel.sh b/infrastructure_files/getting-started-with-zitadel.sh
index 24cb108e1..29f0e4606 100644
--- a/infrastructure_files/getting-started-with-zitadel.sh
+++ b/infrastructure_files/getting-started-with-zitadel.sh
@@ -137,6 +137,13 @@ create_new_application() {
BASE_REDIRECT_URL2=$5
LOGOUT_URL=$6
ZITADEL_DEV_MODE=$7
+ DEVICE_CODE=$8
+
+ if [[ $DEVICE_CODE == "true" ]]; then
+ GRANT_TYPES='["OIDC_GRANT_TYPE_AUTHORIZATION_CODE","OIDC_GRANT_TYPE_DEVICE_CODE","OIDC_GRANT_TYPE_REFRESH_TOKEN"]'
+ else
+ GRANT_TYPES='["OIDC_GRANT_TYPE_AUTHORIZATION_CODE","OIDC_GRANT_TYPE_REFRESH_TOKEN"]'
+ fi
RESPONSE=$(
curl -sS -X POST "$INSTANCE_URL/management/v1/projects/$PROJECT_ID/apps/oidc" \
@@ -154,10 +161,7 @@ create_new_application() {
"RESPONSETypes": [
"OIDC_RESPONSE_TYPE_CODE"
],
- "grantTypes": [
- "OIDC_GRANT_TYPE_AUTHORIZATION_CODE",
- "OIDC_GRANT_TYPE_REFRESH_TOKEN"
- ],
+ "grantTypes": '"$GRANT_TYPES"',
"appType": "OIDC_APP_TYPE_USER_AGENT",
"authMethodType": "OIDC_AUTH_METHOD_TYPE_NONE",
"version": "OIDC_VERSION_1_0",
@@ -340,10 +344,10 @@ init_zitadel() {
# create zitadel spa applications
echo "Creating new Zitadel SPA Dashboard application"
- DASHBOARD_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Dashboard" "$BASE_REDIRECT_URL/nb-auth" "$BASE_REDIRECT_URL/nb-silent-auth" "$BASE_REDIRECT_URL/" "$ZITADEL_DEV_MODE")
+ DASHBOARD_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Dashboard" "$BASE_REDIRECT_URL/nb-auth" "$BASE_REDIRECT_URL/nb-silent-auth" "$BASE_REDIRECT_URL/" "$ZITADEL_DEV_MODE" "false")
echo "Creating new Zitadel SPA Cli application"
- CLI_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Cli" "http://localhost:53000/" "http://localhost:54000/" "http://localhost:53000/" "true")
+ CLI_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Cli" "http://localhost:53000/" "http://localhost:54000/" "http://localhost:53000/" "true" "true")
MACHINE_USER_ID=$(create_service_user "$INSTANCE_URL" "$PAT")
@@ -561,6 +565,8 @@ renderCaddyfile() {
reverse_proxy /.well-known/openid-configuration h2c://zitadel:8080
reverse_proxy /openapi/* h2c://zitadel:8080
reverse_proxy /debug/* h2c://zitadel:8080
+ reverse_proxy /device/* h2c://zitadel:8080
+ reverse_proxy /device h2c://zitadel:8080
# Dashboard
reverse_proxy /* dashboard:80
}
@@ -629,6 +635,14 @@ renderManagementJson() {
"ManagementEndpoint": "$NETBIRD_HTTP_PROTOCOL://$NETBIRD_DOMAIN/management/v1"
}
},
+ "DeviceAuthorizationFlow": {
+ "Provider": "hosted",
+ "ProviderConfig": {
+ "Audience": "$NETBIRD_AUTH_CLIENT_ID_CLI",
+ "ClientID": "$NETBIRD_AUTH_CLIENT_ID_CLI",
+ "Scope": "openid"
+ }
+ },
"PKCEAuthorizationFlow": {
"ProviderConfig": {
"Audience": "$NETBIRD_AUTH_CLIENT_ID_CLI",
diff --git a/infrastructure_files/management.json.tmpl b/infrastructure_files/management.json.tmpl
index 0b607245f..eadb90ce2 100644
--- a/infrastructure_files/management.json.tmpl
+++ b/infrastructure_files/management.json.tmpl
@@ -26,6 +26,13 @@
"Username": "",
"Password": null
},
+ "ReverseProxy": {
+ "TrustedHTTPProxies": [],
+ "TrustedHTTPProxiesCount": 0,
+ "TrustedPeers": [
+ "0.0.0.0/0"
+ ]
+ },
"Datadir": "",
"DataStoreEncryptionKey": "$NETBIRD_DATASTORE_ENC_KEY",
"StoreConfig": {
diff --git a/infrastructure_files/nginx.tmpl.conf b/infrastructure_files/nginx.tmpl.conf
index 77739a67a..23fd760aa 100644
--- a/infrastructure_files/nginx.tmpl.conf
+++ b/infrastructure_files/nginx.tmpl.conf
@@ -46,6 +46,7 @@ server {
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Proxy dashboard
location / {
diff --git a/management/client/client_test.go b/management/client/client_test.go
index b97d7862d..5c9a8b24c 100644
--- a/management/client/client_test.go
+++ b/management/client/client_test.go
@@ -2,7 +2,6 @@ package client
import (
"context"
- "github.com/netbirdio/management-integrations/integrations"
"net"
"path/filepath"
"sync"
@@ -16,6 +15,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
+ "github.com/netbirdio/management-integrations/integrations"
"github.com/netbirdio/netbird/encryption"
mgmtProto "github.com/netbirdio/netbird/management/proto"
mgmt "github.com/netbirdio/netbird/management/server"
@@ -61,7 +61,8 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
eventStore := &activity.InMemoryEventStore{}
- accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil, "", "", eventStore, nil, false, integrations.NewIntegratedApproval())
+ ia, _ := integrations.NewIntegratedApproval(eventStore)
+ accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil, "", "", eventStore, nil, false, ia)
if err != nil {
t.Fatal(err)
}
@@ -364,10 +365,11 @@ func Test_SystemMetaDataFromClient(t *testing.T) {
WiretrusteeVersion: info.WiretrusteeVersion,
KernelVersion: info.KernelVersion,
- NetworkAddresses: protoNetAddr,
- SysSerialNumber: info.SystemSerialNumber,
- SysProductName: info.SystemProductName,
- SysManufacturer: info.SystemManufacturer,
+ NetworkAddresses: protoNetAddr,
+ SysSerialNumber: info.SystemSerialNumber,
+ SysProductName: info.SystemProductName,
+ SysManufacturer: info.SystemManufacturer,
+ Environment: &mgmtProto.Environment{Cloud: info.Environment.Cloud, Platform: info.Environment.Platform},
}
assert.Equal(t, ValidKey, actualValidKey)
@@ -408,7 +410,9 @@ func isEqual(a, b *mgmtProto.PeerSystemMeta) bool {
a.GetUiVersion() == b.GetUiVersion() &&
a.GetSysSerialNumber() == b.GetSysSerialNumber() &&
a.GetSysProductName() == b.GetSysProductName() &&
- a.GetSysManufacturer() == b.GetSysManufacturer()
+ a.GetSysManufacturer() == b.GetSysManufacturer() &&
+ a.GetEnvironment().Cloud == b.GetEnvironment().Cloud &&
+ a.GetEnvironment().Platform == b.GetEnvironment().Platform
}
func Test_GetDeviceAuthorizationFlow(t *testing.T) {
diff --git a/management/client/grpc.go b/management/client/grpc.go
index 3c4106aef..0234f866c 100644
--- a/management/client/grpc.go
+++ b/management/client/grpc.go
@@ -26,6 +26,8 @@ import (
"github.com/netbirdio/netbird/management/proto"
)
+const ConnectTimeout = 10 * time.Second
+
// ConnStateNotifier is a wrapper interface of the status recorders
type ConnStateNotifier interface {
MarkManagementDisconnected(error)
@@ -49,7 +51,7 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
transportOption = grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))
}
- mgmCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
+ mgmCtx, cancel := context.WithTimeout(ctx, ConnectTimeout)
defer cancel()
conn, err := grpc.DialContext(
mgmCtx,
@@ -318,7 +320,7 @@ func (c *GrpcClient) login(serverKey wgtypes.Key, req *proto.LoginRequest) (*pro
log.Errorf("failed to encrypt message: %s", err)
return nil, err
}
- mgmCtx, cancel := context.WithTimeout(c.ctx, 5*time.Second)
+ mgmCtx, cancel := context.WithTimeout(c.ctx, ConnectTimeout)
defer cancel()
resp, err := c.realClient.Login(mgmCtx, &proto.EncryptedMessage{
WgPubKey: c.key.PublicKey().String(),
@@ -474,5 +476,9 @@ func infoToMetaData(info *system.Info) *proto.PeerSystemMeta {
SysSerialNumber: info.SystemSerialNumber,
SysManufacturer: info.SystemManufacturer,
SysProductName: info.SystemProductName,
+ Environment: &proto.Environment{
+ Cloud: info.Environment.Cloud,
+ Platform: info.Environment.Platform,
+ },
}
}
diff --git a/management/cmd/management.go b/management/cmd/management.go
index cea8dfae9..d2f91829e 100644
--- a/management/cmd/management.go
+++ b/management/cmd/management.go
@@ -43,6 +43,7 @@ import (
"github.com/netbirdio/netbird/management/server/metrics"
"github.com/netbirdio/netbird/management/server/telemetry"
"github.com/netbirdio/netbird/util"
+ "github.com/netbirdio/netbird/version"
)
// ManagementLegacyPort is the port that was used before by the Management gRPC server.
@@ -166,13 +167,15 @@ var (
geo, err := geolocation.NewGeolocation(config.Datadir)
if err != nil {
- log.Warnf("could not initialize geo location service, we proceed without geo support")
+ log.Warnf("could not initialize geo location service: %v, we proceed without geo support", err)
} else {
log.Infof("geo location service has been initialized from %s", config.Datadir)
}
- integratedPeerApproval := integrations.NewIntegratedApproval()
-
+ integratedPeerApproval, err := integrations.NewIntegratedApproval(eventStore)
+ if err != nil {
+ return fmt.Errorf("failed to initialize integrated peer approval: %v", err)
+ }
accountManager, err := server.BuildManager(store, peersUpdateManager, idpManager, mgmtSingleAccModeDomain,
dnsDomain, eventStore, geo, userDeleteFromIDPEnabled, integratedPeerApproval)
if err != nil {
@@ -317,12 +320,14 @@ var (
}
}
+ log.Infof("management server version %s", version.NetbirdVersion())
log.Infof("running HTTP server and gRPC server on the same port: %s", listener.Addr().String())
serveGRPCWithHTTP(listener, rootHandler, tlsEnabled)
SetupCloseHandler()
<-stopCh
+ integratedPeerApproval.Stop()
if geo != nil {
_ = geo.Stop()
}
diff --git a/management/proto/management.pb.go b/management/proto/management.pb.go
index aa5122909..18077ea89 100644
--- a/management/proto/management.pb.go
+++ b/management/proto/management.pb.go
@@ -73,7 +73,7 @@ func (x HostConfig_Protocol) Number() protoreflect.EnumNumber {
// Deprecated: Use HostConfig_Protocol.Descriptor instead.
func (HostConfig_Protocol) EnumDescriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{10, 0}
+ return file_management_proto_rawDescGZIP(), []int{11, 0}
}
type DeviceAuthorizationFlowProvider int32
@@ -116,7 +116,7 @@ func (x DeviceAuthorizationFlowProvider) Number() protoreflect.EnumNumber {
// Deprecated: Use DeviceAuthorizationFlowProvider.Descriptor instead.
func (DeviceAuthorizationFlowProvider) EnumDescriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{17, 0}
+ return file_management_proto_rawDescGZIP(), []int{18, 0}
}
type FirewallRuleDirection int32
@@ -162,7 +162,7 @@ func (x FirewallRuleDirection) Number() protoreflect.EnumNumber {
// Deprecated: Use FirewallRuleDirection.Descriptor instead.
func (FirewallRuleDirection) EnumDescriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{27, 0}
+ return file_management_proto_rawDescGZIP(), []int{28, 0}
}
type FirewallRuleAction int32
@@ -208,7 +208,7 @@ func (x FirewallRuleAction) Number() protoreflect.EnumNumber {
// Deprecated: Use FirewallRuleAction.Descriptor instead.
func (FirewallRuleAction) EnumDescriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{27, 1}
+ return file_management_proto_rawDescGZIP(), []int{28, 1}
}
type FirewallRuleProtocol int32
@@ -263,7 +263,7 @@ func (x FirewallRuleProtocol) Number() protoreflect.EnumNumber {
// Deprecated: Use FirewallRuleProtocol.Descriptor instead.
func (FirewallRuleProtocol) EnumDescriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{27, 2}
+ return file_management_proto_rawDescGZIP(), []int{28, 2}
}
type EncryptedMessage struct {
@@ -589,6 +589,64 @@ func (x *PeerKeys) GetWgPubKey() []byte {
return nil
}
+// Environment is part of the PeerSystemMeta and describes the environment the agent is running in.
+type Environment struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // cloud is the cloud provider the agent is running in if applicable.
+ Cloud string `protobuf:"bytes,1,opt,name=cloud,proto3" json:"cloud,omitempty"`
+ // platform is the platform the agent is running on if applicable.
+ Platform string `protobuf:"bytes,2,opt,name=platform,proto3" json:"platform,omitempty"`
+}
+
+func (x *Environment) Reset() {
+ *x = Environment{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_management_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Environment) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Environment) ProtoMessage() {}
+
+func (x *Environment) ProtoReflect() protoreflect.Message {
+ mi := &file_management_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Environment.ProtoReflect.Descriptor instead.
+func (*Environment) Descriptor() ([]byte, []int) {
+ return file_management_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *Environment) GetCloud() string {
+ if x != nil {
+ return x.Cloud
+ }
+ return ""
+}
+
+func (x *Environment) GetPlatform() string {
+ if x != nil {
+ return x.Platform
+ }
+ return ""
+}
+
// PeerSystemMeta is machine meta data like OS and version.
type PeerSystemMeta struct {
state protoimpl.MessageState
@@ -609,12 +667,13 @@ type PeerSystemMeta struct {
SysSerialNumber string `protobuf:"bytes,12,opt,name=sysSerialNumber,proto3" json:"sysSerialNumber,omitempty"`
SysProductName string `protobuf:"bytes,13,opt,name=sysProductName,proto3" json:"sysProductName,omitempty"`
SysManufacturer string `protobuf:"bytes,14,opt,name=sysManufacturer,proto3" json:"sysManufacturer,omitempty"`
+ Environment *Environment `protobuf:"bytes,15,opt,name=environment,proto3" json:"environment,omitempty"`
}
func (x *PeerSystemMeta) Reset() {
*x = PeerSystemMeta{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[5]
+ mi := &file_management_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -627,7 +686,7 @@ func (x *PeerSystemMeta) String() string {
func (*PeerSystemMeta) ProtoMessage() {}
func (x *PeerSystemMeta) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[5]
+ mi := &file_management_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -640,7 +699,7 @@ func (x *PeerSystemMeta) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeerSystemMeta.ProtoReflect.Descriptor instead.
func (*PeerSystemMeta) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{5}
+ return file_management_proto_rawDescGZIP(), []int{6}
}
func (x *PeerSystemMeta) GetHostname() string {
@@ -741,6 +800,13 @@ func (x *PeerSystemMeta) GetSysManufacturer() string {
return ""
}
+func (x *PeerSystemMeta) GetEnvironment() *Environment {
+ if x != nil {
+ return x.Environment
+ }
+ return nil
+}
+
type LoginResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -755,7 +821,7 @@ type LoginResponse struct {
func (x *LoginResponse) Reset() {
*x = LoginResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[6]
+ mi := &file_management_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -768,7 +834,7 @@ func (x *LoginResponse) String() string {
func (*LoginResponse) ProtoMessage() {}
func (x *LoginResponse) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[6]
+ mi := &file_management_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -781,7 +847,7 @@ func (x *LoginResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead.
func (*LoginResponse) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{6}
+ return file_management_proto_rawDescGZIP(), []int{7}
}
func (x *LoginResponse) GetWiretrusteeConfig() *WiretrusteeConfig {
@@ -814,7 +880,7 @@ type ServerKeyResponse struct {
func (x *ServerKeyResponse) Reset() {
*x = ServerKeyResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[7]
+ mi := &file_management_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -827,7 +893,7 @@ func (x *ServerKeyResponse) String() string {
func (*ServerKeyResponse) ProtoMessage() {}
func (x *ServerKeyResponse) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[7]
+ mi := &file_management_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -840,7 +906,7 @@ func (x *ServerKeyResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ServerKeyResponse.ProtoReflect.Descriptor instead.
func (*ServerKeyResponse) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{7}
+ return file_management_proto_rawDescGZIP(), []int{8}
}
func (x *ServerKeyResponse) GetKey() string {
@@ -873,7 +939,7 @@ type Empty struct {
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[8]
+ mi := &file_management_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -886,7 +952,7 @@ func (x *Empty) String() string {
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[8]
+ mi := &file_management_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -899,7 +965,7 @@ func (x *Empty) ProtoReflect() protoreflect.Message {
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{8}
+ return file_management_proto_rawDescGZIP(), []int{9}
}
// WiretrusteeConfig is a common configuration of any Wiretrustee peer. It contains STUN, TURN, Signal and Management servers configurations
@@ -919,7 +985,7 @@ type WiretrusteeConfig struct {
func (x *WiretrusteeConfig) Reset() {
*x = WiretrusteeConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[9]
+ mi := &file_management_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -932,7 +998,7 @@ func (x *WiretrusteeConfig) String() string {
func (*WiretrusteeConfig) ProtoMessage() {}
func (x *WiretrusteeConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[9]
+ mi := &file_management_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -945,7 +1011,7 @@ func (x *WiretrusteeConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use WiretrusteeConfig.ProtoReflect.Descriptor instead.
func (*WiretrusteeConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{9}
+ return file_management_proto_rawDescGZIP(), []int{10}
}
func (x *WiretrusteeConfig) GetStuns() []*HostConfig {
@@ -983,7 +1049,7 @@ type HostConfig struct {
func (x *HostConfig) Reset() {
*x = HostConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[10]
+ mi := &file_management_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -996,7 +1062,7 @@ func (x *HostConfig) String() string {
func (*HostConfig) ProtoMessage() {}
func (x *HostConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[10]
+ mi := &file_management_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1009,7 +1075,7 @@ func (x *HostConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use HostConfig.ProtoReflect.Descriptor instead.
func (*HostConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{10}
+ return file_management_proto_rawDescGZIP(), []int{11}
}
func (x *HostConfig) GetUri() string {
@@ -1041,7 +1107,7 @@ type ProtectedHostConfig struct {
func (x *ProtectedHostConfig) Reset() {
*x = ProtectedHostConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[11]
+ mi := &file_management_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1054,7 +1120,7 @@ func (x *ProtectedHostConfig) String() string {
func (*ProtectedHostConfig) ProtoMessage() {}
func (x *ProtectedHostConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[11]
+ mi := &file_management_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1067,7 +1133,7 @@ func (x *ProtectedHostConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProtectedHostConfig.ProtoReflect.Descriptor instead.
func (*ProtectedHostConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{11}
+ return file_management_proto_rawDescGZIP(), []int{12}
}
func (x *ProtectedHostConfig) GetHostConfig() *HostConfig {
@@ -1111,7 +1177,7 @@ type PeerConfig struct {
func (x *PeerConfig) Reset() {
*x = PeerConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[12]
+ mi := &file_management_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1124,7 +1190,7 @@ func (x *PeerConfig) String() string {
func (*PeerConfig) ProtoMessage() {}
func (x *PeerConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[12]
+ mi := &file_management_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1137,7 +1203,7 @@ func (x *PeerConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use PeerConfig.ProtoReflect.Descriptor instead.
func (*PeerConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{12}
+ return file_management_proto_rawDescGZIP(), []int{13}
}
func (x *PeerConfig) GetAddress() string {
@@ -1199,7 +1265,7 @@ type NetworkMap struct {
func (x *NetworkMap) Reset() {
*x = NetworkMap{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[13]
+ mi := &file_management_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1212,7 +1278,7 @@ func (x *NetworkMap) String() string {
func (*NetworkMap) ProtoMessage() {}
func (x *NetworkMap) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[13]
+ mi := &file_management_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1225,7 +1291,7 @@ func (x *NetworkMap) ProtoReflect() protoreflect.Message {
// Deprecated: Use NetworkMap.ProtoReflect.Descriptor instead.
func (*NetworkMap) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{13}
+ return file_management_proto_rawDescGZIP(), []int{14}
}
func (x *NetworkMap) GetSerial() uint64 {
@@ -1311,7 +1377,7 @@ type RemotePeerConfig struct {
func (x *RemotePeerConfig) Reset() {
*x = RemotePeerConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[14]
+ mi := &file_management_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1324,7 +1390,7 @@ func (x *RemotePeerConfig) String() string {
func (*RemotePeerConfig) ProtoMessage() {}
func (x *RemotePeerConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[14]
+ mi := &file_management_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1337,7 +1403,7 @@ func (x *RemotePeerConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use RemotePeerConfig.ProtoReflect.Descriptor instead.
func (*RemotePeerConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{14}
+ return file_management_proto_rawDescGZIP(), []int{15}
}
func (x *RemotePeerConfig) GetWgPubKey() string {
@@ -1384,7 +1450,7 @@ type SSHConfig struct {
func (x *SSHConfig) Reset() {
*x = SSHConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[15]
+ mi := &file_management_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1397,7 +1463,7 @@ func (x *SSHConfig) String() string {
func (*SSHConfig) ProtoMessage() {}
func (x *SSHConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[15]
+ mi := &file_management_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1410,7 +1476,7 @@ func (x *SSHConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use SSHConfig.ProtoReflect.Descriptor instead.
func (*SSHConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{15}
+ return file_management_proto_rawDescGZIP(), []int{16}
}
func (x *SSHConfig) GetSshEnabled() bool {
@@ -1437,7 +1503,7 @@ type DeviceAuthorizationFlowRequest struct {
func (x *DeviceAuthorizationFlowRequest) Reset() {
*x = DeviceAuthorizationFlowRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[16]
+ mi := &file_management_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1450,7 +1516,7 @@ func (x *DeviceAuthorizationFlowRequest) String() string {
func (*DeviceAuthorizationFlowRequest) ProtoMessage() {}
func (x *DeviceAuthorizationFlowRequest) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[16]
+ mi := &file_management_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1463,7 +1529,7 @@ func (x *DeviceAuthorizationFlowRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeviceAuthorizationFlowRequest.ProtoReflect.Descriptor instead.
func (*DeviceAuthorizationFlowRequest) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{16}
+ return file_management_proto_rawDescGZIP(), []int{17}
}
// DeviceAuthorizationFlow represents Device Authorization Flow information
@@ -1482,7 +1548,7 @@ type DeviceAuthorizationFlow struct {
func (x *DeviceAuthorizationFlow) Reset() {
*x = DeviceAuthorizationFlow{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[17]
+ mi := &file_management_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1495,7 +1561,7 @@ func (x *DeviceAuthorizationFlow) String() string {
func (*DeviceAuthorizationFlow) ProtoMessage() {}
func (x *DeviceAuthorizationFlow) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[17]
+ mi := &file_management_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1508,7 +1574,7 @@ func (x *DeviceAuthorizationFlow) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeviceAuthorizationFlow.ProtoReflect.Descriptor instead.
func (*DeviceAuthorizationFlow) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{17}
+ return file_management_proto_rawDescGZIP(), []int{18}
}
func (x *DeviceAuthorizationFlow) GetProvider() DeviceAuthorizationFlowProvider {
@@ -1535,7 +1601,7 @@ type PKCEAuthorizationFlowRequest struct {
func (x *PKCEAuthorizationFlowRequest) Reset() {
*x = PKCEAuthorizationFlowRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[18]
+ mi := &file_management_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1548,7 +1614,7 @@ func (x *PKCEAuthorizationFlowRequest) String() string {
func (*PKCEAuthorizationFlowRequest) ProtoMessage() {}
func (x *PKCEAuthorizationFlowRequest) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[18]
+ mi := &file_management_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1561,7 +1627,7 @@ func (x *PKCEAuthorizationFlowRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use PKCEAuthorizationFlowRequest.ProtoReflect.Descriptor instead.
func (*PKCEAuthorizationFlowRequest) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{18}
+ return file_management_proto_rawDescGZIP(), []int{19}
}
// PKCEAuthorizationFlow represents Authorization Code Flow information
@@ -1578,7 +1644,7 @@ type PKCEAuthorizationFlow struct {
func (x *PKCEAuthorizationFlow) Reset() {
*x = PKCEAuthorizationFlow{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[19]
+ mi := &file_management_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1591,7 +1657,7 @@ func (x *PKCEAuthorizationFlow) String() string {
func (*PKCEAuthorizationFlow) ProtoMessage() {}
func (x *PKCEAuthorizationFlow) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[19]
+ mi := &file_management_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1604,7 +1670,7 @@ func (x *PKCEAuthorizationFlow) ProtoReflect() protoreflect.Message {
// Deprecated: Use PKCEAuthorizationFlow.ProtoReflect.Descriptor instead.
func (*PKCEAuthorizationFlow) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{19}
+ return file_management_proto_rawDescGZIP(), []int{20}
}
func (x *PKCEAuthorizationFlow) GetProviderConfig() *ProviderConfig {
@@ -1646,7 +1712,7 @@ type ProviderConfig struct {
func (x *ProviderConfig) Reset() {
*x = ProviderConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[20]
+ mi := &file_management_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1659,7 +1725,7 @@ func (x *ProviderConfig) String() string {
func (*ProviderConfig) ProtoMessage() {}
func (x *ProviderConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[20]
+ mi := &file_management_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1672,7 +1738,7 @@ func (x *ProviderConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use ProviderConfig.ProtoReflect.Descriptor instead.
func (*ProviderConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{20}
+ return file_management_proto_rawDescGZIP(), []int{21}
}
func (x *ProviderConfig) GetClientID() string {
@@ -1763,7 +1829,7 @@ type Route struct {
func (x *Route) Reset() {
*x = Route{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[21]
+ mi := &file_management_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1776,7 +1842,7 @@ func (x *Route) String() string {
func (*Route) ProtoMessage() {}
func (x *Route) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[21]
+ mi := &file_management_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1789,7 +1855,7 @@ func (x *Route) ProtoReflect() protoreflect.Message {
// Deprecated: Use Route.ProtoReflect.Descriptor instead.
func (*Route) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{21}
+ return file_management_proto_rawDescGZIP(), []int{22}
}
func (x *Route) GetID() string {
@@ -1855,7 +1921,7 @@ type DNSConfig struct {
func (x *DNSConfig) Reset() {
*x = DNSConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[22]
+ mi := &file_management_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1868,7 +1934,7 @@ func (x *DNSConfig) String() string {
func (*DNSConfig) ProtoMessage() {}
func (x *DNSConfig) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[22]
+ mi := &file_management_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1881,7 +1947,7 @@ func (x *DNSConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use DNSConfig.ProtoReflect.Descriptor instead.
func (*DNSConfig) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{22}
+ return file_management_proto_rawDescGZIP(), []int{23}
}
func (x *DNSConfig) GetServiceEnable() bool {
@@ -1918,7 +1984,7 @@ type CustomZone struct {
func (x *CustomZone) Reset() {
*x = CustomZone{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[23]
+ mi := &file_management_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1931,7 +1997,7 @@ func (x *CustomZone) String() string {
func (*CustomZone) ProtoMessage() {}
func (x *CustomZone) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[23]
+ mi := &file_management_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1944,7 +2010,7 @@ func (x *CustomZone) ProtoReflect() protoreflect.Message {
// Deprecated: Use CustomZone.ProtoReflect.Descriptor instead.
func (*CustomZone) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{23}
+ return file_management_proto_rawDescGZIP(), []int{24}
}
func (x *CustomZone) GetDomain() string {
@@ -1977,7 +2043,7 @@ type SimpleRecord struct {
func (x *SimpleRecord) Reset() {
*x = SimpleRecord{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[24]
+ mi := &file_management_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1990,7 +2056,7 @@ func (x *SimpleRecord) String() string {
func (*SimpleRecord) ProtoMessage() {}
func (x *SimpleRecord) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[24]
+ mi := &file_management_proto_msgTypes[25]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2003,7 +2069,7 @@ func (x *SimpleRecord) ProtoReflect() protoreflect.Message {
// Deprecated: Use SimpleRecord.ProtoReflect.Descriptor instead.
func (*SimpleRecord) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{24}
+ return file_management_proto_rawDescGZIP(), []int{25}
}
func (x *SimpleRecord) GetName() string {
@@ -2056,7 +2122,7 @@ type NameServerGroup struct {
func (x *NameServerGroup) Reset() {
*x = NameServerGroup{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[25]
+ mi := &file_management_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2069,7 +2135,7 @@ func (x *NameServerGroup) String() string {
func (*NameServerGroup) ProtoMessage() {}
func (x *NameServerGroup) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[25]
+ mi := &file_management_proto_msgTypes[26]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2082,7 +2148,7 @@ func (x *NameServerGroup) ProtoReflect() protoreflect.Message {
// Deprecated: Use NameServerGroup.ProtoReflect.Descriptor instead.
func (*NameServerGroup) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{25}
+ return file_management_proto_rawDescGZIP(), []int{26}
}
func (x *NameServerGroup) GetNameServers() []*NameServer {
@@ -2127,7 +2193,7 @@ type NameServer struct {
func (x *NameServer) Reset() {
*x = NameServer{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[26]
+ mi := &file_management_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2140,7 +2206,7 @@ func (x *NameServer) String() string {
func (*NameServer) ProtoMessage() {}
func (x *NameServer) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[26]
+ mi := &file_management_proto_msgTypes[27]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2153,7 +2219,7 @@ func (x *NameServer) ProtoReflect() protoreflect.Message {
// Deprecated: Use NameServer.ProtoReflect.Descriptor instead.
func (*NameServer) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{26}
+ return file_management_proto_rawDescGZIP(), []int{27}
}
func (x *NameServer) GetIP() string {
@@ -2193,7 +2259,7 @@ type FirewallRule struct {
func (x *FirewallRule) Reset() {
*x = FirewallRule{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[27]
+ mi := &file_management_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2206,7 +2272,7 @@ func (x *FirewallRule) String() string {
func (*FirewallRule) ProtoMessage() {}
func (x *FirewallRule) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[27]
+ mi := &file_management_proto_msgTypes[28]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2219,7 +2285,7 @@ func (x *FirewallRule) ProtoReflect() protoreflect.Message {
// Deprecated: Use FirewallRule.ProtoReflect.Descriptor instead.
func (*FirewallRule) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{27}
+ return file_management_proto_rawDescGZIP(), []int{28}
}
func (x *FirewallRule) GetPeerIP() string {
@@ -2269,7 +2335,7 @@ type NetworkAddress struct {
func (x *NetworkAddress) Reset() {
*x = NetworkAddress{}
if protoimpl.UnsafeEnabled {
- mi := &file_management_proto_msgTypes[28]
+ mi := &file_management_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2282,7 +2348,7 @@ func (x *NetworkAddress) String() string {
func (*NetworkAddress) ProtoMessage() {}
func (x *NetworkAddress) ProtoReflect() protoreflect.Message {
- mi := &file_management_proto_msgTypes[28]
+ mi := &file_management_proto_msgTypes[29]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2295,7 +2361,7 @@ func (x *NetworkAddress) ProtoReflect() protoreflect.Message {
// Deprecated: Use NetworkAddress.ProtoReflect.Descriptor instead.
func (*NetworkAddress) Descriptor() ([]byte, []int) {
- return file_management_proto_rawDescGZIP(), []int{28}
+ return file_management_proto_rawDescGZIP(), []int{29}
}
func (x *NetworkAddress) GetNetIP() string {
@@ -2360,291 +2426,299 @@ var file_management_proto_rawDesc = []byte{
0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x73, 0x68, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12,
0x1a, 0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0c, 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0xee, 0x03, 0x0a, 0x0e,
- 0x50, 0x65, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a,
- 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f,
- 0x4f, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x12, 0x16,
- 0x0a, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
- 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c,
- 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c,
- 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x53, 0x18, 0x06, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x02, 0x4f, 0x53, 0x12, 0x2e, 0x0a, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72,
- 0x75, 0x73, 0x74, 0x65, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x56,
- 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x69, 0x56, 0x65, 0x72, 0x73,
- 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x69, 0x56, 0x65, 0x72,
- 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x56, 0x65,
- 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6b, 0x65, 0x72,
- 0x6e, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x53,
- 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f,
- 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x77,
- 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
- 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x10,
- 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
- 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x79, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x79, 0x73, 0x53, 0x65,
- 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x79,
- 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0e, 0x73, 0x79, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61,
- 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x79, 0x73, 0x4d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63,
- 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x79, 0x73,
- 0x4d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x22, 0x94, 0x01, 0x0a,
- 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b,
- 0x0a, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
- 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74,
- 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72,
- 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x0a, 0x70,
- 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65,
- 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x22, 0x79, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78,
- 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72,
- 0x65, 0x73, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x07,
- 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xa8, 0x01, 0x0a, 0x11, 0x57, 0x69, 0x72, 0x65,
- 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a,
- 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d,
- 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x05, 0x74,
- 0x75, 0x72, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e,
- 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65,
- 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x74, 0x75, 0x72,
- 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
- 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e,
- 0x61, 0x6c, 0x22, 0x98, 0x01, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
- 0x75, 0x72, 0x69, 0x12, 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72,
- 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
- 0x22, 0x3b, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03,
- 0x55, 0x44, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x08,
- 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50,
- 0x53, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x54, 0x4c, 0x53, 0x10, 0x04, 0x22, 0x7d, 0x0a,
- 0x13, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04,
- 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72,
- 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x81, 0x01, 0x0a,
- 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64,
- 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x03, 0x64, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e,
- 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x52, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04,
- 0x66, 0x71, 0x64, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e,
- 0x22, 0xe2, 0x03, 0x0a, 0x0a, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x12,
- 0x16, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x06, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43,
+ 0x0c, 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x3f, 0x0a, 0x0b, 0x45,
+ 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c,
+ 0x6f, 0x75, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+ 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xa9, 0x04, 0x0a,
+ 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x12,
+ 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67,
+ 0x6f, 0x4f, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x12,
+ 0x16, 0x0a, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70,
+ 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
+ 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x53, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x53, 0x12, 0x2e, 0x0a, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74,
+ 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x69, 0x56, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x69, 0x56, 0x65,
+ 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x56,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6b, 0x65,
+ 0x72, 0x6e, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x4f,
+ 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+ 0x4f, 0x53, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x10, 0x6e, 0x65, 0x74,
+ 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0b, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
+ 0x10, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65,
+ 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x79, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75,
+ 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x79, 0x73, 0x53,
+ 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x73,
+ 0x79, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0d, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x79, 0x73, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e,
+ 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x79, 0x73, 0x4d, 0x61, 0x6e, 0x75, 0x66, 0x61,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x79,
+ 0x73, 0x4d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x12, 0x39, 0x0a,
+ 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
+ 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x76,
+ 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x67,
+ 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x11, 0x77, 0x69,
+ 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65,
+ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61,
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x3e, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
- 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12,
- 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73,
- 0x45, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6d,
- 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12,
- 0x29, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x6f, 0x75,
- 0x74, 0x65, 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x44, 0x4e,
- 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e,
- 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x4e, 0x53, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x40, 0x0a, 0x0c, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18,
- 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x52, 0x0c, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72,
- 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c,
- 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75,
- 0x6c, 0x65, 0x52, 0x0d, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65,
- 0x73, 0x12, 0x32, 0x0a, 0x14, 0x66, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c,
- 0x65, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
+ 0x79, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65,
+ 0x73, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74,
+ 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d,
+ 0x70, 0x74, 0x79, 0x22, 0xa8, 0x01, 0x0a, 0x11, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73,
+ 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x73, 0x74, 0x75,
+ 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x52, 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73,
+ 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73,
+ 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x12, 0x2e,
+ 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x22, 0x98,
+ 0x01, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
+ 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12,
+ 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48,
+ 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
+ 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x3b, 0x0a, 0x08,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10,
+ 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54,
+ 0x54, 0x50, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x03, 0x12,
+ 0x08, 0x0a, 0x04, 0x44, 0x54, 0x4c, 0x53, 0x10, 0x04, 0x22, 0x7d, 0x0a, 0x13, 0x50, 0x72, 0x6f,
+ 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x12, 0x36, 0x0a, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x68, 0x6f,
+ 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08,
+ 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+ 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x0a, 0x50, 0x65, 0x65,
+ 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
+ 0x64, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x73,
+ 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x64, 0x6e,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0xe2, 0x03, 0x0a,
+ 0x0a, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x53,
+ 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x53, 0x65, 0x72,
+ 0x69, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+ 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0b, 0x72,
+ 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65,
+ 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b,
+ 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x72,
+ 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74,
+ 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50,
+ 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x29, 0x0a, 0x06, 0x52,
+ 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x61,
+ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x06,
+ 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
+ 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x52, 0x09, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x0c, 0x6f,
+ 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52,
+ 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+ 0x0c, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x3e, 0x0a,
+ 0x0d, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x08,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d,
+ 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x0a,
0x14, 0x66, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x49, 0x73,
- 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x97, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65,
- 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x67,
- 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x67,
- 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
- 0x64, 0x49, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f,
- 0x77, 0x65, 0x64, 0x49, 0x70, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
- 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x52, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66,
- 0x71, 0x64, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22,
- 0x49, 0x0a, 0x09, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a,
- 0x73, 0x73, 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0a, 0x73, 0x73, 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09,
- 0x73, 0x73, 0x68, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
- 0x09, 0x73, 0x73, 0x68, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x20, 0x0a, 0x1e, 0x44, 0x65,
- 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xbf, 0x01, 0x0a,
- 0x17, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76,
- 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x6d, 0x61, 0x6e,
- 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75,
- 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x2e,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,
- 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e,
- 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x16, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
- 0x65, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x00, 0x22, 0x1e,
- 0x0a, 0x1c, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5b,
- 0x0a, 0x15, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x42, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f,
- 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x50, 0x72, 0x6f,
- 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xea, 0x02, 0x0a, 0x0e,
- 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a,
- 0x0a, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x6c,
- 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16,
- 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
- 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e,
- 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e,
- 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68,
- 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
- 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69,
- 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f,
- 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
- 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70,
- 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1e,
- 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x49, 0x44, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x0a, 0x55, 0x73, 0x65, 0x49, 0x44, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x34,
- 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45,
- 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x41,
- 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70,
- 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
- 0x55, 0x52, 0x4c, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, 0x64, 0x69,
- 0x72, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75,
- 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
- 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x20, 0x0a, 0x0b,
- 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12,
- 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65,
- 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61,
- 0x73, 0x71, 0x75, 0x65, 0x72, 0x61, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
- 0x4d, 0x61, 0x73, 0x71, 0x75, 0x65, 0x72, 0x61, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x65,
- 0x74, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x65, 0x74, 0x49, 0x44,
- 0x22, 0xb4, 0x01, 0x0a, 0x09, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24,
- 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b,
- 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
- 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x10, 0x4e, 0x61, 0x6d,
- 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x38, 0x0a,
- 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
- 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x0b, 0x43, 0x75, 0x73, 0x74,
- 0x6f, 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x22, 0x58, 0x0a, 0x0a, 0x43, 0x75, 0x73, 0x74, 0x6f,
- 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x32, 0x0a,
- 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18,
- 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x69, 0x6d, 0x70,
- 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
- 0x73, 0x22, 0x74, 0x0a, 0x0c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72,
- 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x43, 0x6c, 0x61,
- 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12,
- 0x10, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x54, 0x54,
- 0x4c, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x05, 0x52, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb3, 0x01, 0x0a, 0x0f, 0x4e, 0x61, 0x6d, 0x65,
- 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x38, 0x0a, 0x0b, 0x4e,
- 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x61,
- 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12,
- 0x18, 0x0a, 0x07, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
- 0x52, 0x07, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x65, 0x61,
- 0x72, 0x63, 0x68, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44,
- 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x48, 0x0a,
- 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x49,
- 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x50, 0x12, 0x16, 0x0a, 0x06, 0x4e,
- 0x53, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x4e, 0x53, 0x54,
- 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xf0, 0x02, 0x0a, 0x0c, 0x46, 0x69, 0x72, 0x65,
- 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72,
- 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50,
- 0x12, 0x40, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x64, 0x69,
- 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
- 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x61, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x50,
- 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e,
- 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77,
- 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
- 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f,
- 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x1c,
- 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x49,
- 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x22, 0x1e, 0x0a, 0x06,
- 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54,
- 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x22, 0x3c, 0x0a, 0x08,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
- 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x07,
- 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x03,
- 0x12, 0x08, 0x0a, 0x04, 0x49, 0x43, 0x4d, 0x50, 0x10, 0x04, 0x22, 0x38, 0x0a, 0x0e, 0x4e, 0x65,
- 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05,
- 0x6e, 0x65, 0x74, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x65, 0x74,
- 0x49, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x03, 0x6d, 0x61, 0x63, 0x32, 0xd1, 0x03, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
- 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f,
- 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x45, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x66, 0x69, 0x72,
+ 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74,
+ 0x79, 0x22, 0x97, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b,
+ 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49, 0x70, 0x73,
+ 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49,
+ 0x70, 0x73, 0x12, 0x33, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x73, 0x73,
+ 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x64, 0x6e, 0x22, 0x49, 0x0a, 0x09, 0x53,
+ 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x73, 0x68, 0x45,
+ 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x73,
+ 0x68, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x73, 0x68, 0x50,
+ 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x73, 0x68,
+ 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x20, 0x0a, 0x1e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f,
+ 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xbf, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x76,
+ 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x76,
+ 0x69, 0x64, 0x65, 0x72, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x42,
+ 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x22, 0x16, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x0a,
+ 0x0a, 0x06, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x00, 0x22, 0x1e, 0x0a, 0x1c, 0x50, 0x4b,
+ 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46,
+ 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5b, 0x0a, 0x15, 0x50, 0x4b,
+ 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46,
+ 0x6c, 0x6f, 0x77, 0x12, 0x42, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61,
+ 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xea, 0x02, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76,
+ 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x44, 0x6f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x2e,
+ 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x64, 0x70,
+ 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x44, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x24,
+ 0x0a, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70,
+ 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x55, 0x73,
+ 0x65, 0x49, 0x44, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
+ 0x55, 0x73, 0x65, 0x49, 0x44, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x34, 0x0a, 0x15, 0x41, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f,
+ 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
+ 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x73,
+ 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x55, 0x52, 0x4c, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x0e,
+ 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x18,
+ 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x4e,
+ 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65,
+ 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x16,
+ 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x73, 0x71, 0x75, 0x65,
+ 0x72, 0x61, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x4d, 0x61, 0x73, 0x71,
+ 0x75, 0x65, 0x72, 0x61, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x65, 0x74, 0x49, 0x44, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x65, 0x74, 0x49, 0x44, 0x22, 0xb4, 0x01, 0x0a,
+ 0x09, 0x44, 0x4e, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+ 0x12, 0x47, 0x0a, 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x47, 0x72,
+ 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x61, 0x6e,
+ 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x10, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x43, 0x75, 0x73,
+ 0x74, 0x6f, 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74,
+ 0x6f, 0x6d, 0x5a, 0x6f, 0x6e, 0x65, 0x52, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5a, 0x6f,
+ 0x6e, 0x65, 0x73, 0x22, 0x58, 0x0a, 0x0a, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5a, 0x6f, 0x6e,
+ 0x65, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x32, 0x0a, 0x07, 0x52, 0x65, 0x63,
+ 0x6f, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e,
+ 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65,
+ 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x22, 0x74, 0x0a,
+ 0x0c, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a,
+ 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54,
+ 0x54, 0x4c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x14, 0x0a,
+ 0x05, 0x52, 0x44, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x52, 0x44,
+ 0x61, 0x74, 0x61, 0x22, 0xb3, 0x01, 0x0a, 0x0f, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x38, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x73, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x44,
+ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x44, 0x6f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44,
+ 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x6f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x48, 0x0a, 0x0a, 0x4e, 0x61, 0x6d,
+ 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x50, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x50, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12,
+ 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50,
+ 0x6f, 0x72, 0x74, 0x22, 0xf0, 0x02, 0x0a, 0x0c, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c,
+ 0x52, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x12, 0x40, 0x0a, 0x09,
+ 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72,
+ 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37,
+ 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f,
+ 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65,
+ 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+ 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
+ 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52,
+ 0x75, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x1c, 0x0a, 0x09, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x00, 0x12,
+ 0x07, 0x0a, 0x03, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x22, 0x1e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x10, 0x00, 0x12, 0x08,
+ 0x0a, 0x04, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x22, 0x3c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
+ 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43,
+ 0x50, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04,
+ 0x49, 0x43, 0x4d, 0x50, 0x10, 0x04, 0x22, 0x38, 0x0a, 0x0e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
+ 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x65, 0x74, 0x49,
+ 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x65, 0x74, 0x49, 0x50, 0x12, 0x10,
+ 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, 0x63,
+ 0x32, 0xd1, 0x03, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12,
+ 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63,
+ 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e,
+ 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79,
+ 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a,
+ 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45,
- 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
- 0x00, 0x12, 0x46, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
- 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64,
- 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
- 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74,
- 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
- 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d,
- 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a,
- 0x09, 0x69, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e,
- 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e,
- 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
- 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41,
- 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77,
- 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e,
- 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c,
- 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72,
- 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x58,
- 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
- 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e,
+ 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48,
+ 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
+ 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5a,
+ 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f,
+ 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d,
+ 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70,
+ 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e,
0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65,
- 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d,
- 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x18, 0x47, 0x65,
+ 0x74, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -2660,7 +2734,7 @@ func file_management_proto_rawDescGZIP() []byte {
}
var file_management_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
+var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
var file_management_proto_goTypes = []interface{}{
(HostConfig_Protocol)(0), // 0: management.HostConfig.Protocol
(DeviceAuthorizationFlowProvider)(0), // 1: management.DeviceAuthorizationFlow.provider
@@ -2672,83 +2746,85 @@ var file_management_proto_goTypes = []interface{}{
(*SyncResponse)(nil), // 7: management.SyncResponse
(*LoginRequest)(nil), // 8: management.LoginRequest
(*PeerKeys)(nil), // 9: management.PeerKeys
- (*PeerSystemMeta)(nil), // 10: management.PeerSystemMeta
- (*LoginResponse)(nil), // 11: management.LoginResponse
- (*ServerKeyResponse)(nil), // 12: management.ServerKeyResponse
- (*Empty)(nil), // 13: management.Empty
- (*WiretrusteeConfig)(nil), // 14: management.WiretrusteeConfig
- (*HostConfig)(nil), // 15: management.HostConfig
- (*ProtectedHostConfig)(nil), // 16: management.ProtectedHostConfig
- (*PeerConfig)(nil), // 17: management.PeerConfig
- (*NetworkMap)(nil), // 18: management.NetworkMap
- (*RemotePeerConfig)(nil), // 19: management.RemotePeerConfig
- (*SSHConfig)(nil), // 20: management.SSHConfig
- (*DeviceAuthorizationFlowRequest)(nil), // 21: management.DeviceAuthorizationFlowRequest
- (*DeviceAuthorizationFlow)(nil), // 22: management.DeviceAuthorizationFlow
- (*PKCEAuthorizationFlowRequest)(nil), // 23: management.PKCEAuthorizationFlowRequest
- (*PKCEAuthorizationFlow)(nil), // 24: management.PKCEAuthorizationFlow
- (*ProviderConfig)(nil), // 25: management.ProviderConfig
- (*Route)(nil), // 26: management.Route
- (*DNSConfig)(nil), // 27: management.DNSConfig
- (*CustomZone)(nil), // 28: management.CustomZone
- (*SimpleRecord)(nil), // 29: management.SimpleRecord
- (*NameServerGroup)(nil), // 30: management.NameServerGroup
- (*NameServer)(nil), // 31: management.NameServer
- (*FirewallRule)(nil), // 32: management.FirewallRule
- (*NetworkAddress)(nil), // 33: management.NetworkAddress
- (*timestamppb.Timestamp)(nil), // 34: google.protobuf.Timestamp
+ (*Environment)(nil), // 10: management.Environment
+ (*PeerSystemMeta)(nil), // 11: management.PeerSystemMeta
+ (*LoginResponse)(nil), // 12: management.LoginResponse
+ (*ServerKeyResponse)(nil), // 13: management.ServerKeyResponse
+ (*Empty)(nil), // 14: management.Empty
+ (*WiretrusteeConfig)(nil), // 15: management.WiretrusteeConfig
+ (*HostConfig)(nil), // 16: management.HostConfig
+ (*ProtectedHostConfig)(nil), // 17: management.ProtectedHostConfig
+ (*PeerConfig)(nil), // 18: management.PeerConfig
+ (*NetworkMap)(nil), // 19: management.NetworkMap
+ (*RemotePeerConfig)(nil), // 20: management.RemotePeerConfig
+ (*SSHConfig)(nil), // 21: management.SSHConfig
+ (*DeviceAuthorizationFlowRequest)(nil), // 22: management.DeviceAuthorizationFlowRequest
+ (*DeviceAuthorizationFlow)(nil), // 23: management.DeviceAuthorizationFlow
+ (*PKCEAuthorizationFlowRequest)(nil), // 24: management.PKCEAuthorizationFlowRequest
+ (*PKCEAuthorizationFlow)(nil), // 25: management.PKCEAuthorizationFlow
+ (*ProviderConfig)(nil), // 26: management.ProviderConfig
+ (*Route)(nil), // 27: management.Route
+ (*DNSConfig)(nil), // 28: management.DNSConfig
+ (*CustomZone)(nil), // 29: management.CustomZone
+ (*SimpleRecord)(nil), // 30: management.SimpleRecord
+ (*NameServerGroup)(nil), // 31: management.NameServerGroup
+ (*NameServer)(nil), // 32: management.NameServer
+ (*FirewallRule)(nil), // 33: management.FirewallRule
+ (*NetworkAddress)(nil), // 34: management.NetworkAddress
+ (*timestamppb.Timestamp)(nil), // 35: google.protobuf.Timestamp
}
var file_management_proto_depIdxs = []int32{
- 14, // 0: management.SyncResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
- 17, // 1: management.SyncResponse.peerConfig:type_name -> management.PeerConfig
- 19, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig
- 18, // 3: management.SyncResponse.NetworkMap:type_name -> management.NetworkMap
- 10, // 4: management.LoginRequest.meta:type_name -> management.PeerSystemMeta
+ 15, // 0: management.SyncResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
+ 18, // 1: management.SyncResponse.peerConfig:type_name -> management.PeerConfig
+ 20, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig
+ 19, // 3: management.SyncResponse.NetworkMap:type_name -> management.NetworkMap
+ 11, // 4: management.LoginRequest.meta:type_name -> management.PeerSystemMeta
9, // 5: management.LoginRequest.peerKeys:type_name -> management.PeerKeys
- 33, // 6: management.PeerSystemMeta.networkAddresses:type_name -> management.NetworkAddress
- 14, // 7: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
- 17, // 8: management.LoginResponse.peerConfig:type_name -> management.PeerConfig
- 34, // 9: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp
- 15, // 10: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig
- 16, // 11: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig
- 15, // 12: management.WiretrusteeConfig.signal:type_name -> management.HostConfig
- 0, // 13: management.HostConfig.protocol:type_name -> management.HostConfig.Protocol
- 15, // 14: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig
- 20, // 15: management.PeerConfig.sshConfig:type_name -> management.SSHConfig
- 17, // 16: management.NetworkMap.peerConfig:type_name -> management.PeerConfig
- 19, // 17: management.NetworkMap.remotePeers:type_name -> management.RemotePeerConfig
- 26, // 18: management.NetworkMap.Routes:type_name -> management.Route
- 27, // 19: management.NetworkMap.DNSConfig:type_name -> management.DNSConfig
- 19, // 20: management.NetworkMap.offlinePeers:type_name -> management.RemotePeerConfig
- 32, // 21: management.NetworkMap.FirewallRules:type_name -> management.FirewallRule
- 20, // 22: management.RemotePeerConfig.sshConfig:type_name -> management.SSHConfig
- 1, // 23: management.DeviceAuthorizationFlow.Provider:type_name -> management.DeviceAuthorizationFlow.provider
- 25, // 24: management.DeviceAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
- 25, // 25: management.PKCEAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
- 30, // 26: management.DNSConfig.NameServerGroups:type_name -> management.NameServerGroup
- 28, // 27: management.DNSConfig.CustomZones:type_name -> management.CustomZone
- 29, // 28: management.CustomZone.Records:type_name -> management.SimpleRecord
- 31, // 29: management.NameServerGroup.NameServers:type_name -> management.NameServer
- 2, // 30: management.FirewallRule.Direction:type_name -> management.FirewallRule.direction
- 3, // 31: management.FirewallRule.Action:type_name -> management.FirewallRule.action
- 4, // 32: management.FirewallRule.Protocol:type_name -> management.FirewallRule.protocol
- 5, // 33: management.ManagementService.Login:input_type -> management.EncryptedMessage
- 5, // 34: management.ManagementService.Sync:input_type -> management.EncryptedMessage
- 13, // 35: management.ManagementService.GetServerKey:input_type -> management.Empty
- 13, // 36: management.ManagementService.isHealthy:input_type -> management.Empty
- 5, // 37: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage
- 5, // 38: management.ManagementService.GetPKCEAuthorizationFlow:input_type -> management.EncryptedMessage
- 5, // 39: management.ManagementService.Login:output_type -> management.EncryptedMessage
- 5, // 40: management.ManagementService.Sync:output_type -> management.EncryptedMessage
- 12, // 41: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse
- 13, // 42: management.ManagementService.isHealthy:output_type -> management.Empty
- 5, // 43: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage
- 5, // 44: management.ManagementService.GetPKCEAuthorizationFlow:output_type -> management.EncryptedMessage
- 39, // [39:45] is the sub-list for method output_type
- 33, // [33:39] is the sub-list for method input_type
- 33, // [33:33] is the sub-list for extension type_name
- 33, // [33:33] is the sub-list for extension extendee
- 0, // [0:33] is the sub-list for field type_name
+ 34, // 6: management.PeerSystemMeta.networkAddresses:type_name -> management.NetworkAddress
+ 10, // 7: management.PeerSystemMeta.environment:type_name -> management.Environment
+ 15, // 8: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig
+ 18, // 9: management.LoginResponse.peerConfig:type_name -> management.PeerConfig
+ 35, // 10: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp
+ 16, // 11: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig
+ 17, // 12: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig
+ 16, // 13: management.WiretrusteeConfig.signal:type_name -> management.HostConfig
+ 0, // 14: management.HostConfig.protocol:type_name -> management.HostConfig.Protocol
+ 16, // 15: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig
+ 21, // 16: management.PeerConfig.sshConfig:type_name -> management.SSHConfig
+ 18, // 17: management.NetworkMap.peerConfig:type_name -> management.PeerConfig
+ 20, // 18: management.NetworkMap.remotePeers:type_name -> management.RemotePeerConfig
+ 27, // 19: management.NetworkMap.Routes:type_name -> management.Route
+ 28, // 20: management.NetworkMap.DNSConfig:type_name -> management.DNSConfig
+ 20, // 21: management.NetworkMap.offlinePeers:type_name -> management.RemotePeerConfig
+ 33, // 22: management.NetworkMap.FirewallRules:type_name -> management.FirewallRule
+ 21, // 23: management.RemotePeerConfig.sshConfig:type_name -> management.SSHConfig
+ 1, // 24: management.DeviceAuthorizationFlow.Provider:type_name -> management.DeviceAuthorizationFlow.provider
+ 26, // 25: management.DeviceAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
+ 26, // 26: management.PKCEAuthorizationFlow.ProviderConfig:type_name -> management.ProviderConfig
+ 31, // 27: management.DNSConfig.NameServerGroups:type_name -> management.NameServerGroup
+ 29, // 28: management.DNSConfig.CustomZones:type_name -> management.CustomZone
+ 30, // 29: management.CustomZone.Records:type_name -> management.SimpleRecord
+ 32, // 30: management.NameServerGroup.NameServers:type_name -> management.NameServer
+ 2, // 31: management.FirewallRule.Direction:type_name -> management.FirewallRule.direction
+ 3, // 32: management.FirewallRule.Action:type_name -> management.FirewallRule.action
+ 4, // 33: management.FirewallRule.Protocol:type_name -> management.FirewallRule.protocol
+ 5, // 34: management.ManagementService.Login:input_type -> management.EncryptedMessage
+ 5, // 35: management.ManagementService.Sync:input_type -> management.EncryptedMessage
+ 14, // 36: management.ManagementService.GetServerKey:input_type -> management.Empty
+ 14, // 37: management.ManagementService.isHealthy:input_type -> management.Empty
+ 5, // 38: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage
+ 5, // 39: management.ManagementService.GetPKCEAuthorizationFlow:input_type -> management.EncryptedMessage
+ 5, // 40: management.ManagementService.Login:output_type -> management.EncryptedMessage
+ 5, // 41: management.ManagementService.Sync:output_type -> management.EncryptedMessage
+ 13, // 42: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse
+ 14, // 43: management.ManagementService.isHealthy:output_type -> management.Empty
+ 5, // 44: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage
+ 5, // 45: management.ManagementService.GetPKCEAuthorizationFlow:output_type -> management.EncryptedMessage
+ 40, // [40:46] is the sub-list for method output_type
+ 34, // [34:40] is the sub-list for method input_type
+ 34, // [34:34] is the sub-list for extension type_name
+ 34, // [34:34] is the sub-list for extension extendee
+ 0, // [0:34] is the sub-list for field type_name
}
func init() { file_management_proto_init() }
@@ -2818,7 +2894,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PeerSystemMeta); i {
+ switch v := v.(*Environment); i {
case 0:
return &v.state
case 1:
@@ -2830,7 +2906,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*LoginResponse); i {
+ switch v := v.(*PeerSystemMeta); i {
case 0:
return &v.state
case 1:
@@ -2842,7 +2918,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ServerKeyResponse); i {
+ switch v := v.(*LoginResponse); i {
case 0:
return &v.state
case 1:
@@ -2854,7 +2930,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Empty); i {
+ switch v := v.(*ServerKeyResponse); i {
case 0:
return &v.state
case 1:
@@ -2866,7 +2942,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WiretrusteeConfig); i {
+ switch v := v.(*Empty); i {
case 0:
return &v.state
case 1:
@@ -2878,7 +2954,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*HostConfig); i {
+ switch v := v.(*WiretrusteeConfig); i {
case 0:
return &v.state
case 1:
@@ -2890,7 +2966,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ProtectedHostConfig); i {
+ switch v := v.(*HostConfig); i {
case 0:
return &v.state
case 1:
@@ -2902,7 +2978,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PeerConfig); i {
+ switch v := v.(*ProtectedHostConfig); i {
case 0:
return &v.state
case 1:
@@ -2914,7 +2990,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*NetworkMap); i {
+ switch v := v.(*PeerConfig); i {
case 0:
return &v.state
case 1:
@@ -2926,7 +3002,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RemotePeerConfig); i {
+ switch v := v.(*NetworkMap); i {
case 0:
return &v.state
case 1:
@@ -2938,7 +3014,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SSHConfig); i {
+ switch v := v.(*RemotePeerConfig); i {
case 0:
return &v.state
case 1:
@@ -2950,7 +3026,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*DeviceAuthorizationFlowRequest); i {
+ switch v := v.(*SSHConfig); i {
case 0:
return &v.state
case 1:
@@ -2962,7 +3038,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*DeviceAuthorizationFlow); i {
+ switch v := v.(*DeviceAuthorizationFlowRequest); i {
case 0:
return &v.state
case 1:
@@ -2974,7 +3050,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PKCEAuthorizationFlowRequest); i {
+ switch v := v.(*DeviceAuthorizationFlow); i {
case 0:
return &v.state
case 1:
@@ -2986,7 +3062,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PKCEAuthorizationFlow); i {
+ switch v := v.(*PKCEAuthorizationFlowRequest); i {
case 0:
return &v.state
case 1:
@@ -2998,7 +3074,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ProviderConfig); i {
+ switch v := v.(*PKCEAuthorizationFlow); i {
case 0:
return &v.state
case 1:
@@ -3010,7 +3086,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Route); i {
+ switch v := v.(*ProviderConfig); i {
case 0:
return &v.state
case 1:
@@ -3022,7 +3098,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*DNSConfig); i {
+ switch v := v.(*Route); i {
case 0:
return &v.state
case 1:
@@ -3034,7 +3110,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CustomZone); i {
+ switch v := v.(*DNSConfig); i {
case 0:
return &v.state
case 1:
@@ -3046,7 +3122,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SimpleRecord); i {
+ switch v := v.(*CustomZone); i {
case 0:
return &v.state
case 1:
@@ -3058,7 +3134,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*NameServerGroup); i {
+ switch v := v.(*SimpleRecord); i {
case 0:
return &v.state
case 1:
@@ -3070,7 +3146,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*NameServer); i {
+ switch v := v.(*NameServerGroup); i {
case 0:
return &v.state
case 1:
@@ -3082,7 +3158,7 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FirewallRule); i {
+ switch v := v.(*NameServer); i {
case 0:
return &v.state
case 1:
@@ -3094,6 +3170,18 @@ func file_management_proto_init() {
}
}
file_management_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FirewallRule); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_management_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NetworkAddress); i {
case 0:
return &v.state
@@ -3112,7 +3200,7 @@ func file_management_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_management_proto_rawDesc,
NumEnums: 5,
- NumMessages: 29,
+ NumMessages: 30,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/management/proto/management.proto b/management/proto/management.proto
index aeadafc2e..2cc0efa22 100644
--- a/management/proto/management.proto
+++ b/management/proto/management.proto
@@ -92,6 +92,14 @@ message PeerKeys {
bytes wgPubKey = 2;
}
+// Environment is part of the PeerSystemMeta and describes the environment the agent is running in.
+message Environment {
+ // cloud is the cloud provider the agent is running in if applicable.
+ string cloud = 1;
+ // platform is the platform the agent is running on if applicable.
+ string platform = 2;
+}
+
// PeerSystemMeta is machine meta data like OS and version.
message PeerSystemMeta {
string hostname = 1;
@@ -108,6 +116,7 @@ message PeerSystemMeta {
string sysSerialNumber = 12;
string sysProductName = 13;
string sysManufacturer = 14;
+ Environment environment = 15;
}
message LoginResponse {
diff --git a/management/server/account.go b/management/server/account.go
index cfa94bead..56d4c262f 100644
--- a/management/server/account.go
+++ b/management/server/account.go
@@ -126,6 +126,7 @@ type AccountManager interface {
SavePostureChecks(accountID, userID string, postureChecks *posture.Checks) error
DeletePostureChecks(accountID, postureChecksID, userID string) error
ListPostureChecks(accountID, userID string) ([]*posture.Checks, error)
+ GetIdpManager() idp.Manager
UpdateIntegratedApprovalGroups(accountID string, userID string, groups []string) error
GroupValidation(accountId string, groups []string) (bool, error)
}
@@ -209,6 +210,7 @@ type Account struct {
// User.Id it was created by
CreatedBy string
+ CreatedAt time.Time
Domain string `gorm:"index"`
DomainCategory string
IsDomainPrimaryAccount bool
@@ -703,6 +705,7 @@ func (a *Account) Copy() *Account {
return &Account{
Id: a.Id,
CreatedBy: a.CreatedBy,
+ CreatedAt: a.CreatedAt,
Domain: a.Domain,
DomainCategory: a.DomainCategory,
IsDomainPrimaryAccount: a.IsDomainPrimaryAccount,
@@ -922,6 +925,10 @@ func (am *DefaultAccountManager) GetExternalCacheManager() ExternalCacheManager
return am.externalCacheManager
}
+func (am *DefaultAccountManager) GetIdpManager() idp.Manager {
+ return am.idpManager
+}
+
// UpdateAccountSettings updates Account settings.
// Only users with role UserRoleAdmin can update the account.
// User that performs the update has to belong to the account.
@@ -939,12 +946,7 @@ func (am *DefaultAccountManager) UpdateAccountSettings(accountID, userID string,
unlock := am.Store.AcquireAccountLock(accountID)
defer unlock()
- account, err := am.Store.GetAccountByUser(userID)
- if err != nil {
- return nil, err
- }
-
- err = additions.ValidateExtraSettings(newSettings.Extra, account.Settings.Extra, account.Peers, userID, accountID, am.eventStore)
+ account, err := am.Store.GetAccount(accountID)
if err != nil {
return nil, err
}
@@ -958,6 +960,11 @@ func (am *DefaultAccountManager) UpdateAccountSettings(accountID, userID string,
return nil, status.Errorf(status.PermissionDenied, "user is not allowed to update account")
}
+ err = additions.ValidateExtraSettings(newSettings.Extra, account.Settings.Extra, account.Peers, userID, accountID, am.eventStore)
+ if err != nil {
+ return nil, err
+ }
+
oldSettings := account.Settings
if oldSettings.PeerLoginExpirationEnabled != newSettings.PeerLoginExpirationEnabled {
event := activity.AccountPeerLoginExpirationEnabled
@@ -1892,6 +1899,7 @@ func newAccountWithId(accountID, userID, domain string) *Account {
acc := &Account{
Id: accountID,
+ CreatedAt: time.Now().UTC(),
SetupKeys: setupKeys,
Network: network,
Peers: peers,
diff --git a/management/server/account_test.go b/management/server/account_test.go
index 1e698eb96..02d242e3a 100644
--- a/management/server/account_test.go
+++ b/management/server/account_test.go
@@ -32,8 +32,12 @@ func (MocIntegratedApproval) PreparePeer(accountID string, peer *nbpeer.Peer, pe
return peer
}
-func (MocIntegratedApproval) SyncPeer(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool) {
- return peer.Copy(), false
+func (MocIntegratedApproval) IsRequiresApproval(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) bool {
+ return false
+}
+
+func (MocIntegratedApproval) Stop() {
+
}
func verifyCanAddPeerToAccount(t *testing.T, manager AccountManager, account *Account, userID string) {
@@ -104,6 +108,10 @@ func verifyNewAccountHasDefaultFields(t *testing.T, account *Account, createdBy
t.Errorf("expecting newly created account to be created by user %s, got %s", createdBy, account.CreatedBy)
}
+ if account.CreatedAt.IsZero() {
+ t.Errorf("expecting newly created account to have a non-zero creation time")
+ }
+
if account.Domain != domain {
t.Errorf("expecting newly created account to have domain %s, got %s", domain, account.Domain)
}
@@ -1483,6 +1491,7 @@ func TestAccount_Copy(t *testing.T) {
account := &Account{
Id: "account1",
CreatedBy: "tester",
+ CreatedAt: time.Now().UTC(),
Domain: "test.com",
DomainCategory: "public",
IsDomainPrimaryAccount: true,
diff --git a/management/server/activity/event.go b/management/server/activity/event.go
index 249547122..0e819c3a7 100644
--- a/management/server/activity/event.go
+++ b/management/server/activity/event.go
@@ -9,7 +9,7 @@ const (
)
// ActivityDescriber is an interface that describes an activity
-type ActivityDescriber interface {
+type ActivityDescriber interface { //nolint:revive
StringCode() string
Message() string
}
diff --git a/management/server/geolocation/database.go b/management/server/geolocation/database.go
new file mode 100644
index 000000000..1bada6075
--- /dev/null
+++ b/management/server/geolocation/database.go
@@ -0,0 +1,210 @@
+package geolocation
+
+import (
+ "encoding/csv"
+ "fmt"
+ "io"
+ "net/url"
+ "os"
+ "path"
+ "strconv"
+
+ "gorm.io/driver/sqlite"
+ "gorm.io/gorm"
+ "gorm.io/gorm/logger"
+)
+
+const (
+ geoLiteCityTarGZURL = "https://pkgs.netbird.io/geolocation-dbs/GeoLite2-City/download?suffix=tar.gz"
+ geoLiteCityZipURL = "https://pkgs.netbird.io/geolocation-dbs/GeoLite2-City-CSV/download?suffix=zip"
+ geoLiteCitySha256TarURL = "https://pkgs.netbird.io/geolocation-dbs/GeoLite2-City/download?suffix=tar.gz.sha256"
+ geoLiteCitySha256ZipURL = "https://pkgs.netbird.io/geolocation-dbs/GeoLite2-City-CSV/download?suffix=zip.sha256"
+)
+
+// loadGeolocationDatabases loads the MaxMind databases.
+func loadGeolocationDatabases(dataDir string) error {
+ files := []string{MMDBFileName, GeoSqliteDBFile}
+ for _, file := range files {
+ exists, _ := fileExists(path.Join(dataDir, file))
+ if exists {
+ continue
+ }
+
+ switch file {
+ case MMDBFileName:
+ extractFunc := func(src string, dst string) error {
+ if err := decompressTarGzFile(src, dst); err != nil {
+ return err
+ }
+ return copyFile(path.Join(dst, MMDBFileName), path.Join(dataDir, MMDBFileName))
+ }
+ if err := loadDatabase(
+ geoLiteCitySha256TarURL,
+ geoLiteCityTarGZURL,
+ extractFunc,
+ ); err != nil {
+ return err
+ }
+
+ case GeoSqliteDBFile:
+ extractFunc := func(src string, dst string) error {
+ if err := decompressZipFile(src, dst); err != nil {
+ return err
+ }
+ extractedCsvFile := path.Join(dst, "GeoLite2-City-Locations-en.csv")
+ return importCsvToSqlite(dataDir, extractedCsvFile)
+ }
+
+ if err := loadDatabase(
+ geoLiteCitySha256ZipURL,
+ geoLiteCityZipURL,
+ extractFunc,
+ ); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// loadDatabase downloads a file from the specified URL and verifies its checksum.
+// It then calls the extract function to perform additional processing on the extracted files.
+func loadDatabase(checksumURL string, fileURL string, extractFunc func(src string, dst string) error) error {
+ temp, err := os.MkdirTemp(os.TempDir(), "geolite")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(temp)
+
+ checksumFile := path.Join(temp, getDatabaseFileName(checksumURL))
+ err = downloadFile(checksumURL, checksumFile)
+ if err != nil {
+ return err
+ }
+
+ sha256sum, err := loadChecksumFromFile(checksumFile)
+ if err != nil {
+ return err
+ }
+
+ dbFile := path.Join(temp, getDatabaseFileName(fileURL))
+ err = downloadFile(fileURL, dbFile)
+ if err != nil {
+ return err
+ }
+
+ if err := verifyChecksum(dbFile, sha256sum); err != nil {
+ return err
+ }
+
+ return extractFunc(dbFile, temp)
+}
+
+// importCsvToSqlite imports a CSV file into a SQLite database.
+func importCsvToSqlite(dataDir string, csvFile string) error {
+ geonames, err := loadGeonamesCsv(csvFile)
+ if err != nil {
+ return err
+ }
+
+ db, err := gorm.Open(sqlite.Open(path.Join(dataDir, GeoSqliteDBFile)), &gorm.Config{
+ Logger: logger.Default.LogMode(logger.Silent),
+ CreateBatchSize: 1000,
+ PrepareStmt: true,
+ })
+ if err != nil {
+ return err
+ }
+ defer func() {
+ sql, err := db.DB()
+ if err != nil {
+ return
+ }
+ sql.Close()
+ }()
+
+ if err := db.AutoMigrate(&GeoNames{}); err != nil {
+ return err
+ }
+
+ return db.Create(geonames).Error
+}
+
+func loadGeonamesCsv(filepath string) ([]GeoNames, error) {
+ f, err := os.Open(filepath)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ reader := csv.NewReader(f)
+ records, err := reader.ReadAll()
+ if err != nil {
+ return nil, err
+ }
+
+ var geoNames []GeoNames
+ for index, record := range records {
+ if index == 0 {
+ continue
+ }
+ geoNameID, err := strconv.Atoi(record[0])
+ if err != nil {
+ return nil, err
+ }
+
+ geoName := GeoNames{
+ GeoNameID: geoNameID,
+ LocaleCode: record[1],
+ ContinentCode: record[2],
+ ContinentName: record[3],
+ CountryIsoCode: record[4],
+ CountryName: record[5],
+ Subdivision1IsoCode: record[6],
+ Subdivision1Name: record[7],
+ Subdivision2IsoCode: record[8],
+ Subdivision2Name: record[9],
+ CityName: record[10],
+ MetroCode: record[11],
+ TimeZone: record[12],
+ IsInEuropeanUnion: record[13],
+ }
+ geoNames = append(geoNames, geoName)
+ }
+
+ return geoNames, nil
+}
+
+// getDatabaseFileName extracts the file name from a given URL string.
+func getDatabaseFileName(urlStr string) string {
+ u, err := url.Parse(urlStr)
+ if err != nil {
+ panic(err)
+ }
+
+ ext := u.Query().Get("suffix")
+ fileName := fmt.Sprintf("%s.%s", path.Base(u.Path), ext)
+ return fileName
+}
+
+// copyFile performs a file copy operation from the source file to the destination.
+func copyFile(src string, dst string) error {
+ srcFile, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer srcFile.Close()
+
+ dstFile, err := os.Create(dst)
+ if err != nil {
+ return err
+ }
+ defer dstFile.Close()
+
+ _, err = io.Copy(dstFile, srcFile)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/management/server/geolocation/geolocation.go b/management/server/geolocation/geolocation.go
index de7a8af82..88cdfcb9f 100644
--- a/management/server/geolocation/geolocation.go
+++ b/management/server/geolocation/geolocation.go
@@ -2,9 +2,7 @@ package geolocation
import (
"bytes"
- "crypto/sha256"
"fmt"
- "io"
"net"
"os"
"path"
@@ -54,20 +52,23 @@ type Country struct {
CountryName string
}
-func NewGeolocation(datadir string) (*Geolocation, error) {
- mmdbPath := path.Join(datadir, MMDBFileName)
+func NewGeolocation(dataDir string) (*Geolocation, error) {
+ if err := loadGeolocationDatabases(dataDir); err != nil {
+ return nil, fmt.Errorf("failed to load MaxMind databases: %v", err)
+ }
+ mmdbPath := path.Join(dataDir, MMDBFileName)
db, err := openDB(mmdbPath)
if err != nil {
return nil, err
}
- sha256sum, err := getSha256sum(mmdbPath)
+ sha256sum, err := calculateFileSHA256(mmdbPath)
if err != nil {
return nil, err
}
- locationDB, err := NewSqliteStore(datadir)
+ locationDB, err := NewSqliteStore(dataDir)
if err != nil {
return nil, err
}
@@ -104,21 +105,6 @@ func openDB(mmdbPath string) (*maxminddb.Reader, error) {
return db, nil
}
-func getSha256sum(mmdbPath string) ([]byte, error) {
- f, err := os.Open(mmdbPath)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- h := sha256.New()
- if _, err := io.Copy(h, f); err != nil {
- return nil, err
- }
-
- return h.Sum(nil), nil
-}
-
func (gl *Geolocation) Lookup(ip net.IP) (*Record, error) {
gl.mux.RLock()
defer gl.mux.RUnlock()
@@ -189,7 +175,7 @@ func (gl *Geolocation) reloader() {
log.Errorf("geonames db reload failed: %s", err)
}
- newSha256sum1, err := getSha256sum(gl.mmdbPath)
+ newSha256sum1, err := calculateFileSHA256(gl.mmdbPath)
if err != nil {
log.Errorf("failed to calculate sha256 sum for '%s': %s", gl.mmdbPath, err)
continue
@@ -198,7 +184,7 @@ func (gl *Geolocation) reloader() {
// we check sum twice just to avoid possible case when we reload during update of the file
// considering the frequency of file update (few times a week) checking sum twice should be enough
time.Sleep(50 * time.Millisecond)
- newSha256sum2, err := getSha256sum(gl.mmdbPath)
+ newSha256sum2, err := calculateFileSHA256(gl.mmdbPath)
if err != nil {
log.Errorf("failed to calculate sha256 sum for '%s': %s", gl.mmdbPath, err)
continue
diff --git a/management/server/geolocation/store.go b/management/server/geolocation/store.go
index 9f3638a7c..74401d6ca 100644
--- a/management/server/geolocation/store.go
+++ b/management/server/geolocation/store.go
@@ -20,6 +20,27 @@ const (
GeoSqliteDBFile = "geonames.db"
)
+type GeoNames struct {
+ GeoNameID int `gorm:"column:geoname_id"`
+ LocaleCode string `gorm:"column:locale_code"`
+ ContinentCode string `gorm:"column:continent_code"`
+ ContinentName string `gorm:"column:continent_name"`
+ CountryIsoCode string `gorm:"column:country_iso_code"`
+ CountryName string `gorm:"column:country_name"`
+ Subdivision1IsoCode string `gorm:"column:subdivision_1_iso_code"`
+ Subdivision1Name string `gorm:"column:subdivision_1_name"`
+ Subdivision2IsoCode string `gorm:"column:subdivision_2_iso_code"`
+ Subdivision2Name string `gorm:"column:subdivision_2_name"`
+ CityName string `gorm:"column:city_name"`
+ MetroCode string `gorm:"column:metro_code"`
+ TimeZone string `gorm:"column:time_zone"`
+ IsInEuropeanUnion string `gorm:"column:is_in_european_union"`
+}
+
+func (*GeoNames) TableName() string {
+ return "geonames"
+}
+
// SqliteStore represents a location storage backed by a Sqlite DB.
type SqliteStore struct {
db *gorm.DB
@@ -37,7 +58,7 @@ func NewSqliteStore(dataDir string) (*SqliteStore, error) {
return nil, err
}
- sha256sum, err := getSha256sum(file)
+ sha256sum, err := calculateFileSHA256(file)
if err != nil {
return nil, err
}
@@ -60,7 +81,7 @@ func (s *SqliteStore) GetAllCountries() ([]Country, error) {
}
var countries []Country
- result := s.db.Table("geonames").
+ result := s.db.Model(&GeoNames{}).
Select("country_iso_code", "country_name").
Group("country_name").
Scan(&countries)
@@ -81,7 +102,7 @@ func (s *SqliteStore) GetCitiesByCountry(countryISOCode string) ([]City, error)
}
var cities []City
- result := s.db.Table("geonames").
+ result := s.db.Model(&GeoNames{}).
Select("geoname_id", "city_name").
Where("country_iso_code = ?", countryISOCode).
Group("city_name").
@@ -98,7 +119,7 @@ func (s *SqliteStore) reload() error {
s.mux.Lock()
defer s.mux.Unlock()
- newSha256sum1, err := getSha256sum(s.filePath)
+ newSha256sum1, err := calculateFileSHA256(s.filePath)
if err != nil {
log.Errorf("failed to calculate sha256 sum for '%s': %s", s.filePath, err)
}
@@ -107,7 +128,7 @@ func (s *SqliteStore) reload() error {
// we check sum twice just to avoid possible case when we reload during update of the file
// considering the frequency of file update (few times a week) checking sum twice should be enough
time.Sleep(50 * time.Millisecond)
- newSha256sum2, err := getSha256sum(s.filePath)
+ newSha256sum2, err := calculateFileSHA256(s.filePath)
if err != nil {
return fmt.Errorf("failed to calculate sha256 sum for '%s': %s", s.filePath, err)
}
diff --git a/management/server/geolocation/utils.go b/management/server/geolocation/utils.go
new file mode 100644
index 000000000..bdbd4732d
--- /dev/null
+++ b/management/server/geolocation/utils.go
@@ -0,0 +1,176 @@
+package geolocation
+
+import (
+ "archive/tar"
+ "archive/zip"
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "crypto/sha256"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "path"
+ "strings"
+)
+
+// decompressTarGzFile decompresses a .tar.gz file.
+func decompressTarGzFile(filepath, destDir string) error {
+ file, err := os.Open(filepath)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ gzipReader, err := gzip.NewReader(file)
+ if err != nil {
+ return err
+ }
+ defer gzipReader.Close()
+
+ tarReader := tar.NewReader(gzipReader)
+
+ for {
+ header, err := tarReader.Next()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ return err
+ }
+
+ if header.Typeflag == tar.TypeReg {
+ outFile, err := os.Create(path.Join(destDir, path.Base(header.Name)))
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(outFile, tarReader) // #nosec G110
+ outFile.Close()
+ if err != nil {
+ return err
+ }
+ }
+
+ }
+
+ return nil
+}
+
+// decompressZipFile decompresses a .zip file.
+func decompressZipFile(filepath, destDir string) error {
+ r, err := zip.OpenReader(filepath)
+ if err != nil {
+ return err
+ }
+ defer r.Close()
+
+ for _, f := range r.File {
+ if f.FileInfo().IsDir() {
+ continue
+ }
+
+ outFile, err := os.Create(path.Join(destDir, path.Base(f.Name)))
+ if err != nil {
+ return err
+ }
+
+ rc, err := f.Open()
+ if err != nil {
+ outFile.Close()
+ return err
+ }
+
+ _, err = io.Copy(outFile, rc) // #nosec G110
+ outFile.Close()
+ rc.Close()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// calculateFileSHA256 calculates the SHA256 checksum of a file.
+func calculateFileSHA256(filepath string) ([]byte, error) {
+ file, err := os.Open(filepath)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ h := sha256.New()
+ if _, err := io.Copy(h, file); err != nil {
+ return nil, err
+ }
+
+ return h.Sum(nil), nil
+}
+
+// loadChecksumFromFile loads the first checksum from a file.
+func loadChecksumFromFile(filepath string) (string, error) {
+ file, err := os.Open(filepath)
+ if err != nil {
+ return "", err
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ if scanner.Scan() {
+ parts := strings.Fields(scanner.Text())
+ if len(parts) > 0 {
+ return parts[0], nil
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return "", err
+ }
+
+ return "", nil
+}
+
+// verifyChecksum compares the calculated SHA256 checksum of a file against the expected checksum.
+func verifyChecksum(filepath, expectedChecksum string) error {
+ calculatedChecksum, err := calculateFileSHA256(filepath)
+
+ fileCheckSum := fmt.Sprintf("%x", calculatedChecksum)
+ if err != nil {
+ return err
+ }
+
+ if fileCheckSum != expectedChecksum {
+ return fmt.Errorf("checksum mismatch: expected %s, got %s", expectedChecksum, fileCheckSum)
+ }
+
+ return nil
+}
+
+// downloadFile downloads a file from a URL and saves it to a local file path.
+func downloadFile(url, filepath string) error {
+ resp, err := http.Get(url)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+
+ bodyBytes, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return err
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("unexpected error occurred while downloading the file: %s", string(bodyBytes))
+ }
+
+ out, err := os.Create(filepath)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+
+ _, err = io.Copy(out, bytes.NewBuffer(bodyBytes))
+ return err
+}
diff --git a/management/server/grpcserver.go b/management/server/grpcserver.go
index a79fe6456..341d202b6 100644
--- a/management/server/grpcserver.go
+++ b/management/server/grpcserver.go
@@ -288,6 +288,10 @@ func extractPeerMeta(loginReq *proto.LoginRequest) nbpeer.PeerSystemMeta {
SystemSerialNumber: loginReq.GetMeta().GetSysSerialNumber(),
SystemProductName: loginReq.GetMeta().GetSysProductName(),
SystemManufacturer: loginReq.GetMeta().GetSysManufacturer(),
+ Environment: nbpeer.Environment{
+ Cloud: loginReq.GetMeta().GetEnvironment().GetCloud(),
+ Platform: loginReq.GetMeta().GetEnvironment().GetPlatform(),
+ },
}
}
diff --git a/management/server/http/api/openapi.yml b/management/server/http/api/openapi.yml
index 5c05c15ad..b2ddfd5cc 100644
--- a/management/server/http/api/openapi.yml
+++ b/management/server/http/api/openapi.yml
@@ -121,7 +121,7 @@ components:
description: Last time this user performed a login to the dashboard
type: string
format: date-time
- example: 2023-05-05T09:00:35.477782Z
+ example: "2023-05-05T09:00:35.477782Z"
auto_groups:
description: Group IDs to auto-assign to peers registered by this user
type: array
@@ -259,7 +259,7 @@ components:
description: Last time peer connected to Netbird's management service
type: string
format: date-time
- example: 2023-05-05T10:05:26.420578Z
+ example: "2023-05-05T10:05:26.420578Z"
os:
description: Peer's operating system and version
type: string
@@ -313,7 +313,7 @@ components:
description: Last time this peer performed log in (authentication). E.g., user authenticated.
type: string
format: date-time
- example: 2023-05-05T09:00:35.477782Z
+ example: "2023-05-05T09:00:35.477782Z"
approval_required:
description: (Cloud only) Indicates whether peer needs approval
type: boolean
@@ -405,7 +405,7 @@ components:
description: Setup Key expiration date
type: string
format: date-time
- example: 2023-06-01T14:47:22.291057Z
+ example: "2023-06-01T14:47:22.291057Z"
type:
description: Setup key type, one-off for single time usage and reusable
type: string
@@ -426,7 +426,7 @@ components:
description: Setup key last usage date
type: string
format: date-time
- example: 2023-05-05T09:00:35.477782Z
+ example: "2023-05-05T09:00:35.477782Z"
state:
description: Setup key status, "valid", "overused","expired" or "revoked"
type: string
@@ -441,7 +441,7 @@ components:
description: Setup key last update date
type: string
format: date-time
- example: 2023-05-05T09:00:35.477782Z
+ example: "2023-05-05T09:00:35.477782Z"
usage_limit:
description: A number of times this key can be used. The value of 0 indicates the unlimited usage.
type: integer
@@ -522,7 +522,7 @@ components:
description: Date the token expires
type: string
format: date-time
- example: 2023-05-05T14:38:28.977616Z
+ example: "2023-05-05T14:38:28.977616Z"
created_by:
description: User ID of the user who created the token
type: string
@@ -531,12 +531,12 @@ components:
description: Date the token was created
type: string
format: date-time
- example: 2023-05-02T14:48:20.465209Z
+ example: "2023-05-02T14:48:20.465209Z"
last_used:
description: Date the token was last used
type: string
format: date-time
- example: 2023-05-04T12:45:25.9723616Z
+ example: "2023-05-04T12:45:25.9723616Z"
required:
- id
- name
@@ -862,8 +862,8 @@ components:
$ref: '#/components/schemas/OSVersionCheck'
geo_location_check:
$ref: '#/components/schemas/GeoLocationCheck'
- private_network_check:
- $ref: '#/components/schemas/PrivateNetworkCheck'
+ peer_network_range_check:
+ $ref: '#/components/schemas/PeerNetworkRangeCheck'
NBVersionCheck:
description: Posture check for the version of NetBird
type: object
@@ -934,16 +934,16 @@ components:
required:
- locations
- action
- PrivateNetworkCheck:
- description: Posture check for allow or deny private network
+ PeerNetworkRangeCheck:
+ description: Posture check for allow or deny access based on peer local network addresses
type: object
properties:
ranges:
- description: List of private network ranges in CIDR notation
+ description: List of peer network ranges in CIDR notation
type: array
items:
type: string
- example: ["192.168.1.0/24", "10.0.0.0/8"]
+ example: ["192.168.1.0/24", "10.0.0.0/8", "2001:db8:1234:1a00::/56"]
action:
description: Action to take upon policy match
type: string
@@ -979,7 +979,7 @@ components:
type: string
example: "Germany"
country_code:
- $ref: '#/components/schemas/CountryCode'
+ $ref: '#/components/schemas/CountryCode'
required:
- country_name
- country_code
@@ -1197,7 +1197,7 @@ components:
description: The date and time when the event occurred
type: string
format: date-time
- example: 2023-05-05T10:04:37.473542Z
+ example: "2023-05-05T10:04:37.473542Z"
activity:
description: The activity that occurred during the event
type: string
diff --git a/management/server/http/api/types.gen.go b/management/server/http/api/types.gen.go
index 28fe63c9d..c007663a4 100644
--- a/management/server/http/api/types.gen.go
+++ b/management/server/http/api/types.gen.go
@@ -74,6 +74,12 @@ const (
NameserverNsTypeUdp NameserverNsType = "udp"
)
+// Defines values for PeerNetworkRangeCheckAction.
+const (
+ PeerNetworkRangeCheckActionAllow PeerNetworkRangeCheckAction = "allow"
+ PeerNetworkRangeCheckActionDeny PeerNetworkRangeCheckAction = "deny"
+)
+
// Defines values for PolicyRuleAction.
const (
PolicyRuleActionAccept PolicyRuleAction = "accept"
@@ -116,12 +122,6 @@ const (
PolicyRuleUpdateProtocolUdp PolicyRuleUpdateProtocol = "udp"
)
-// Defines values for PrivateNetworkCheckAction.
-const (
- PrivateNetworkCheckActionAllow PrivateNetworkCheckAction = "allow"
- PrivateNetworkCheckActionDeny PrivateNetworkCheckAction = "deny"
-)
-
// Defines values for UserStatus.
const (
UserStatusActive UserStatus = "active"
@@ -199,8 +199,8 @@ type Checks struct {
// OsVersionCheck Posture check for the version of operating system
OsVersionCheck *OSVersionCheck `json:"os_version_check,omitempty"`
- // PrivateNetworkCheck Posture check for allow or deny private network
- PrivateNetworkCheck *PrivateNetworkCheck `json:"private_network_check,omitempty"`
+ // PeerNetworkRangeCheck Posture check for allow or deny access based on peer local network addresses
+ PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:"peer_network_range_check,omitempty"`
}
// City Describe city geographical location information
@@ -656,6 +656,18 @@ type PeerMinimum struct {
Name string `json:"name"`
}
+// PeerNetworkRangeCheck Posture check for allow or deny access based on peer local network addresses
+type PeerNetworkRangeCheck struct {
+ // Action Action to take upon policy match
+ Action PeerNetworkRangeCheckAction `json:"action"`
+
+ // Ranges List of peer network ranges in CIDR notation
+ Ranges []string `json:"ranges"`
+}
+
+// PeerNetworkRangeCheckAction Action to take upon policy match
+type PeerNetworkRangeCheckAction string
+
// PeerRequest defines model for PeerRequest.
type PeerRequest struct {
// ApprovalRequired (Cloud only) Indicates whether peer needs approval
@@ -898,18 +910,6 @@ type PostureCheckUpdate struct {
Name string `json:"name"`
}
-// PrivateNetworkCheck Posture check for allow or deny private network
-type PrivateNetworkCheck struct {
- // Action Action to take upon policy match
- Action PrivateNetworkCheckAction `json:"action"`
-
- // Ranges List of private network ranges in CIDR notation
- Ranges []string `json:"ranges"`
-}
-
-// PrivateNetworkCheckAction Action to take upon policy match
-type PrivateNetworkCheckAction string
-
// Route defines model for Route.
type Route struct {
// Description Route description
diff --git a/management/server/http/middleware/auth_middleware_test.go b/management/server/http/middleware/auth_middleware_test.go
index 3e3e84194..588bcaf02 100644
--- a/management/server/http/middleware/auth_middleware_test.go
+++ b/management/server/http/middleware/auth_middleware_test.go
@@ -177,7 +177,10 @@ func TestAuthMiddleware_Handler(t *testing.T) {
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
if tc.shouldBypassAuth {
- bypass.AddBypassPath(tc.path)
+ err := bypass.AddBypassPath(tc.path)
+ if err != nil {
+ t.Fatalf("failed to add bypass path: %v", err)
+ }
}
req := httptest.NewRequest("GET", "http://testing"+tc.path, nil)
diff --git a/management/server/http/middleware/bypass/bypass.go b/management/server/http/middleware/bypass/bypass.go
index 2f2652eb6..87b41c6fc 100644
--- a/management/server/http/middleware/bypass/bypass.go
+++ b/management/server/http/middleware/bypass/bypass.go
@@ -1,8 +1,12 @@
package bypass
import (
+ "fmt"
"net/http"
+ "path"
"sync"
+
+ log "github.com/sirupsen/logrus"
)
var byPassMutex sync.RWMutex
@@ -11,10 +15,16 @@ var byPassMutex sync.RWMutex
var bypassPaths = make(map[string]struct{})
// AddBypassPath adds an exact path to the list of paths that bypass middleware.
-func AddBypassPath(path string) {
+// Paths can include wildcards, such as /api/*. Paths are matched using path.Match.
+// Returns an error if the path has invalid pattern.
+func AddBypassPath(path string) error {
byPassMutex.Lock()
defer byPassMutex.Unlock()
+ if err := validatePath(path); err != nil {
+ return fmt.Errorf("validate: %w", err)
+ }
bypassPaths[path] = struct{}{}
+ return nil
}
// RemovePath removes a path from the list of paths that bypass middleware.
@@ -24,16 +34,41 @@ func RemovePath(path string) {
delete(bypassPaths, path)
}
+// GetList returns a list of all bypass paths.
+func GetList() []string {
+ byPassMutex.RLock()
+ defer byPassMutex.RUnlock()
+
+ list := make([]string, 0, len(bypassPaths))
+ for k := range bypassPaths {
+ list = append(list, k)
+ }
+
+ return list
+}
+
// ShouldBypass checks if the request path is one of the auth bypass paths and returns true if the middleware should be bypassed.
// This can be used to bypass authz/authn middlewares for certain paths, such as webhooks that implement their own authentication.
func ShouldBypass(requestPath string, h http.Handler, w http.ResponseWriter, r *http.Request) bool {
byPassMutex.RLock()
defer byPassMutex.RUnlock()
- if _, ok := bypassPaths[requestPath]; ok {
- h.ServeHTTP(w, r)
- return true
+ for bypassPath := range bypassPaths {
+ matched, err := path.Match(bypassPath, requestPath)
+ if err != nil {
+ log.Errorf("Error matching path %s with %s from %s: %v", bypassPath, requestPath, GetList(), err)
+ continue
+ }
+ if matched {
+ h.ServeHTTP(w, r)
+ return true
+ }
}
return false
}
+
+func validatePath(p string) error {
+ _, err := path.Match(p, "")
+ return err
+}
diff --git a/management/server/http/middleware/bypass/bypass_test.go b/management/server/http/middleware/bypass/bypass_test.go
index efcfe1c3d..c65e6fa1f 100644
--- a/management/server/http/middleware/bypass/bypass_test.go
+++ b/management/server/http/middleware/bypass/bypass_test.go
@@ -11,6 +11,19 @@ import (
"github.com/netbirdio/netbird/management/server/http/middleware/bypass"
)
+func TestGetList(t *testing.T) {
+ bypassPaths := []string{"/path1", "/path2", "/path3"}
+
+ for _, path := range bypassPaths {
+ err := bypass.AddBypassPath(path)
+ require.NoError(t, err, "Adding bypass path should not fail")
+ }
+
+ list := bypass.GetList()
+
+ assert.ElementsMatch(t, bypassPaths, list, "Bypass path list did not match expected paths")
+}
+
func TestAuthBypass(t *testing.T) {
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
@@ -31,6 +44,13 @@ func TestAuthBypass(t *testing.T) {
expectBypass: true,
expectHTTPCode: http.StatusOK,
},
+ {
+ name: "Wildcard path added to bypass",
+ pathToAdd: "/bypass/*",
+ testPath: "/bypass/extra",
+ expectBypass: true,
+ expectHTTPCode: http.StatusOK,
+ },
{
name: "Path not added to bypass",
testPath: "/no-bypass",
@@ -59,6 +79,13 @@ func TestAuthBypass(t *testing.T) {
expectBypass: false,
expectHTTPCode: http.StatusOK,
},
+ {
+ name: "Wildcard subpath does not match bypass",
+ pathToAdd: "/webhook/*",
+ testPath: "/webhook/extra/path",
+ expectBypass: false,
+ expectHTTPCode: http.StatusOK,
+ },
{
name: "Similar path does not match bypass",
pathToAdd: "/webhook",
@@ -78,7 +105,8 @@ func TestAuthBypass(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
if tc.pathToAdd != "" {
- bypass.AddBypassPath(tc.pathToAdd)
+ err := bypass.AddBypassPath(tc.pathToAdd)
+ require.NoError(t, err, "Adding bypass path should not fail")
defer bypass.RemovePath(tc.pathToAdd)
}
diff --git a/management/server/http/posture_checks_handler.go b/management/server/http/posture_checks_handler.go
index 581bba2b7..fcccc1997 100644
--- a/management/server/http/posture_checks_handler.go
+++ b/management/server/http/posture_checks_handler.go
@@ -213,8 +213,8 @@ func (p *PostureChecksHandler) savePostureChecks(
postureChecks.Checks.GeoLocationCheck = toPostureGeoLocationCheck(geoLocationCheck)
}
- if privateNetworkCheck := req.Checks.PrivateNetworkCheck; privateNetworkCheck != nil {
- postureChecks.Checks.PrivateNetworkCheck, err = toPrivateNetworkCheck(privateNetworkCheck)
+ if peerNetworkRangeCheck := req.Checks.PeerNetworkRangeCheck; peerNetworkRangeCheck != nil {
+ postureChecks.Checks.PeerNetworkRangeCheck, err = toPeerNetworkRangeCheck(peerNetworkRangeCheck)
if err != nil {
util.WriteError(status.Errorf(status.InvalidArgument, "invalid network prefix"), w)
return
@@ -235,7 +235,7 @@ func validatePostureChecksUpdate(req api.PostureCheckUpdate) error {
}
if req.Checks == nil || (req.Checks.NbVersionCheck == nil && req.Checks.OsVersionCheck == nil &&
- req.Checks.GeoLocationCheck == nil && req.Checks.PrivateNetworkCheck == nil) {
+ req.Checks.GeoLocationCheck == nil && req.Checks.PeerNetworkRangeCheck == nil) {
return status.Errorf(status.InvalidArgument, "posture checks shouldn't be empty")
}
@@ -278,17 +278,17 @@ func validatePostureChecksUpdate(req api.PostureCheckUpdate) error {
}
}
- if privateNetworkCheck := req.Checks.PrivateNetworkCheck; privateNetworkCheck != nil {
- if privateNetworkCheck.Action == "" {
- return status.Errorf(status.InvalidArgument, "action for private network check shouldn't be empty")
+ if peerNetworkRangeCheck := req.Checks.PeerNetworkRangeCheck; peerNetworkRangeCheck != nil {
+ if peerNetworkRangeCheck.Action == "" {
+ return status.Errorf(status.InvalidArgument, "action for peer network range check shouldn't be empty")
}
- allowedActions := []api.PrivateNetworkCheckAction{api.PrivateNetworkCheckActionAllow, api.PrivateNetworkCheckActionDeny}
- if !slices.Contains(allowedActions, privateNetworkCheck.Action) {
- return status.Errorf(status.InvalidArgument, "action for private network check is not valid value")
+ allowedActions := []api.PeerNetworkRangeCheckAction{api.PeerNetworkRangeCheckActionAllow, api.PeerNetworkRangeCheckActionDeny}
+ if !slices.Contains(allowedActions, peerNetworkRangeCheck.Action) {
+ return status.Errorf(status.InvalidArgument, "action for peer network range check is not valid value")
}
- if len(privateNetworkCheck.Ranges) == 0 {
- return status.Errorf(status.InvalidArgument, "network ranges for private network check shouldn't be empty")
+ if len(peerNetworkRangeCheck.Ranges) == 0 {
+ return status.Errorf(status.InvalidArgument, "network ranges for peer network range check shouldn't be empty")
}
}
@@ -318,8 +318,8 @@ func toPostureChecksResponse(postureChecks *posture.Checks) *api.PostureCheck {
checks.GeoLocationCheck = toGeoLocationCheckResponse(postureChecks.Checks.GeoLocationCheck)
}
- if postureChecks.Checks.PrivateNetworkCheck != nil {
- checks.PrivateNetworkCheck = toPrivateNetworkCheckResponse(postureChecks.Checks.PrivateNetworkCheck)
+ if postureChecks.Checks.PeerNetworkRangeCheck != nil {
+ checks.PeerNetworkRangeCheck = toPeerNetworkRangeCheckResponse(postureChecks.Checks.PeerNetworkRangeCheck)
}
return &api.PostureCheck{
@@ -369,19 +369,19 @@ func toPostureGeoLocationCheck(apiGeoLocationCheck *api.GeoLocationCheck) *postu
}
}
-func toPrivateNetworkCheckResponse(check *posture.PrivateNetworkCheck) *api.PrivateNetworkCheck {
+func toPeerNetworkRangeCheckResponse(check *posture.PeerNetworkRangeCheck) *api.PeerNetworkRangeCheck {
netPrefixes := make([]string, 0, len(check.Ranges))
for _, netPrefix := range check.Ranges {
netPrefixes = append(netPrefixes, netPrefix.String())
}
- return &api.PrivateNetworkCheck{
+ return &api.PeerNetworkRangeCheck{
Ranges: netPrefixes,
- Action: api.PrivateNetworkCheckAction(check.Action),
+ Action: api.PeerNetworkRangeCheckAction(check.Action),
}
}
-func toPrivateNetworkCheck(check *api.PrivateNetworkCheck) (*posture.PrivateNetworkCheck, error) {
+func toPeerNetworkRangeCheck(check *api.PeerNetworkRangeCheck) (*posture.PeerNetworkRangeCheck, error) {
prefixes := make([]netip.Prefix, 0)
for _, prefix := range check.Ranges {
parsedPrefix, err := netip.ParsePrefix(prefix)
@@ -391,7 +391,7 @@ func toPrivateNetworkCheck(check *api.PrivateNetworkCheck) (*posture.PrivateNetw
prefixes = append(prefixes, parsedPrefix)
}
- return &posture.PrivateNetworkCheck{
+ return &posture.PeerNetworkRangeCheck{
Ranges: prefixes,
Action: string(check.Action),
}, nil
diff --git a/management/server/http/posture_checks_handler_test.go b/management/server/http/posture_checks_handler_test.go
index 24a28f3ec..70e803214 100644
--- a/management/server/http/posture_checks_handler_test.go
+++ b/management/server/http/posture_checks_handler_test.go
@@ -131,7 +131,7 @@ func TestGetPostureCheck(t *testing.T) {
ID: "privateNetworkPostureCheck",
Name: "privateNetwork",
Checks: posture.ChecksDefinition{
- PrivateNetworkCheck: &posture.PrivateNetworkCheck{
+ PeerNetworkRangeCheck: &posture.PeerNetworkRangeCheck{
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
},
@@ -375,7 +375,7 @@ func TestPostureCheckUpdate(t *testing.T) {
},
},
{
- name: "Create Posture Checks Private Network",
+ name: "Create Posture Checks Peer Network Range",
requestType: http.MethodPost,
requestPath: "/api/posture-checks",
requestBody: bytes.NewBuffer(
@@ -383,7 +383,7 @@ func TestPostureCheckUpdate(t *testing.T) {
"name": "default",
"description": "default",
"checks": {
- "private_network_check": {
+ "peer_network_range_check": {
"action": "allow",
"ranges": [
"10.0.0.0/8"
@@ -398,11 +398,11 @@ func TestPostureCheckUpdate(t *testing.T) {
Name: "default",
Description: str("default"),
Checks: api.Checks{
- PrivateNetworkCheck: &api.PrivateNetworkCheck{
+ PeerNetworkRangeCheck: &api.PeerNetworkRangeCheck{
Ranges: []string{
"10.0.0.0/8",
},
- Action: api.PrivateNetworkCheckActionAllow,
+ Action: api.PeerNetworkRangeCheckActionAllow,
},
},
},
@@ -715,14 +715,14 @@ func TestPostureCheckUpdate(t *testing.T) {
expectedBody: false,
},
{
- name: "Update Posture Checks Private Network",
+ name: "Update Posture Checks Peer Network Range",
requestType: http.MethodPut,
- requestPath: "/api/posture-checks/privateNetworkPostureCheck",
+ requestPath: "/api/posture-checks/peerNetworkRangePostureCheck",
requestBody: bytes.NewBuffer(
[]byte(`{
"name": "default",
"checks": {
- "private_network_check": {
+ "peer_network_range_check": {
"action": "deny",
"ranges": [
"192.168.1.0/24"
@@ -737,11 +737,11 @@ func TestPostureCheckUpdate(t *testing.T) {
Name: "default",
Description: str(""),
Checks: api.Checks{
- PrivateNetworkCheck: &api.PrivateNetworkCheck{
+ PeerNetworkRangeCheck: &api.PeerNetworkRangeCheck{
Ranges: []string{
"192.168.1.0/24",
},
- Action: api.PrivateNetworkCheckActionDeny,
+ Action: api.PeerNetworkRangeCheckActionDeny,
},
},
},
@@ -784,10 +784,10 @@ func TestPostureCheckUpdate(t *testing.T) {
},
},
&posture.Checks{
- ID: "privateNetworkPostureCheck",
- Name: "privateNetwork",
+ ID: "peerNetworkRangePostureCheck",
+ Name: "peerNetworkRange",
Checks: posture.ChecksDefinition{
- PrivateNetworkCheck: &posture.PrivateNetworkCheck{
+ PeerNetworkRangeCheck: &posture.PeerNetworkRangeCheck{
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
},
@@ -891,29 +891,50 @@ func TestPostureCheck_validatePostureChecksUpdate(t *testing.T) {
err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{OsVersionCheck: &osVersionCheck}})
assert.NoError(t, err)
- // valid private network check
- privateNetworkCheck := api.PrivateNetworkCheck{
- Action: api.PrivateNetworkCheckActionAllow,
+ // valid peer network range check
+ peerNetworkRangeCheck := api.PeerNetworkRangeCheck{
+ Action: api.PeerNetworkRangeCheckActionAllow,
Ranges: []string{
"192.168.1.0/24", "10.0.0.0/8",
},
}
- err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}})
+ err = validatePostureChecksUpdate(
+ api.PostureCheckUpdate{
+ Name: "Default",
+ Checks: &api.Checks{
+ PeerNetworkRangeCheck: &peerNetworkRangeCheck,
+ },
+ },
+ )
assert.NoError(t, err)
- // invalid private network check
- privateNetworkCheck = api.PrivateNetworkCheck{
- Action: api.PrivateNetworkCheckActionDeny,
+ // invalid peer network range check
+ peerNetworkRangeCheck = api.PeerNetworkRangeCheck{
+ Action: api.PeerNetworkRangeCheckActionDeny,
Ranges: []string{},
}
- err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}})
+ err = validatePostureChecksUpdate(
+ api.PostureCheckUpdate{
+ Name: "Default",
+ Checks: &api.Checks{
+ PeerNetworkRangeCheck: &peerNetworkRangeCheck,
+ },
+ },
+ )
assert.Error(t, err)
- // invalid private network check
- privateNetworkCheck = api.PrivateNetworkCheck{
+ // invalid peer network range check
+ peerNetworkRangeCheck = api.PeerNetworkRangeCheck{
Action: "unknownAction",
Ranges: []string{},
}
- err = validatePostureChecksUpdate(api.PostureCheckUpdate{Name: "Default", Checks: &api.Checks{PrivateNetworkCheck: &privateNetworkCheck}})
+ err = validatePostureChecksUpdate(
+ api.PostureCheckUpdate{
+ Name: "Default",
+ Checks: &api.Checks{
+ PeerNetworkRangeCheck: &peerNetworkRangeCheck,
+ },
+ },
+ )
assert.Error(t, err)
}
diff --git a/management/server/idp/auth0.go b/management/server/idp/auth0.go
index 745136f62..34a5c0de5 100644
--- a/management/server/idp/auth0.go
+++ b/management/server/idp/auth0.go
@@ -114,6 +114,22 @@ type auth0Profile struct {
LastLogin string `json:"last_login"`
}
+// Connections represents a single Auth0 connection
+// https://auth0.com/docs/api/management/v2/connections/get-connections
+type Connection struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ DisplayName string `json:"display_name"`
+ IsDomainConnection bool `json:"is_domain_connection"`
+ Realms []string `json:"realms"`
+ Metadata map[string]string `json:"metadata"`
+ Options ConnectionOptions `json:"options"`
+}
+
+type ConnectionOptions struct {
+ DomainAliases []string `json:"domain_aliases"`
+}
+
// NewAuth0Manager creates a new instance of the Auth0Manager
func NewAuth0Manager(config Auth0ClientConfig, appMetrics telemetry.AppMetrics) (*Auth0Manager, error) {
httpTransport := http.DefaultTransport.(*http.Transport).Clone()
@@ -581,13 +597,13 @@ func (am *Auth0Manager) GetAllAccounts() (map[string][]*UserData, error) {
body, err := io.ReadAll(jobResp.Body)
if err != nil {
- log.Debugf("Coudln't read export job response; %v", err)
+ log.Debugf("Couldn't read export job response; %v", err)
return nil, err
}
err = am.helper.Unmarshal(body, &exportJobResp)
if err != nil {
- log.Debugf("Coudln't unmarshal export job response; %v", err)
+ log.Debugf("Couldn't unmarshal export job response; %v", err)
return nil, err
}
@@ -635,7 +651,7 @@ func (am *Auth0Manager) GetUserByEmail(email string) ([]*UserData, error) {
err = am.helper.Unmarshal(body, &userResp)
if err != nil {
- log.Debugf("Coudln't unmarshal export job response; %v", err)
+ log.Debugf("Couldn't unmarshal export job response; %v", err)
return nil, err
}
@@ -684,13 +700,13 @@ func (am *Auth0Manager) CreateUser(email, name, accountID, invitedByEmail string
body, err := io.ReadAll(resp.Body)
if err != nil {
- log.Debugf("Coudln't read export job response; %v", err)
+ log.Debugf("Couldn't read export job response; %v", err)
return nil, err
}
err = am.helper.Unmarshal(body, &createResp)
if err != nil {
- log.Debugf("Coudln't unmarshal export job response; %v", err)
+ log.Debugf("Couldn't unmarshal export job response; %v", err)
return nil, err
}
@@ -777,6 +793,56 @@ func (am *Auth0Manager) DeleteUser(userID string) error {
return nil
}
+// GetAllConnections returns detailed list of all connections filtered by given params.
+// Note this method is not part of the IDP Manager interface as this is Auth0 specific.
+func (am *Auth0Manager) GetAllConnections(strategy []string) ([]Connection, error) {
+ var connections []Connection
+
+ q := make(url.Values)
+ q.Set("strategy", strings.Join(strategy, ","))
+
+ req, err := am.createRequest(http.MethodGet, "/api/v2/connections?"+q.Encode(), nil)
+ if err != nil {
+ return connections, err
+ }
+
+ resp, err := am.httpClient.Do(req)
+ if err != nil {
+ log.Debugf("execute get connections request: %v", err)
+ if am.appMetrics != nil {
+ am.appMetrics.IDPMetrics().CountRequestError()
+ }
+ return connections, err
+ }
+
+ defer func() {
+ err = resp.Body.Close()
+ if err != nil {
+ log.Errorf("close get connections request body: %v", err)
+ }
+ }()
+ if resp.StatusCode != 200 {
+ if am.appMetrics != nil {
+ am.appMetrics.IDPMetrics().CountRequestStatusError()
+ }
+ return connections, fmt.Errorf("unable to get connections, statusCode %d", resp.StatusCode)
+ }
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ log.Debugf("Couldn't read get connections response; %v", err)
+ return connections, err
+ }
+
+ err = am.helper.Unmarshal(body, &connections)
+ if err != nil {
+ log.Debugf("Couldn't unmarshal get connection response; %v", err)
+ return connections, err
+ }
+
+ return connections, err
+}
+
// checkExportJobStatus checks the status of the job created at CreateExportUsersJob.
// If the status is "completed", then return the downloadLink
func (am *Auth0Manager) checkExportJobStatus(jobID string) (bool, string, error) {
diff --git a/management/server/integrated_approval/interface.go b/management/server/integrated_approval/interface.go
index bf1219f47..be09d2669 100644
--- a/management/server/integrated_approval/interface.go
+++ b/management/server/integrated_approval/interface.go
@@ -8,5 +8,6 @@ import (
// IntegratedApproval interface exists to avoid the circle dependencies
type IntegratedApproval interface {
PreparePeer(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) *nbpeer.Peer
- SyncPeer(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool)
+ IsRequiresApproval(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) bool
+ Stop()
}
diff --git a/management/server/management_test.go b/management/server/management_test.go
index af8f51d0a..bc74eded1 100644
--- a/management/server/management_test.go
+++ b/management/server/management_test.go
@@ -452,8 +452,12 @@ func (MocIntegratedApproval) PreparePeer(accountID string, peer *nbpeer.Peer, pe
return peer
}
-func (MocIntegratedApproval) SyncPeer(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool) {
- return peer.Copy(), false
+func (MocIntegratedApproval) IsRequiresApproval(accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) bool {
+ return false
+}
+
+func (MocIntegratedApproval) Stop() {
+
}
func loginPeerWithValidSetupKey(serverPubKey wgtypes.Key, key wgtypes.Key, client mgmtProto.ManagementServiceClient) *mgmtProto.LoginResponse {
diff --git a/management/server/mock_server/account_mock.go b/management/server/mock_server/account_mock.go
index a5628da46..32076cb1f 100644
--- a/management/server/mock_server/account_mock.go
+++ b/management/server/mock_server/account_mock.go
@@ -11,6 +11,7 @@ import (
nbdns "github.com/netbirdio/netbird/dns"
"github.com/netbirdio/netbird/management/server"
"github.com/netbirdio/netbird/management/server/activity"
+ "github.com/netbirdio/netbird/management/server/idp"
"github.com/netbirdio/netbird/management/server/jwtclaims"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/posture"
@@ -93,6 +94,7 @@ type MockAccountManager struct {
DeletePostureChecksFunc func(accountID, postureChecksID, userID string) error
ListPostureChecksFunc func(accountID, userID string) ([]*posture.Checks, error)
GetUsageFunc func(ctx context.Context, accountID string, start, end time.Time) (*server.AccountUsageStats, error)
+ GetIdpManagerFunc func() idp.Manager
UpdateIntegratedApprovalGroupsFunc func(accountID string, userID string, groups []string) error
GroupValidationFunc func(accountId string, groups []string) (bool, error)
}
@@ -707,7 +709,7 @@ func (am *MockAccountManager) ListPostureChecks(accountID, userID string) ([]*po
return nil, status.Errorf(codes.Unimplemented, "method ListPostureChecks is not implemented")
}
-// GetUsage mocks GetCurrentUsage of the AccountManager interface
+// GetUsage mocks GetUsage of the AccountManager interface
func (am *MockAccountManager) GetUsage(ctx context.Context, accountID string, start time.Time, end time.Time) (*server.AccountUsageStats, error) {
if am.GetUsageFunc != nil {
return am.GetUsageFunc(ctx, accountID, start, end)
@@ -715,6 +717,14 @@ func (am *MockAccountManager) GetUsage(ctx context.Context, accountID string, st
return nil, status.Errorf(codes.Unimplemented, "method GetUsage is not implemented")
}
+// GetIdpManager mocks GetIdpManager of the AccountManager interface
+func (am *MockAccountManager) GetIdpManager() idp.Manager {
+ if am.GetIdpManagerFunc != nil {
+ return am.GetIdpManagerFunc()
+ }
+ return nil
+}
+
// UpdateIntegratedApprovalGroups mocks UpdateIntegratedApprovalGroups of the AccountManager interface
func (am *MockAccountManager) UpdateIntegratedApprovalGroups(accountID string, userID string, groups []string) error {
if am.UpdateIntegratedApprovalGroupsFunc != nil {
diff --git a/management/server/peer.go b/management/server/peer.go
index 4a5a9c53e..b8ab3091d 100644
--- a/management/server/peer.go
+++ b/management/server/peer.go
@@ -408,6 +408,8 @@ func (am *DefaultAccountManager) AddPeer(setupKey, userID string, peer *nbpeer.P
return nil, nil, err
}
+ registrationTime := time.Now().UTC()
+
newPeer := &nbpeer.Peer{
ID: xid.New().String(),
Key: peer.Key,
@@ -417,10 +419,11 @@ func (am *DefaultAccountManager) AddPeer(setupKey, userID string, peer *nbpeer.P
Name: peer.Meta.Hostname,
DNSLabel: newLabel,
UserID: userID,
- Status: &nbpeer.PeerStatus{Connected: false, LastSeen: time.Now().UTC()},
+ Status: &nbpeer.PeerStatus{Connected: false, LastSeen: registrationTime},
SSHEnabled: false,
SSHKey: peer.SSHKey,
- LastLogin: time.Now().UTC(),
+ LastLogin: registrationTime,
+ CreatedAt: registrationTime,
LoginExpirationEnabled: addedByUser,
Ephemeral: ephemeral,
}
@@ -518,10 +521,9 @@ func (am *DefaultAccountManager) SyncPeer(sync PeerSync) (*nbpeer.Peer, *Network
return nil, nil, status.Errorf(status.PermissionDenied, "peer login has expired, please log in once more")
}
- peer, updated := am.integratedPeerValidator.SyncPeer(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
-
- if updated {
- account.UpdatePeer(peer)
+ requiresApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
+ if peer.Status.RequiresApproval != requiresApproval {
+ peer.Status.RequiresApproval = requiresApproval
err = am.Store.SaveAccount(account)
if err != nil {
return nil, nil, err
@@ -594,12 +596,12 @@ func (am *DefaultAccountManager) LoginPeer(login PeerLogin) (*nbpeer.Peer, *Netw
am.StoreEvent(login.UserID, peer.ID, account.Id, activity.UserLoggedInPeer, peer.EventMeta(am.GetDNSDomain()))
}
- peer, updated := am.integratedPeerValidator.SyncPeer(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
- if updated {
+ isRequiresApproval := am.integratedPeerValidator.IsRequiresApproval(account.Id, peer, account.GetPeerGroupsList(peer.ID), account.Settings.Extra)
+ if peer.Status.RequiresApproval != isRequiresApproval {
shouldStoreAccount = true
}
- peer, updated = updatePeerMeta(peer, login.Meta, account)
+ peer, updated := updatePeerMeta(peer, login.Meta, account)
if updated {
shouldStoreAccount = true
}
diff --git a/management/server/peer/peer.go b/management/server/peer/peer.go
index f45c1cb9e..e62843180 100644
--- a/management/server/peer/peer.go
+++ b/management/server/peer/peer.go
@@ -40,13 +40,15 @@ type Peer struct {
LoginExpirationEnabled bool
// LastLogin the time when peer performed last login operation
LastLogin time.Time
+ // CreatedAt records the time the peer was created
+ CreatedAt time.Time
// Indicate ephemeral peer attribute
Ephemeral bool
// Geo location based on connection IP
Location Location `gorm:"embedded;embeddedPrefix:location_"`
}
-type PeerStatus struct {
+type PeerStatus struct { //nolint:revive
// LastSeen is the last time peer was connected to the management service
LastSeen time.Time
// Connected indicates whether peer is connected to the management service or not
@@ -71,8 +73,14 @@ type NetworkAddress struct {
Mac string
}
+// Environment is a system environment information
+type Environment struct {
+ Cloud string
+ Platform string
+}
+
// PeerSystemMeta is a metadata of a Peer machine system
-type PeerSystemMeta struct {
+type PeerSystemMeta struct { //nolint:revive
Hostname string
GoOS string
Kernel string
@@ -87,6 +95,7 @@ type PeerSystemMeta struct {
SystemSerialNumber string
SystemProductName string
SystemManufacturer string
+ Environment Environment `gorm:"serializer:json"`
}
func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
@@ -119,7 +128,9 @@ func (p PeerSystemMeta) isEqual(other PeerSystemMeta) bool {
p.UIVersion == other.UIVersion &&
p.SystemSerialNumber == other.SystemSerialNumber &&
p.SystemProductName == other.SystemProductName &&
- p.SystemManufacturer == other.SystemManufacturer
+ p.SystemManufacturer == other.SystemManufacturer &&
+ p.Environment.Cloud == other.Environment.Cloud &&
+ p.Environment.Platform == other.Environment.Platform
}
// AddedWithSSOLogin indicates whether this peer has been added with an SSO login by a user.
@@ -148,6 +159,7 @@ func (p *Peer) Copy() *Peer {
SSHEnabled: p.SSHEnabled,
LoginExpirationEnabled: p.LoginExpirationEnabled,
LastLogin: p.LastLogin,
+ CreatedAt: p.CreatedAt,
Ephemeral: p.Ephemeral,
Location: p.Location,
}
@@ -204,7 +216,7 @@ func (p *Peer) FQDN(dnsDomain string) string {
// EventMeta returns activity event meta related to the peer
func (p *Peer) EventMeta(dnsDomain string) map[string]any {
- return map[string]any{"name": p.Name, "fqdn": p.FQDN(dnsDomain), "ip": p.IP}
+ return map[string]any{"name": p.Name, "fqdn": p.FQDN(dnsDomain), "ip": p.IP, "created_at": p.CreatedAt}
}
// Copy PeerStatus
diff --git a/management/server/posture/checks.go b/management/server/posture/checks.go
index ee85be405..1b1f9d322 100644
--- a/management/server/posture/checks.go
+++ b/management/server/posture/checks.go
@@ -10,10 +10,10 @@ import (
)
const (
- NBVersionCheckName = "NBVersionCheck"
- OSVersionCheckName = "OSVersionCheck"
- GeoLocationCheckName = "GeoLocationCheck"
- PrivateNetworkCheckName = "PrivateNetworkCheck"
+ NBVersionCheckName = "NBVersionCheck"
+ OSVersionCheckName = "OSVersionCheck"
+ GeoLocationCheckName = "GeoLocationCheck"
+ PeerNetworkRangeCheckName = "PeerNetworkRangeCheck"
CheckActionAllow string = "allow"
CheckActionDeny string = "deny"
@@ -44,10 +44,10 @@ type Checks struct {
// ChecksDefinition contains definition of actual check
type ChecksDefinition struct {
- NBVersionCheck *NBVersionCheck `json:",omitempty"`
- OSVersionCheck *OSVersionCheck `json:",omitempty"`
- GeoLocationCheck *GeoLocationCheck `json:",omitempty"`
- PrivateNetworkCheck *PrivateNetworkCheck `json:",omitempty"`
+ NBVersionCheck *NBVersionCheck `json:",omitempty"`
+ OSVersionCheck *OSVersionCheck `json:",omitempty"`
+ GeoLocationCheck *GeoLocationCheck `json:",omitempty"`
+ PeerNetworkRangeCheck *PeerNetworkRangeCheck `json:",omitempty"`
}
// Copy returns a copy of a checks definition.
@@ -85,13 +85,13 @@ func (cd ChecksDefinition) Copy() ChecksDefinition {
}
copy(cdCopy.GeoLocationCheck.Locations, geoCheck.Locations)
}
- if cd.PrivateNetworkCheck != nil {
- privateNetCheck := cd.PrivateNetworkCheck
- cdCopy.PrivateNetworkCheck = &PrivateNetworkCheck{
- Action: privateNetCheck.Action,
- Ranges: make([]netip.Prefix, len(privateNetCheck.Ranges)),
+ if cd.PeerNetworkRangeCheck != nil {
+ peerNetRangeCheck := cd.PeerNetworkRangeCheck
+ cdCopy.PeerNetworkRangeCheck = &PeerNetworkRangeCheck{
+ Action: peerNetRangeCheck.Action,
+ Ranges: make([]netip.Prefix, len(peerNetRangeCheck.Ranges)),
}
- copy(cdCopy.PrivateNetworkCheck.Ranges, privateNetCheck.Ranges)
+ copy(cdCopy.PeerNetworkRangeCheck.Ranges, peerNetRangeCheck.Ranges)
}
return cdCopy
}
@@ -130,8 +130,8 @@ func (pc *Checks) GetChecks() []Check {
if pc.Checks.GeoLocationCheck != nil {
checks = append(checks, pc.Checks.GeoLocationCheck)
}
- if pc.Checks.PrivateNetworkCheck != nil {
- checks = append(checks, pc.Checks.PrivateNetworkCheck)
+ if pc.Checks.PeerNetworkRangeCheck != nil {
+ checks = append(checks, pc.Checks.PeerNetworkRangeCheck)
}
return checks
}
diff --git a/management/server/posture/checks_test.go b/management/server/posture/checks_test.go
index fc36e7f12..d36d4f50c 100644
--- a/management/server/posture/checks_test.go
+++ b/management/server/posture/checks_test.go
@@ -254,7 +254,7 @@ func TestChecks_Copy(t *testing.T) {
},
Action: CheckActionAllow,
},
- PrivateNetworkCheck: &PrivateNetworkCheck{
+ PeerNetworkRangeCheck: &PeerNetworkRangeCheck{
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
netip.MustParsePrefix("10.0.0.0/8"),
diff --git a/management/server/posture/network.go b/management/server/posture/network.go
index 8607d07aa..9bf969f4c 100644
--- a/management/server/posture/network.go
+++ b/management/server/posture/network.go
@@ -8,16 +8,16 @@ import (
nbpeer "github.com/netbirdio/netbird/management/server/peer"
)
-type PrivateNetworkCheck struct {
+type PeerNetworkRangeCheck struct {
Action string
Ranges []netip.Prefix `gorm:"serializer:json"`
}
-var _ Check = (*PrivateNetworkCheck)(nil)
+var _ Check = (*PeerNetworkRangeCheck)(nil)
-func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) {
+func (p *PeerNetworkRangeCheck) Check(peer nbpeer.Peer) (bool, error) {
if len(peer.Meta.NetworkAddresses) == 0 {
- return false, fmt.Errorf("peer's does not contain private network addresses")
+ return false, fmt.Errorf("peer's does not contain peer network range addresses")
}
maskedPrefixes := make([]netip.Prefix, 0, len(p.Ranges))
@@ -34,7 +34,7 @@ func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) {
case CheckActionAllow:
return true, nil
default:
- return false, fmt.Errorf("invalid private network check action: %s", p.Action)
+ return false, fmt.Errorf("invalid peer network range check action: %s", p.Action)
}
}
}
@@ -46,9 +46,9 @@ func (p *PrivateNetworkCheck) Check(peer nbpeer.Peer) (bool, error) {
return false, nil
}
- return false, fmt.Errorf("invalid private network check action: %s", p.Action)
+ return false, fmt.Errorf("invalid peer network range check action: %s", p.Action)
}
-func (p *PrivateNetworkCheck) Name() string {
- return PrivateNetworkCheckName
+func (p *PeerNetworkRangeCheck) Name() string {
+ return PeerNetworkRangeCheckName
}
diff --git a/management/server/posture/network_test.go b/management/server/posture/network_test.go
index 018005460..36ead4660 100644
--- a/management/server/posture/network_test.go
+++ b/management/server/posture/network_test.go
@@ -9,17 +9,17 @@ import (
nbpeer "github.com/netbirdio/netbird/management/server/peer"
)
-func TestPrivateNetworkCheck_Check(t *testing.T) {
+func TestPeerNetworkRangeCheck_Check(t *testing.T) {
tests := []struct {
name string
- check PrivateNetworkCheck
+ check PeerNetworkRangeCheck
peer nbpeer.Peer
wantErr bool
isValid bool
}{
{
- name: "Peer private networks matches the allowed range",
- check: PrivateNetworkCheck{
+ name: "Peer networks range matches the allowed range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionAllow,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
@@ -42,8 +42,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) {
isValid: true,
},
{
- name: "Peer private networks doesn't matches the allowed range",
- check: PrivateNetworkCheck{
+ name: "Peer networks range doesn't matches the allowed range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionAllow,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
@@ -63,8 +63,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) {
isValid: false,
},
{
- name: "Peer with no privates network in the allow range",
- check: PrivateNetworkCheck{
+ name: "Peer with no network range in the allow range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionAllow,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/16"),
@@ -76,8 +76,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) {
isValid: false,
},
{
- name: "Peer private networks matches the denied range",
- check: PrivateNetworkCheck{
+ name: "Peer networks range matches the denied range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionDeny,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
@@ -100,8 +100,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) {
isValid: false,
},
{
- name: "Peer private networks doesn't matches the denied range",
- check: PrivateNetworkCheck{
+ name: "Peer networks range doesn't matches the denied range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionDeny,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/24"),
@@ -121,8 +121,8 @@ func TestPrivateNetworkCheck_Check(t *testing.T) {
isValid: true,
},
{
- name: "Peer with no private networks in the denied range",
- check: PrivateNetworkCheck{
+ name: "Peer with no networks range in the denied range",
+ check: PeerNetworkRangeCheck{
Action: CheckActionDeny,
Ranges: []netip.Prefix{
netip.MustParsePrefix("192.168.0.0/16"),
diff --git a/management/server/scheduler.go b/management/server/scheduler.go
index a35bdc30c..356348056 100644
--- a/management/server/scheduler.go
+++ b/management/server/scheduler.go
@@ -1,9 +1,10 @@
package server
import (
- log "github.com/sirupsen/logrus"
"sync"
"time"
+
+ log "github.com/sirupsen/logrus"
)
// Scheduler is an interface which implementations can schedule and cancel jobs
@@ -55,14 +56,8 @@ func (wm *DefaultScheduler) cancel(ID string) bool {
cancel, ok := wm.jobs[ID]
if ok {
delete(wm.jobs, ID)
- select {
- case cancel <- struct{}{}:
- log.Debugf("cancelled scheduled job %s", ID)
- default:
- log.Warnf("couldn't cancel job %s because there was no routine listening on the cancel event", ID)
- return false
- }
-
+ close(cancel)
+ log.Debugf("cancelled scheduled job %s", ID)
}
return ok
}
@@ -90,25 +85,41 @@ func (wm *DefaultScheduler) Schedule(in time.Duration, ID string, job func() (ne
return
}
+ ticker := time.NewTicker(in)
+
wm.jobs[ID] = cancel
log.Debugf("scheduled a job %s to run in %s. There are %d total jobs scheduled.", ID, in.String(), len(wm.jobs))
go func() {
- select {
- case <-time.After(in):
- log.Debugf("time to do a scheduled job %s", ID)
- runIn, reschedule := job()
- wm.mu.Lock()
- defer wm.mu.Unlock()
- delete(wm.jobs, ID)
- if reschedule {
- go wm.Schedule(runIn, ID, job)
+ for {
+ select {
+ case <-ticker.C:
+ select {
+ case <-cancel:
+ log.Debugf("scheduled job %s was canceled, stop timer", ID)
+ ticker.Stop()
+ return
+ default:
+ log.Debugf("time to do a scheduled job %s", ID)
+ }
+ runIn, reschedule := job()
+ if !reschedule {
+ wm.mu.Lock()
+ defer wm.mu.Unlock()
+ delete(wm.jobs, ID)
+ log.Debugf("job %s is not scheduled to run again", ID)
+ ticker.Stop()
+ return
+ }
+ // we need this comparison to avoid resetting the ticker with the same duration and missing the current elapsesed time
+ if runIn != in {
+ ticker.Reset(runIn)
+ }
+ case <-cancel:
+ log.Debugf("job %s was canceled, stopping timer", ID)
+ ticker.Stop()
+ return
}
- case <-cancel:
- log.Debugf("stopped scheduled job %s ", ID)
- wm.mu.Lock()
- defer wm.mu.Unlock()
- delete(wm.jobs, ID)
- return
}
+
}()
}
diff --git a/management/server/scheduler_test.go b/management/server/scheduler_test.go
index 0c0cef99b..4b2c2e30d 100644
--- a/management/server/scheduler_test.go
+++ b/management/server/scheduler_test.go
@@ -2,11 +2,12 @@ package server
import (
"fmt"
- "github.com/stretchr/testify/assert"
"math/rand"
"sync"
"testing"
"time"
+
+ "github.com/stretchr/testify/assert"
)
func TestScheduler_Performance(t *testing.T) {
@@ -36,15 +37,24 @@ func TestScheduler_Cancel(t *testing.T) {
jobID1 := "test-scheduler-job-1"
jobID2 := "test-scheduler-job-2"
scheduler := NewDefaultScheduler()
- scheduler.Schedule(2*time.Second, jobID1, func() (nextRunIn time.Duration, reschedule bool) {
- return 0, false
+ tChan := make(chan struct{})
+ p := []string{jobID1, jobID2}
+ scheduler.Schedule(2*time.Millisecond, jobID1, func() (nextRunIn time.Duration, reschedule bool) {
+ tt := p[0]
+ <-tChan
+ t.Logf("job %s", tt)
+ return 2 * time.Millisecond, true
})
- scheduler.Schedule(2*time.Second, jobID2, func() (nextRunIn time.Duration, reschedule bool) {
- return 0, false
+ scheduler.Schedule(2*time.Millisecond, jobID2, func() (nextRunIn time.Duration, reschedule bool) {
+ return 2 * time.Millisecond, true
})
+ time.Sleep(4 * time.Millisecond)
assert.Len(t, scheduler.jobs, 2)
scheduler.Cancel([]string{jobID1})
+ close(tChan)
+ p = []string{}
+ time.Sleep(4 * time.Millisecond)
assert.Len(t, scheduler.jobs, 1)
assert.NotNil(t, scheduler.jobs[jobID2])
}
diff --git a/management/server/user.go b/management/server/user.go
index 651488f2b..f1516139b 100644
--- a/management/server/user.go
+++ b/management/server/user.go
@@ -85,6 +85,8 @@ type User struct {
Blocked bool
// LastLogin is the last time the user logged in to IdP
LastLogin time.Time
+ // CreatedAt records the time the user was created
+ CreatedAt time.Time
// Issued of the user
Issued string `gorm:"default:api"`
@@ -173,6 +175,7 @@ func (u *User) Copy() *User {
PATs: pats,
Blocked: u.Blocked,
LastLogin: u.LastLogin,
+ CreatedAt: u.CreatedAt,
Issued: u.Issued,
IntegrationReference: u.IntegrationReference,
}
@@ -188,6 +191,7 @@ func NewUser(id string, role UserRole, isServiceUser bool, nonDeletable bool, se
ServiceUserName: serviceUserName,
AutoGroups: autoGroups,
Issued: issued,
+ CreatedAt: time.Now().UTC(),
}
}
@@ -338,6 +342,7 @@ func (am *DefaultAccountManager) inviteNewUser(accountID, userID string, invite
AutoGroups: invite.AutoGroups,
Issued: invite.Issued,
IntegrationReference: invite.IntegrationReference,
+ CreatedAt: time.Now().UTC(),
}
account.Users[idpUser.ID] = newUser
@@ -414,7 +419,7 @@ func (am *DefaultAccountManager) ListUsers(accountID string) ([]*User, error) {
}
func (am *DefaultAccountManager) deleteServiceUser(account *Account, initiatorUserID string, targetUser *User) {
- meta := map[string]any{"name": targetUser.ServiceUserName}
+ meta := map[string]any{"name": targetUser.ServiceUserName, "created_at": targetUser.CreatedAt}
am.StoreEvent(initiatorUserID, targetUser.Id, account.Id, activity.ServiceUserDeleted, meta)
delete(account.Users, targetUser.Id)
}
@@ -494,13 +499,23 @@ func (am *DefaultAccountManager) deleteRegularUser(account *Account, initiatorUs
return err
}
+ u, err := account.FindUser(targetUserID)
+ if err != nil {
+ log.Errorf("failed to find user %s for deletion, this should never happen: %s", targetUserID, err)
+ }
+
+ var tuCreatedAt time.Time
+ if u != nil {
+ tuCreatedAt = u.CreatedAt
+ }
+
delete(account.Users, targetUserID)
err = am.Store.SaveAccount(account)
if err != nil {
return err
}
- meta := map[string]any{"name": tuName, "email": tuEmail}
+ meta := map[string]any{"name": tuName, "email": tuEmail, "created_at": tuCreatedAt}
am.StoreEvent(initiatorUserID, targetUserID, account.Id, activity.UserDeleted, meta)
am.updateAccountPeers(account)
diff --git a/management/server/user_test.go b/management/server/user_test.go
index 8de2267b3..50cd726ef 100644
--- a/management/server/user_test.go
+++ b/management/server/user_test.go
@@ -273,7 +273,8 @@ func TestUser_Copy(t *testing.T) {
},
},
Blocked: false,
- LastLogin: time.Now(),
+ LastLogin: time.Now().UTC(),
+ CreatedAt: time.Now().UTC(),
Issued: "test",
IntegrationReference: IntegrationReference{
ID: 0,
diff --git a/signal/client/grpc.go b/signal/client/grpc.go
index 07276aef1..7531608c3 100644
--- a/signal/client/grpc.go
+++ b/signal/client/grpc.go
@@ -21,11 +21,10 @@ import (
"google.golang.org/grpc/status"
"github.com/netbirdio/netbird/encryption"
+ "github.com/netbirdio/netbird/management/client"
"github.com/netbirdio/netbird/signal/proto"
)
-const defaultSendTimeout = 5 * time.Second
-
// ConnStateNotifier is a wrapper interface of the status recorder
type ConnStateNotifier interface {
MarkSignalDisconnected(error)
@@ -71,7 +70,7 @@ func NewClient(ctx context.Context, addr string, key wgtypes.Key, tlsEnabled boo
transportOption = grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))
}
- sigCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
+ sigCtx, cancel := context.WithTimeout(ctx, client.ConnectTimeout)
defer cancel()
conn, err := grpc.DialContext(
sigCtx,
@@ -353,7 +352,7 @@ func (c *GrpcClient) Send(msg *proto.Message) error {
return err
}
- attemptTimeout := defaultSendTimeout
+ attemptTimeout := client.ConnectTimeout
for attempt := 0; attempt < 4; attempt++ {
if attempt > 1 {
diff --git a/signal/cmd/run.go b/signal/cmd/run.go
index 9b52fb52d..10a2da636 100644
--- a/signal/cmd/run.go
+++ b/signal/cmd/run.go
@@ -4,7 +4,6 @@ import (
"errors"
"flag"
"fmt"
- "golang.org/x/crypto/acme/autocert"
"io"
"io/fs"
"net"
@@ -14,10 +13,14 @@ import (
"strings"
"time"
+ "golang.org/x/crypto/acme/autocert"
+
"github.com/netbirdio/netbird/encryption"
"github.com/netbirdio/netbird/signal/proto"
"github.com/netbirdio/netbird/signal/server"
"github.com/netbirdio/netbird/util"
+ "github.com/netbirdio/netbird/version"
+
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc"
@@ -129,6 +132,7 @@ var (
log.Infof("running gRPC server: %s", grpcListener.Addr().String())
}
+ log.Infof("signal server version %s", version.NetbirdVersion())
log.Infof("started Signal Service")
SetupCloseHandler()