forked from TrueCloudLab/certificates
allow multiple identical SANs in cert
This commit is contained in:
parent
f0683c2e0a
commit
e6e8443f3c
8 changed files with 95 additions and 75 deletions
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
@ -231,7 +231,7 @@
|
||||||
"utils",
|
"utils",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "a1df67d396f730ff0e7bf1916cd27ae8d5255236"
|
revision = "49d4a4c26c802e83c5ed160abdd5babab1c9b5c6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -45,7 +45,7 @@ required = [
|
||||||
name = "github.com/go-chi/chi"
|
name = "github.com/go-chi/chi"
|
||||||
|
|
||||||
[[override]]
|
[[override]]
|
||||||
branch = "master"
|
branch = "sans"
|
||||||
name = "github.com/smallstep/cli"
|
name = "github.com/smallstep/cli"
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package authority
|
package authority
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -50,17 +48,16 @@ type dnsNamesClaim struct {
|
||||||
|
|
||||||
// Valid checks that certificate request common name matches the one configured.
|
// Valid checks that certificate request common name matches the one configured.
|
||||||
func (c *dnsNamesClaim) Valid(crt *x509.Certificate) error {
|
func (c *dnsNamesClaim) Valid(crt *x509.Certificate) error {
|
||||||
sort.Strings(c.names)
|
tokMap := make(map[string]int)
|
||||||
sort.Strings(crt.DNSNames)
|
for _, e := range c.names {
|
||||||
if len(c.names) != len(crt.DNSNames) {
|
tokMap[e] = 1
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
for i := range c.names {
|
crtMap := make(map[string]int)
|
||||||
if c.names[i] != crt.DNSNames[i] {
|
for _, e := range crt.DNSNames {
|
||||||
fmt.Printf("c.names[i] = %+v, crt.DNSNames[i] = %+v\n", c.names[i], crt.DNSNames[i])
|
crtMap[e] = 1
|
||||||
return errors.Errorf("DNS names claim failed - got %s, want %s", crt.DNSNames, c.names)
|
}
|
||||||
}
|
if !reflect.DeepEqual(tokMap, crtMap) {
|
||||||
|
return errors.Errorf("DNS names claim failed - got %s, want %s", crt.DNSNames, c.names)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -71,19 +68,16 @@ type ipAddressesClaim struct {
|
||||||
|
|
||||||
// Valid checks that certificate request common name matches the one configured.
|
// Valid checks that certificate request common name matches the one configured.
|
||||||
func (c *ipAddressesClaim) Valid(crt *x509.Certificate) error {
|
func (c *ipAddressesClaim) Valid(crt *x509.Certificate) error {
|
||||||
if len(c.ips) != len(crt.IPAddresses) {
|
tokMap := make(map[string]int)
|
||||||
return errors.Errorf("IP Addresses claim failed - got %v, want %v", crt.IPAddresses, c.ips)
|
for _, e := range c.ips {
|
||||||
|
tokMap[e.String()] = 1
|
||||||
}
|
}
|
||||||
sort.Slice(c.ips, func(i, j int) bool {
|
crtMap := make(map[string]int)
|
||||||
return bytes.Compare(c.ips[i], c.ips[j]) < 0
|
for _, e := range crt.IPAddresses {
|
||||||
})
|
crtMap[e.String()] = 1
|
||||||
sort.Slice(crt.IPAddresses, func(i, j int) bool {
|
}
|
||||||
return bytes.Compare(crt.IPAddresses[i], crt.IPAddresses[j]) < 0
|
if !reflect.DeepEqual(tokMap, crtMap) {
|
||||||
})
|
return errors.Errorf("IP Addresses claim failed - got %v, want %v", crt.IPAddresses, c.ips)
|
||||||
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])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,23 +52,28 @@ func TestIPAddressesClaim_Valid(t *testing.T) {
|
||||||
crt *x509.Certificate
|
crt *x509.Certificate
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
"unexpected-ip": {
|
"unexpected-ip-in-crt": {
|
||||||
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"), net.ParseIP("1.1.1.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": {
|
"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")}},
|
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": {
|
"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")}},
|
crt: &x509.Certificate{IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}},
|
||||||
},
|
},
|
||||||
"ok-empty-ips": {
|
"ok-multiple-identical-ip-entries": {
|
||||||
iac: &ipAddressesClaim{name: "127.0.0.1"},
|
iac: &ipAddressesClaim{ips: []net.IP{net.ParseIP("127.0.0.1")}},
|
||||||
crt: &x509.Certificate{IPAddresses: []net.IP{}},
|
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
|
crt *x509.Certificate
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
"wrong-dns-name": {
|
"unexpected-dns-name-in-crt": {
|
||||||
dnc: &dnsNamesClaim{name: "foo"},
|
dnc: &dnsNamesClaim{names: []string{"foo"}},
|
||||||
crt: &x509.Certificate{DNSNames: []string{"foo", "bar"}},
|
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": {
|
"ok": {
|
||||||
dnc: &dnsNamesClaim{name: "foo"},
|
dnc: &dnsNamesClaim{names: []string{"foo", "bar"}},
|
||||||
crt: &x509.Certificate{DNSNames: []string{"foo"}},
|
crt: &x509.Certificate{DNSNames: []string{"bar", "foo"}},
|
||||||
},
|
},
|
||||||
"ok-empty-dnsNames": {
|
"missing-dns-name-in-crt": {
|
||||||
dnc: &dnsNamesClaim{"foo"},
|
dnc: &dnsNamesClaim{names: []string{"foo", "bar"}},
|
||||||
crt: &x509.Certificate{},
|
crt: &x509.Certificate{DNSNames: []string{"foo"}},
|
||||||
|
err: errors.New("DNS names claim failed - got [foo], want [foo bar]"),
|
||||||
},
|
},
|
||||||
"ok-multiple-identical-dns-entries": {
|
"ok-multiple-identical-dns-entries": {
|
||||||
dnc: &dnsNamesClaim{name: "foo"},
|
dnc: &dnsNamesClaim{names: []string{"foo"}},
|
||||||
crt: &x509.Certificate{DNSNames: []string{"foo", "foo", "foo"}},
|
crt: &x509.Certificate{DNSNames: []string{"foo", "foo", "foo"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,15 +197,15 @@ func (a *Authority) Renew(ocx *x509.Certificate) (*x509.Certificate, *x509.Certi
|
||||||
ExtKeyUsage: oldCert.ExtKeyUsage,
|
ExtKeyUsage: oldCert.ExtKeyUsage,
|
||||||
UnknownExtKeyUsage: oldCert.UnknownExtKeyUsage,
|
UnknownExtKeyUsage: oldCert.UnknownExtKeyUsage,
|
||||||
BasicConstraintsValid: oldCert.BasicConstraintsValid,
|
BasicConstraintsValid: oldCert.BasicConstraintsValid,
|
||||||
IsCA: oldCert.IsCA,
|
IsCA: oldCert.IsCA,
|
||||||
MaxPathLen: oldCert.MaxPathLen,
|
MaxPathLen: oldCert.MaxPathLen,
|
||||||
MaxPathLenZero: oldCert.MaxPathLenZero,
|
MaxPathLenZero: oldCert.MaxPathLenZero,
|
||||||
OCSPServer: oldCert.OCSPServer,
|
OCSPServer: oldCert.OCSPServer,
|
||||||
IssuingCertificateURL: oldCert.IssuingCertificateURL,
|
IssuingCertificateURL: oldCert.IssuingCertificateURL,
|
||||||
DNSNames: oldCert.DNSNames,
|
DNSNames: oldCert.DNSNames,
|
||||||
EmailAddresses: oldCert.EmailAddresses,
|
EmailAddresses: oldCert.EmailAddresses,
|
||||||
IPAddresses: oldCert.IPAddresses,
|
IPAddresses: oldCert.IPAddresses,
|
||||||
URIs: oldCert.URIs,
|
URIs: oldCert.URIs,
|
||||||
PermittedDNSDomainsCritical: oldCert.PermittedDNSDomainsCritical,
|
PermittedDNSDomainsCritical: oldCert.PermittedDNSDomainsCritical,
|
||||||
PermittedDNSDomains: oldCert.PermittedDNSDomains,
|
PermittedDNSDomains: oldCert.PermittedDNSDomains,
|
||||||
ExcludedDNSDomains: oldCert.ExcludedDNSDomains,
|
ExcludedDNSDomains: oldCert.ExcludedDNSDomains,
|
||||||
|
|
|
@ -94,6 +94,7 @@ func generateBootstrapToken(ca, subject, sha string) string {
|
||||||
cl := struct {
|
cl := struct {
|
||||||
SHA string `json:"sha"`
|
SHA string `json:"sha"`
|
||||||
jwt.Claims
|
jwt.Claims
|
||||||
|
SANS []string `json:"sans"`
|
||||||
}{
|
}{
|
||||||
SHA: sha,
|
SHA: sha,
|
||||||
Claims: jwt.Claims{
|
Claims: jwt.Claims{
|
||||||
|
@ -104,6 +105,7 @@ func generateBootstrapToken(ca, subject, sha string) string {
|
||||||
Expiry: jwt.NewNumericDate(now.Add(time.Minute)),
|
Expiry: jwt.NewNumericDate(now.Add(time.Minute)),
|
||||||
Audience: []string{ca + "/sign"},
|
Audience: []string{ca + "/sign"},
|
||||||
},
|
},
|
||||||
|
SANS: []string{subject},
|
||||||
}
|
}
|
||||||
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -154,13 +154,19 @@ ZEp7knvU2psWRw==
|
||||||
"fail commonname-claim": func(t *testing.T) *signTest {
|
"fail commonname-claim": func(t *testing.T) *signTest {
|
||||||
jti, err := randutil.ASCII(32)
|
jti, err := randutil.ASCII(32)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
cl := jwt.Claims{
|
cl := struct {
|
||||||
Subject: "invalid",
|
jwt.Claims
|
||||||
Issuer: "step-cli",
|
SANS []string `json:"sans"`
|
||||||
NotBefore: jwt.NewNumericDate(now),
|
}{
|
||||||
Expiry: jwt.NewNumericDate(now.Add(time.Minute)),
|
Claims: jwt.Claims{
|
||||||
Audience: validAud,
|
Subject: "invalid",
|
||||||
ID: jti,
|
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()
|
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -181,13 +187,19 @@ ZEp7knvU2psWRw==
|
||||||
"ok": func(t *testing.T) *signTest {
|
"ok": func(t *testing.T) *signTest {
|
||||||
jti, err := randutil.ASCII(32)
|
jti, err := randutil.ASCII(32)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
cl := jwt.Claims{
|
cl := struct {
|
||||||
Subject: "test.smallstep.com",
|
jwt.Claims
|
||||||
Issuer: "step-cli",
|
SANS []string `json:"sans"`
|
||||||
NotBefore: jwt.NewNumericDate(now),
|
}{
|
||||||
Expiry: jwt.NewNumericDate(now.Add(time.Minute)),
|
Claims: jwt.Claims{
|
||||||
Audience: validAud,
|
Subject: "test.smallstep.com",
|
||||||
ID: jti,
|
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()
|
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
|
|
@ -39,13 +39,19 @@ func generateOTT(subject string) string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
cl := jwt.Claims{
|
cl := struct {
|
||||||
ID: id,
|
jwt.Claims
|
||||||
Subject: subject,
|
SANS []string `json:"sans"`
|
||||||
Issuer: "mariano",
|
}{
|
||||||
NotBefore: jwt.NewNumericDate(now),
|
Claims: jwt.Claims{
|
||||||
Expiry: jwt.NewNumericDate(now.Add(time.Minute)),
|
ID: id,
|
||||||
Audience: []string{"https://127.0.0.1:0/sign"},
|
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()
|
raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Add table
Reference in a new issue