Compare commits
5 Commits
retire
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
394a3b240b | |||
f8d5ba9a3f | |||
dc26e816fd | |||
e9434c9455 | |||
16d1ef949c |
@ -264,9 +264,10 @@ func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertVali
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Duration(selfSignedCertValidity) * 365 * (24 * time.Hour)),
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign,
|
||||
ExtKeyUsage: append([]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, additionalUsages...),
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
}
|
||||
|
||||
if info.Logger != nil {
|
||||
|
@ -15,12 +15,17 @@
|
||||
package transport
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -573,3 +578,157 @@ func TestSocktOptsEmpty(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewListenerWithACRLFile tests when a revocation list is present.
|
||||
func TestNewListenerWithACRLFile(t *testing.T) {
|
||||
clientTLSInfo, err := createSelfCertEx(t, "127.0.0.1", x509.ExtKeyUsageClientAuth)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create client cert: %v", err)
|
||||
}
|
||||
|
||||
loadFileAsPEM := func(fileName string) []byte {
|
||||
loaded, readErr := os.ReadFile(fileName)
|
||||
if readErr != nil {
|
||||
t.Fatalf("unable to read file %q: %v", fileName, readErr)
|
||||
}
|
||||
block, _ := pem.Decode(loaded)
|
||||
return block.Bytes
|
||||
}
|
||||
|
||||
clientCert, err := x509.ParseCertificate(loadFileAsPEM(clientTLSInfo.CertFile))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse client cert: %v", err)
|
||||
}
|
||||
|
||||
tests := map[string]struct {
|
||||
expectHandshakeError bool
|
||||
revokedCertificateEntries []x509.RevocationListEntry
|
||||
revocationListContents []byte
|
||||
}{
|
||||
"empty revocation list": {
|
||||
expectHandshakeError: false,
|
||||
},
|
||||
"client cert is revoked": {
|
||||
expectHandshakeError: true,
|
||||
revokedCertificateEntries: []x509.RevocationListEntry{
|
||||
{
|
||||
SerialNumber: clientCert.SerialNumber,
|
||||
RevocationTime: time.Now(),
|
||||
},
|
||||
},
|
||||
},
|
||||
"invalid CRL file content": {
|
||||
expectHandshakeError: true,
|
||||
revocationListContents: []byte("@invalidcontent"),
|
||||
},
|
||||
}
|
||||
|
||||
for testName, test := range tests {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
tmpdir := t.TempDir()
|
||||
tlsInfo, err := createSelfCert(t)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create server cert: %v", err)
|
||||
}
|
||||
tlsInfo.TrustedCAFile = clientTLSInfo.CertFile
|
||||
tlsInfo.CRLFile = filepath.Join(tmpdir, "revoked.r0")
|
||||
|
||||
cert, err := x509.ParseCertificate(loadFileAsPEM(tlsInfo.CertFile))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decode server cert: %v", err)
|
||||
}
|
||||
|
||||
key, err := x509.ParseECPrivateKey(loadFileAsPEM(tlsInfo.KeyFile))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse server key: %v", err)
|
||||
}
|
||||
|
||||
revocationListContents := test.revocationListContents
|
||||
if len(revocationListContents) == 0 {
|
||||
tmpl := &x509.RevocationList{
|
||||
RevokedCertificateEntries: test.revokedCertificateEntries,
|
||||
ThisUpdate: time.Now(),
|
||||
NextUpdate: time.Now().Add(time.Hour),
|
||||
Number: big.NewInt(1),
|
||||
}
|
||||
revocationListContents, err = x509.CreateRevocationList(rand.Reader, tmpl, cert, key)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create revocation list: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.WriteFile(tlsInfo.CRLFile, revocationListContents, 0600); err != nil {
|
||||
t.Fatalf("unable to write revocation list: %v", err)
|
||||
}
|
||||
|
||||
chHandshakeFailure := make(chan error, 1)
|
||||
tlsInfo.HandshakeFailure = func(_ *tls.Conn, err error) {
|
||||
if err != nil {
|
||||
chHandshakeFailure <- err
|
||||
}
|
||||
}
|
||||
|
||||
rootCAs := x509.NewCertPool()
|
||||
rootCAs.AddCert(cert)
|
||||
|
||||
clientCert, err := tls.LoadX509KeyPair(clientTLSInfo.CertFile, clientTLSInfo.KeyFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create peer cert: %v", err)
|
||||
}
|
||||
|
||||
ln, err := NewListener("127.0.0.1:0", "https", tlsInfo)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to start listener: %v", err)
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{}
|
||||
tlsConfig.InsecureSkipVerify = false
|
||||
tlsConfig.Certificates = []tls.Certificate{clientCert}
|
||||
tlsConfig.RootCAs = rootCAs
|
||||
|
||||
tr := &http.Transport{TLSClientConfig: tlsConfig}
|
||||
cli := &http.Client{Transport: tr, Timeout: 5 * time.Second}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if _, gerr := cli.Get("https://" + ln.Addr().String()); gerr != nil {
|
||||
t.Logf("http GET failed: %v", gerr)
|
||||
}
|
||||
}()
|
||||
|
||||
chAcceptConn := make(chan net.Conn, 1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
conn, err := ln.Accept()
|
||||
if err == nil {
|
||||
chAcceptConn <- conn
|
||||
}
|
||||
}()
|
||||
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer func() {
|
||||
if !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-chHandshakeFailure:
|
||||
if !test.expectHandshakeError {
|
||||
t.Errorf("expecting no handshake error, got: %v", err)
|
||||
}
|
||||
case conn := <-chAcceptConn:
|
||||
if test.expectHandshakeError {
|
||||
t.Errorf("expecting handshake error, got nothing")
|
||||
}
|
||||
conn.Close()
|
||||
case <-timer.C:
|
||||
t.Error("timed out waiting for closed connection or handshake error")
|
||||
}
|
||||
|
||||
ln.Close()
|
||||
wg.Wait()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -172,12 +172,12 @@ func checkCRL(crlPath string, cert []*x509.Certificate) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
certList, err := x509.ParseCRL(crlBytes)
|
||||
certList, err := x509.ParseRevocationList(crlBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
revokedSerials := make(map[string]struct{})
|
||||
for _, rc := range certList.TBSCertList.RevokedCertificates {
|
||||
for _, rc := range certList.RevokedCertificateEntries {
|
||||
revokedSerials[string(rc.SerialNumber.Bytes())] = struct{}{}
|
||||
}
|
||||
for _, c := range cert {
|
||||
|
4
go.mod
4
go.mod
@ -66,10 +66,10 @@ require (
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/soheilhy/cmux v0.1.5 // indirect
|
||||
|
8
go.sum
8
go.sum
@ -108,15 +108,15 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
|
Reference in New Issue
Block a user