Files
netbird/management/cmd/management_test.go
T
Nicolas Frati fe7841721a [management] Create HttpConfig before applying TLS flag overrides (#8168)
With the embedded IdP, management.json can leave out the HttpConfig
section, and ApplyEmbeddedIdPConfig creates it later. Command-line
overrides run before that, so --letsencrypt-domain, or --cert-file with
--cert-key, dereferenced a nil HttpConfig and management crashed at
startup.

Create the section only when one of those flags writes to it, so a
config without TLS flags keeps HttpConfig unset.
2026-10-12 13:44:30 +02:00

147 lines
4.3 KiB
Go

package cmd
import (
"context"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
"github.com/netbirdio/netbird/management/server/idp"
"github.com/netbirdio/netbird/shared/management/grpc"
)
const (
exampleConfig = `{
"Relay": {
"Addresses": [
"rel://192.168.100.1:8085",
"rel://192.168.100.1:8086"
],
"CredentialsTTL": "12h0m0s",
"Secret": "8f7e9d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8"
},
"HttpConfig": {
"AuthAudience": "https://stageapp/",
"AuthIssuer": "https://something.eu.auth0.com/",
"OIDCConfigEndpoint": "https://something.eu.auth0.com/.well-known/openid-configuration"
},
"HighestSupportedSyncMessageVersion": 1,
"PerAccountHighestSupportedSyncMessageVersion": {
"1": 0,
"2": 1
}
}`
)
func Test_LoadMgmtConfig(t *testing.T) {
tmpFile, err := createConfig(exampleConfig)
assert.NoError(t, err)
cfg, err := LoadMgmtConfig(context.Background(), tmpFile)
assert.NoError(t, err)
assert.NotEmpty(t, cfg.Relay)
assert.NotEmpty(t, cfg.Relay.Addresses)
assert.Equal(t, int(grpc.ComponentNetworkMap), *cfg.HighestSupportedSyncMessageVersion)
assert.Equal(t, map[string]int{"1": int(grpc.Base), "2": int(grpc.ComponentNetworkMap)}, cfg.PerAccountHighestSupportedSyncMessageVersion)
}
func Test_LoadMgmtConfig_Empty(t *testing.T) {
tmpFile, err := createConfig(`{
"HttpConfig": {
"AuthAudience": "https://stageapp/",
"AuthIssuer": "https://something.eu.auth0.com/",
"OIDCConfigEndpoint": "https://something.eu.auth0.com/.well-known/openid-configuration"
}
}`)
assert.NoError(t, err)
cfg, err := LoadMgmtConfig(context.Background(), tmpFile)
assert.NoError(t, err)
assert.Nil(t, cfg.HighestSupportedSyncMessageVersion)
assert.Nil(t, cfg.PerAccountHighestSupportedSyncMessageVersion)
}
func TestApplyEmbeddedIdPConfigRequiresSingleAccountDomain(t *testing.T) {
previousDomain := mgmtSingleAccModeDomain
previousDisabled := disableSingleAccMode
t.Cleanup(func() {
mgmtSingleAccModeDomain = previousDomain
disableSingleAccMode = previousDisabled
})
mgmtSingleAccModeDomain = ""
disableSingleAccMode = false
cfg := &nbconfig.Config{
EmbeddedIdP: &idp.EmbeddedIdPConfig{Enabled: true},
}
require.ErrorContains(t, ApplyEmbeddedIdPConfig(context.Background(), cfg), "embedded IdP requires single account mode")
}
// A config without an HttpConfig section is valid with the embedded IdP, so the
// TLS flags must not assume the section exists.
func TestApplyCommandLineOverridesWithoutHttpConfig(t *testing.T) {
previousDomain, previousCertFile, previousCertKey := mgmtLetsencryptDomain, certFile, certKey
t.Cleanup(func() {
mgmtLetsencryptDomain, certFile, certKey = previousDomain, previousCertFile, previousCertKey
})
tests := []struct {
name string
domain string
certFile string
certKey string
want nbconfig.HttpServerConfig
}{
{
name: "letsencrypt domain",
domain: "mgmt.example.com",
want: nbconfig.HttpServerConfig{LetsEncryptDomain: "mgmt.example.com"},
},
{
name: "certificate files",
certFile: "/etc/netbird/tls/tls.crt",
certKey: "/etc/netbird/tls/tls.key",
want: nbconfig.HttpServerConfig{CertFile: "/etc/netbird/tls/tls.crt", CertKey: "/etc/netbird/tls/tls.key"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mgmtLetsencryptDomain, certFile, certKey = tt.domain, tt.certFile, tt.certKey
cfg := &nbconfig.Config{}
ApplyCommandLineOverrides(cfg)
require.NotNil(t, cfg.HttpConfig, "HttpConfig should be created for the TLS flags")
assert.Equal(t, tt.want, *cfg.HttpConfig, "HttpConfig should carry only the flag values")
})
}
t.Run("no TLS flags", func(t *testing.T) {
mgmtLetsencryptDomain, certFile, certKey = "", "", ""
cfg := &nbconfig.Config{}
ApplyCommandLineOverrides(cfg)
assert.Nil(t, cfg.HttpConfig, "HttpConfig should stay unset so the embedded IdP does not warn about it")
})
}
func createConfig(config string) (string, error) {
tmpfile, err := os.CreateTemp("", "config.json")
if err != nil {
return "", err
}
_, err = tmpfile.Write([]byte(config))
if err != nil {
return "", err
}
if err := tmpfile.Close(); err != nil {
return "", err
}
return tmpfile.Name(), nil
}