diff --git a/Gopkg.lock b/Gopkg.lock index b8b3dcb3..6293e4c3 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -231,7 +231,7 @@ "utils", ] pruneopts = "UT" - revision = "a1df67d396f730ff0e7bf1916cd27ae8d5255236" + revision = "49d4a4c26c802e83c5ed160abdd5babab1c9b5c6" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index 0e564d1f..0ed06849 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -45,7 +45,7 @@ required = [ name = "github.com/go-chi/chi" [[override]] - branch = "master" + branch = "sans" name = "github.com/smallstep/cli" [prune] diff --git a/authority/claims.go b/authority/claims.go index 2af4d358..d2c45882 100644 --- a/authority/claims.go +++ b/authority/claims.go @@ -1,10 +1,8 @@ package authority import ( - "bytes" - "fmt" "net" - "sort" + "reflect" "time" "github.com/pkg/errors" @@ -50,17 +48,16 @@ type dnsNamesClaim struct { // Valid checks that certificate request common name matches the one configured. func (c *dnsNamesClaim) Valid(crt *x509.Certificate) error { - sort.Strings(c.names) - sort.Strings(crt.DNSNames) - if len(c.names) != len(crt.DNSNames) { - fmt.Printf("len(c.names) = %+v, len(crt.DNSNames) = %+v\n", len(c.names), len(crt.DNSNames)) - return errors.Errorf("DNS names claim failed - got %s, want %s", crt.DNSNames, c.names) + tokMap := make(map[string]int) + for _, e := range c.names { + tokMap[e] = 1 } - for i := range c.names { - if c.names[i] != crt.DNSNames[i] { - fmt.Printf("c.names[i] = %+v, crt.DNSNames[i] = %+v\n", c.names[i], crt.DNSNames[i]) - return errors.Errorf("DNS names claim failed - got %s, want %s", crt.DNSNames, c.names) - } + crtMap := make(map[string]int) + for _, e := range crt.DNSNames { + crtMap[e] = 1 + } + if !reflect.DeepEqual(tokMap, crtMap) { + return errors.Errorf("DNS names claim failed - got %s, want %s", crt.DNSNames, c.names) } return nil } @@ -71,19 +68,16 @@ type ipAddressesClaim struct { // Valid checks that certificate request common name matches the one configured. func (c *ipAddressesClaim) Valid(crt *x509.Certificate) error { - if len(c.ips) != len(crt.IPAddresses) { - return errors.Errorf("IP Addresses claim failed - got %v, want %v", crt.IPAddresses, c.ips) + tokMap := make(map[string]int) + for _, e := range c.ips { + tokMap[e.String()] = 1 } - sort.Slice(c.ips, func(i, j int) bool { - return bytes.Compare(c.ips[i], c.ips[j]) < 0 - }) - sort.Slice(crt.IPAddresses, func(i, j int) bool { - return bytes.Compare(crt.IPAddresses[i], crt.IPAddresses[j]) < 0 - }) - for i := range c.ips { - if !c.ips[i].Equal(crt.IPAddresses[i]) { - return errors.Errorf("IP Addresses claim failed - got %v, want %v", crt.IPAddresses[i], c.ips[i]) - } + crtMap := make(map[string]int) + for _, e := range crt.IPAddresses { + crtMap[e.String()] = 1 + } + if !reflect.DeepEqual(tokMap, crtMap) { + return errors.Errorf("IP Addresses claim failed - got %v, want %v", crt.IPAddresses, c.ips) } return nil } diff --git a/authority/claims_test.go b/authority/claims_test.go index 02a327cc..d9c9d768 100644 --- a/authority/claims_test.go +++ b/authority/claims_test.go @@ -52,23 +52,28 @@ func TestIPAddressesClaim_Valid(t *testing.T) { crt *x509.Certificate err error }{ - "unexpected-ip": { - iac: &ipAddressesClaim{name: "127.0.0.1"}, + "unexpected-ip-in-crt": { + iac: &ipAddressesClaim{ips: []net.IP{net.ParseIP("127.0.0.1")}}, crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("1.1.1.1")}}, - err: errors.New("IP addresses claim failed - got 1.1.1.1, want 127.0.0.1"), + err: errors.New("IP Addresses claim failed - got [127.0.0.1 1.1.1.1], want [127.0.0.1]"), + }, + "missing-ip-in-crt": { + iac: &ipAddressesClaim{ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("1.1.1.1")}}, + crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}}, + err: errors.New("IP Addresses claim failed - got [127.0.0.1], want [127.0.0.1 1.1.1.1]"), }, "invalid-matcher-nonempty-ips": { - iac: &ipAddressesClaim{name: "invalid"}, + iac: &ipAddressesClaim{ips: []net.IP{}}, crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}}, - err: errors.New("IP addresses claim failed - got [127.0.0.1], want none"), + err: errors.New("IP Addresses claim failed - got [127.0.0.1], want []"), }, "ok": { - iac: &ipAddressesClaim{name: "127.0.0.1"}, + iac: &ipAddressesClaim{ips: []net.IP{net.ParseIP("127.0.0.1")}}, crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}}, }, - "ok-empty-ips": { - iac: &ipAddressesClaim{name: "127.0.0.1"}, - crt: &x509.Certificate{IPAddresses: []net.IP{}}, + "ok-multiple-identical-ip-entries": { + iac: &ipAddressesClaim{ips: []net.IP{net.ParseIP("127.0.0.1")}}, + crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.1")}}, }, } @@ -92,21 +97,22 @@ func TestDNSNamesClaim_Valid(t *testing.T) { crt *x509.Certificate err error }{ - "wrong-dns-name": { - dnc: &dnsNamesClaim{name: "foo"}, + "unexpected-dns-name-in-crt": { + dnc: &dnsNamesClaim{names: []string{"foo"}}, crt: &x509.Certificate{DNSNames: []string{"foo", "bar"}}, - err: errors.New("DNS names claim failed - got bar, want foo"), + err: errors.New("DNS names claim failed - got [foo bar], want [foo]"), }, "ok": { - dnc: &dnsNamesClaim{name: "foo"}, - crt: &x509.Certificate{DNSNames: []string{"foo"}}, + dnc: &dnsNamesClaim{names: []string{"foo", "bar"}}, + crt: &x509.Certificate{DNSNames: []string{"bar", "foo"}}, }, - "ok-empty-dnsNames": { - dnc: &dnsNamesClaim{"foo"}, - crt: &x509.Certificate{}, + "missing-dns-name-in-crt": { + dnc: &dnsNamesClaim{names: []string{"foo", "bar"}}, + crt: &x509.Certificate{DNSNames: []string{"foo"}}, + err: errors.New("DNS names claim failed - got [foo], want [foo bar]"), }, "ok-multiple-identical-dns-entries": { - dnc: &dnsNamesClaim{name: "foo"}, + dnc: &dnsNamesClaim{names: []string{"foo"}}, crt: &x509.Certificate{DNSNames: []string{"foo", "foo", "foo"}}, }, } diff --git a/authority/tls.go b/authority/tls.go index 6ca433ff..bd086bee 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -197,15 +197,15 @@ func (a *Authority) Renew(ocx *x509.Certificate) (*x509.Certificate, *x509.Certi ExtKeyUsage: oldCert.ExtKeyUsage, UnknownExtKeyUsage: oldCert.UnknownExtKeyUsage, BasicConstraintsValid: oldCert.BasicConstraintsValid, - IsCA: oldCert.IsCA, - MaxPathLen: oldCert.MaxPathLen, - MaxPathLenZero: oldCert.MaxPathLenZero, - OCSPServer: oldCert.OCSPServer, - IssuingCertificateURL: oldCert.IssuingCertificateURL, - DNSNames: oldCert.DNSNames, - EmailAddresses: oldCert.EmailAddresses, - IPAddresses: oldCert.IPAddresses, - URIs: oldCert.URIs, + IsCA: oldCert.IsCA, + MaxPathLen: oldCert.MaxPathLen, + MaxPathLenZero: oldCert.MaxPathLenZero, + OCSPServer: oldCert.OCSPServer, + IssuingCertificateURL: oldCert.IssuingCertificateURL, + DNSNames: oldCert.DNSNames, + EmailAddresses: oldCert.EmailAddresses, + IPAddresses: oldCert.IPAddresses, + URIs: oldCert.URIs, PermittedDNSDomainsCritical: oldCert.PermittedDNSDomainsCritical, PermittedDNSDomains: oldCert.PermittedDNSDomains, ExcludedDNSDomains: oldCert.ExcludedDNSDomains, diff --git a/ca/bootstrap_test.go b/ca/bootstrap_test.go index 6a0a7159..540b1b20 100644 --- a/ca/bootstrap_test.go +++ b/ca/bootstrap_test.go @@ -94,6 +94,7 @@ func generateBootstrapToken(ca, subject, sha string) string { cl := struct { SHA string `json:"sha"` jwt.Claims + SANS []string `json:"sans"` }{ SHA: sha, Claims: jwt.Claims{ @@ -104,6 +105,7 @@ func generateBootstrapToken(ca, subject, sha string) string { Expiry: jwt.NewNumericDate(now.Add(time.Minute)), Audience: []string{ca + "/sign"}, }, + SANS: []string{subject}, } raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() if err != nil { diff --git a/ca/ca_test.go b/ca/ca_test.go index 99714208..8bec48a1 100644 --- a/ca/ca_test.go +++ b/ca/ca_test.go @@ -154,13 +154,19 @@ ZEp7knvU2psWRw== "fail commonname-claim": func(t *testing.T) *signTest { jti, err := randutil.ASCII(32) assert.FatalError(t, err) - cl := jwt.Claims{ - Subject: "invalid", - Issuer: "step-cli", - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAud, - ID: jti, + cl := struct { + jwt.Claims + SANS []string `json:"sans"` + }{ + Claims: jwt.Claims{ + Subject: "invalid", + Issuer: "step-cli", + NotBefore: jwt.NewNumericDate(now), + Expiry: jwt.NewNumericDate(now.Add(time.Minute)), + Audience: validAud, + ID: jti, + }, + SANS: []string{"invalid"}, } raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() assert.FatalError(t, err) @@ -181,13 +187,19 @@ ZEp7knvU2psWRw== "ok": func(t *testing.T) *signTest { jti, err := randutil.ASCII(32) assert.FatalError(t, err) - cl := jwt.Claims{ - Subject: "test.smallstep.com", - Issuer: "step-cli", - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: validAud, - ID: jti, + cl := struct { + jwt.Claims + SANS []string `json:"sans"` + }{ + Claims: jwt.Claims{ + Subject: "test.smallstep.com", + Issuer: "step-cli", + NotBefore: jwt.NewNumericDate(now), + Expiry: jwt.NewNumericDate(now.Add(time.Minute)), + Audience: validAud, + ID: jti, + }, + SANS: []string{"test.smallstep.com"}, } raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() assert.FatalError(t, err) diff --git a/ca/tls_test.go b/ca/tls_test.go index 6c6a5291..c71e839d 100644 --- a/ca/tls_test.go +++ b/ca/tls_test.go @@ -39,13 +39,19 @@ func generateOTT(subject string) string { if err != nil { panic(err) } - cl := jwt.Claims{ - ID: id, - Subject: subject, - Issuer: "mariano", - NotBefore: jwt.NewNumericDate(now), - Expiry: jwt.NewNumericDate(now.Add(time.Minute)), - Audience: []string{"https://127.0.0.1:0/sign"}, + cl := struct { + jwt.Claims + SANS []string `json:"sans"` + }{ + Claims: jwt.Claims{ + ID: id, + Subject: subject, + Issuer: "mariano", + NotBefore: jwt.NewNumericDate(now), + Expiry: jwt.NewNumericDate(now.Add(time.Minute)), + Audience: []string{"https://127.0.0.1:0/sign"}, + }, + SANS: []string{subject}, } raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() if err != nil {