diff --git a/cmd/nebula-cert/ca.go b/cmd/nebula-cert/ca.go index 9fe1192..ce8d5fa 100644 --- a/cmd/nebula-cert/ca.go +++ b/cmd/nebula-cert/ca.go @@ -37,8 +37,8 @@ func newCaFlags() *caFlags { cf.outCertPath = cf.set.String("out-crt", "ca.crt", "Optional: path to write the certificate to") cf.outQRPath = cf.set.String("out-qr", "", "Optional: output a qr code image (png) of the certificate") cf.groups = cf.set.String("groups", "", "Optional: comma separated list of groups. This will limit which groups subordinate certs can use") - cf.ips = cf.set.String("ips", "", "Optional: comma separated list of ip and network in CIDR notation. This will limit which ip addresses and networks subordinate certs can use") - cf.subnets = cf.set.String("subnets", "", "Optional: comma separated list of ip and network in CIDR notation. This will limit which subnet addresses and networks subordinate certs can use") + cf.ips = cf.set.String("ips", "", "Optional: comma separated list of ipv4 address and network in CIDR notation. This will limit which ipv4 addresses and networks subordinate certs can use for ip addresses") + cf.subnets = cf.set.String("subnets", "", "Optional: comma separated list of ipv4 address and network in CIDR notation. This will limit which ipv4 addresses and networks subordinate certs can use in subnets") return &cf } @@ -82,6 +82,9 @@ func ca(args []string, out io.Writer, errOut io.Writer) error { if err != nil { return newHelpErrorf("invalid ip definition: %s", err) } + if ip.To4() == nil { + return newHelpErrorf("invalid ip definition: can only be ipv4, have %s", rs) + } ipNet.IP = ip ips = append(ips, ipNet) @@ -98,6 +101,9 @@ func ca(args []string, out io.Writer, errOut io.Writer) error { if err != nil { return newHelpErrorf("invalid subnet definition: %s", err) } + if s.IP.To4() == nil { + return newHelpErrorf("invalid subnet definition: can only be ipv4, have %s", rs) + } subnets = append(subnets, s) } } diff --git a/cmd/nebula-cert/ca_test.go b/cmd/nebula-cert/ca_test.go index be803ed..372a4f1 100644 --- a/cmd/nebula-cert/ca_test.go +++ b/cmd/nebula-cert/ca_test.go @@ -31,7 +31,7 @@ func Test_caHelp(t *testing.T) { " -groups string\n"+ " \tOptional: comma separated list of groups. This will limit which groups subordinate certs can use\n"+ " -ips string\n"+ - " \tOptional: comma separated list of ip and network in CIDR notation. This will limit which ip addresses and networks subordinate certs can use\n"+ + " \tOptional: comma separated list of ipv4 address and network in CIDR notation. This will limit which ipv4 addresses and networks subordinate certs can use for ip addresses\n"+ " -name string\n"+ " \tRequired: name of the certificate authority\n"+ " -out-crt string\n"+ @@ -41,7 +41,7 @@ func Test_caHelp(t *testing.T) { " -out-qr string\n"+ " \tOptional: output a qr code image (png) of the certificate\n"+ " -subnets string\n"+ - " \tOptional: comma separated list of ip and network in CIDR notation. This will limit which subnet addresses and networks subordinate certs can use\n", + " \tOptional: comma separated list of ipv4 address and network in CIDR notation. This will limit which ipv4 addresses and networks subordinate certs can use in subnets\n", ob.String(), ) } @@ -55,6 +55,16 @@ func Test_ca(t *testing.T) { assert.Equal(t, "", ob.String()) assert.Equal(t, "", eb.String()) + // ipv4 only ips + assertHelpError(t, ca([]string{"-name", "ipv6", "-ips", "100::100/100"}, ob, eb), "invalid ip definition: can only be ipv4, have 100::100/100") + assert.Equal(t, "", ob.String()) + assert.Equal(t, "", eb.String()) + + // ipv4 only subnets + assertHelpError(t, ca([]string{"-name", "ipv6", "-subnets", "100::100/100"}, ob, eb), "invalid subnet definition: can only be ipv4, have 100::100/100") + assert.Equal(t, "", ob.String()) + assert.Equal(t, "", eb.String()) + // failed key write ob.Reset() eb.Reset() diff --git a/cmd/nebula-cert/sign.go b/cmd/nebula-cert/sign.go index 1f3ddea..4b3b899 100644 --- a/cmd/nebula-cert/sign.go +++ b/cmd/nebula-cert/sign.go @@ -37,14 +37,14 @@ func newSignFlags() *signFlags { sf.caKeyPath = sf.set.String("ca-key", "ca.key", "Optional: path to the signing CA key") sf.caCertPath = sf.set.String("ca-crt", "ca.crt", "Optional: path to the signing CA cert") sf.name = sf.set.String("name", "", "Required: name of the cert, usually a hostname") - sf.ip = sf.set.String("ip", "", "Required: ip and network in CIDR notation to assign the cert") + sf.ip = sf.set.String("ip", "", "Required: ipv4 address and network in CIDR notation to assign the cert") sf.duration = sf.set.Duration("duration", 0, "Optional: how long the cert should be valid for. The default is 1 second before the signing cert expires. Valid time units are seconds: \"s\", minutes: \"m\", hours: \"h\"") sf.inPubPath = sf.set.String("in-pub", "", "Optional (if out-key not set): path to read a previously generated public key") sf.outKeyPath = sf.set.String("out-key", "", "Optional (if in-pub not set): path to write the private key to") sf.outCertPath = sf.set.String("out-crt", "", "Optional: path to write the certificate to") sf.outQRPath = sf.set.String("out-qr", "", "Optional: output a qr code image (png) of the certificate") sf.groups = sf.set.String("groups", "", "Optional: comma separated list of groups") - sf.subnets = sf.set.String("subnets", "", "Optional: comma separated list of subnet this cert can serve for") + sf.subnets = sf.set.String("subnets", "", "Optional: comma separated list of ipv4 address and network in CIDR notation. Subnets this cert can serve for") return &sf } @@ -114,6 +114,9 @@ func signCert(args []string, out io.Writer, errOut io.Writer) error { if err != nil { return newHelpErrorf("invalid ip definition: %s", err) } + if ip.To4() == nil { + return newHelpErrorf("invalid ip definition: can only be ipv4, have %s", *sf.ip) + } ipNet.IP = ip groups := []string{} @@ -135,6 +138,9 @@ func signCert(args []string, out io.Writer, errOut io.Writer) error { if err != nil { return newHelpErrorf("invalid subnet definition: %s", err) } + if s.IP.To4() == nil { + return newHelpErrorf("invalid subnet definition: can only be ipv4, have %s", rs) + } subnets = append(subnets, s) } } diff --git a/cmd/nebula-cert/sign_test.go b/cmd/nebula-cert/sign_test.go index 4ccfaf3..4976fa3 100644 --- a/cmd/nebula-cert/sign_test.go +++ b/cmd/nebula-cert/sign_test.go @@ -39,7 +39,7 @@ func Test_signHelp(t *testing.T) { " -in-pub string\n"+ " \tOptional (if out-key not set): path to read a previously generated public key\n"+ " -ip string\n"+ - " \tRequired: ip and network in CIDR notation to assign the cert\n"+ + " \tRequired: ipv4 address and network in CIDR notation to assign the cert\n"+ " -name string\n"+ " \tRequired: name of the cert, usually a hostname\n"+ " -out-crt string\n"+ @@ -49,7 +49,7 @@ func Test_signHelp(t *testing.T) { " -out-qr string\n"+ " \tOptional: output a qr code image (png) of the certificate\n"+ " -subnets string\n"+ - " \tOptional: comma separated list of subnet this cert can serve for\n", + " \tOptional: comma separated list of ipv4 address and network in CIDR notation. Subnets this cert can serve for\n", ob.String(), ) } @@ -59,7 +59,6 @@ func Test_signCert(t *testing.T) { eb := &bytes.Buffer{} // required args - assertHelpError(t, signCert([]string{"-ca-crt", "./nope", "-ca-key", "./nope", "-ip", "1.1.1.1/24", "-out-key", "nope", "-out-crt", "nope"}, ob, eb), "-name is required") assert.Empty(t, ob.String()) assert.Empty(t, eb.String()) @@ -160,6 +159,13 @@ func Test_signCert(t *testing.T) { assert.Empty(t, ob.String()) assert.Empty(t, eb.String()) + ob.Reset() + eb.Reset() + args = []string{"-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "100::100/100", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"} + assertHelpError(t, signCert(args, ob, eb), "invalid ip definition: can only be ipv4, have 100::100/100") + assert.Empty(t, ob.String()) + assert.Empty(t, eb.String()) + // bad subnet cidr ob.Reset() eb.Reset() @@ -168,6 +174,13 @@ func Test_signCert(t *testing.T) { assert.Empty(t, ob.String()) assert.Empty(t, eb.String()) + ob.Reset() + eb.Reset() + args = []string{"-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m", "-subnets", "100::100/100"} + assertHelpError(t, signCert(args, ob, eb), "invalid subnet definition: can only be ipv4, have 100::100/100") + assert.Empty(t, ob.String()) + assert.Empty(t, eb.String()) + // mismatched ca key _, caPriv2, _ := ed25519.GenerateKey(rand.Reader) caKeyF2, err := ioutil.TempFile("", "sign-cert-2.key")