|
|
@@ -1,10 +1,16 @@
|
|
|
package nebula
|
|
|
|
|
|
import (
|
|
|
+ "fmt"
|
|
|
+ "net/netip"
|
|
|
"strings"
|
|
|
"testing"
|
|
|
+ "time"
|
|
|
|
|
|
"github.com/slackhq/nebula/cert"
|
|
|
+ "github.com/slackhq/nebula/cert_test"
|
|
|
+ "github.com/slackhq/nebula/config"
|
|
|
+ "github.com/slackhq/nebula/test"
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
"github.com/stretchr/testify/require"
|
|
|
)
|
|
|
@@ -92,3 +98,83 @@ func TestNewCipherSuiteUnsupportedCurve(t *testing.T) {
|
|
|
assert.True(t, strings.HasPrefix(err.Error(), "unsupported curve:"), "got: %v", err)
|
|
|
assert.Nil(t, cs)
|
|
|
}
|
|
|
+
|
|
|
+func TestPKIReloadRestartRequired(t *testing.T) {
|
|
|
+ ca, _, caKey, caPEM := cert_test.NewTestCaCert(cert.Version2, cert.Curve_CURVE25519, time.Time{}, time.Time{}, nil, nil, nil)
|
|
|
+ pkiConfig := func(cipher, network string) string {
|
|
|
+ _, _, keyPEM, certPEM := cert_test.NewTestCert(cert.Version2, cert.Curve_CURVE25519, ca, caKey, "host", time.Time{}, time.Time{}, []netip.Prefix{netip.MustParsePrefix(network)}, nil, nil)
|
|
|
+ return fmt.Sprintf("cipher: %s\npki:\n ca: %q\n cert: %q\n key: %q\n", cipher, caPEM, certPEM, keyPEM)
|
|
|
+ }
|
|
|
+
|
|
|
+ c := config.NewC(test.NewLogger())
|
|
|
+ require.NoError(t, c.LoadString(pkiConfig("aes", "10.1.0.2/24")))
|
|
|
+ p, err := NewPKIFromConfig(test.NewLogger(), c)
|
|
|
+ require.NoError(t, err)
|
|
|
+
|
|
|
+ // A cert that changes our networks is refused and needs a restart, it is not a failure
|
|
|
+ res := c.ReloadConfigString(pkiConfig("aes", "10.1.0.3/24"))
|
|
|
+ require.NoError(t, res.Err)
|
|
|
+ assert.True(t, res.RestartRequired)
|
|
|
+ assert.False(t, res.Failed)
|
|
|
+ assert.Equal(t, []netip.Prefix{netip.MustParsePrefix("10.1.0.2/24")}, p.getCertState().myVpnNetworks)
|
|
|
+
|
|
|
+ // The cipher only applies at startup
|
|
|
+ c2 := config.NewC(test.NewLogger())
|
|
|
+ require.NoError(t, c2.LoadString(pkiConfig("aes", "10.1.0.2/24")))
|
|
|
+ p, err = NewPKIFromConfig(test.NewLogger(), c2)
|
|
|
+ require.NoError(t, err)
|
|
|
+ res = c2.ReloadConfigString(pkiConfig("chachapoly", "10.1.0.2/24"))
|
|
|
+ require.NoError(t, res.Err)
|
|
|
+ assert.True(t, res.RestartRequired)
|
|
|
+ assert.Equal(t, "aes", p.getCertState().cipher)
|
|
|
+
|
|
|
+ // A cert that keeps our networks applies without a restart
|
|
|
+ c3 := config.NewC(test.NewLogger())
|
|
|
+ require.NoError(t, c3.LoadString(pkiConfig("aes", "10.1.0.2/24")))
|
|
|
+ _, err = NewPKIFromConfig(test.NewLogger(), c3)
|
|
|
+ require.NoError(t, err)
|
|
|
+ res = c3.ReloadConfigString(pkiConfig("aes", "10.1.0.2/24"))
|
|
|
+ require.NoError(t, res.Err)
|
|
|
+ assert.False(t, res.RestartRequired)
|
|
|
+
|
|
|
+ // A cert that can't be read is a failure, and a restart wouldn't help
|
|
|
+ res = c3.ReloadConfigString(strings.Replace(pkiConfig("aes", "10.1.0.2/24"), "cert: \"", "cert: \"garbage", 1))
|
|
|
+ require.NoError(t, res.Err)
|
|
|
+ assert.True(t, res.Failed)
|
|
|
+ assert.False(t, res.RestartRequired)
|
|
|
+}
|
|
|
+
|
|
|
+// A cert for a version we weren't running is accepted without comparing networks, so switching to one with different
|
|
|
+// networks needs a restart. One with the same networks doesn't
|
|
|
+func TestPKIReloadNewVersionWithOtherNetworks(t *testing.T) {
|
|
|
+ ca1, _, ca1Key, ca1PEM := cert_test.NewTestCaCert(cert.Version1, cert.Curve_CURVE25519, time.Time{}, time.Time{}, nil, nil, nil)
|
|
|
+ ca2, _, ca2Key, ca2PEM := cert_test.NewTestCaCert(cert.Version2, cert.Curve_CURVE25519, time.Time{}, time.Time{}, nil, nil, nil)
|
|
|
+ caPEM := string(ca1PEM) + string(ca2PEM)
|
|
|
+ pkiConfig := func(v cert.Version, network string) string {
|
|
|
+ ca, caKey := ca1, ca1Key
|
|
|
+ if v == cert.Version2 {
|
|
|
+ ca, caKey = ca2, ca2Key
|
|
|
+ }
|
|
|
+ _, _, keyPEM, certPEM := cert_test.NewTestCert(v, cert.Curve_CURVE25519, ca, caKey, "host", time.Time{}, time.Time{}, []netip.Prefix{netip.MustParsePrefix(network)}, nil, nil)
|
|
|
+ return fmt.Sprintf("pki:\n ca: %q\n cert: %q\n key: %q\n", caPEM, certPEM, keyPEM)
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tc := range []struct {
|
|
|
+ network string
|
|
|
+ restart bool
|
|
|
+ }{
|
|
|
+ {"10.9.0.7/24", true},
|
|
|
+ {"10.1.0.2/24", false},
|
|
|
+ } {
|
|
|
+ c := config.NewC(test.NewLogger())
|
|
|
+ require.NoError(t, c.LoadString(pkiConfig(cert.Version1, "10.1.0.2/24")))
|
|
|
+ p, err := NewPKIFromConfig(test.NewLogger(), c)
|
|
|
+ require.NoError(t, err)
|
|
|
+
|
|
|
+ res := c.ReloadConfigString(pkiConfig(cert.Version2, tc.network))
|
|
|
+ require.NoError(t, res.Err)
|
|
|
+ assert.False(t, res.Failed, tc.network)
|
|
|
+ assert.Equal(t, tc.restart, res.RestartRequired, tc.network)
|
|
|
+ assert.Equal(t, []netip.Prefix{netip.MustParsePrefix(tc.network)}, p.getCertState().myVpnNetworks, "accepted either way, as before")
|
|
|
+ }
|
|
|
+}
|