Skip to content

Commit

Permalink
fix(test): test cases with example.com URL (#238)
Browse files Browse the repository at this point in the history
Fix:
- added mocked HTTP client for a test case of revocation package
- replaced `*.com` with `*.test` to avoid mentioning a real domain in
testing URL

NOTE: `.test` is a reserved domain for testing in RFC 2606

---------

Signed-off-by: Junjie Gao <[email protected]>
  • Loading branch information
JeyJeyGao authored Nov 5, 2024
1 parent 3067ab1 commit 4819e1d
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 51 deletions.
20 changes: 10 additions & 10 deletions revocation/crl/fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func TestFetch(t *testing.T) {
if err != nil {
t.Fatalf("failed to parse base CRL: %v", err)
}
const exampleURL = "http://example.com"
const uncachedURL = "http://uncached.com"
const exampleURL = "http://localhost.test"
const uncachedURL = "http://uncached.test"

bundle := &Bundle{
BaseCRL: baseCRL,
Expand Down Expand Up @@ -167,7 +167,7 @@ func TestFetch(t *testing.T) {
t.Fatalf("failed to parse base CRL: %v", err)
}
// store the expired CRL
const expiredCRLURL = "http://example.com/expired"
const expiredCRLURL = "http://localhost.test/expired"
bundle := &Bundle{
BaseCRL: expiredCRL,
}
Expand Down Expand Up @@ -299,22 +299,22 @@ func TestDownload(t *testing.T) {
}
})
t.Run("https download", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "https://example.com", http.DefaultClient)
_, err := fetchCRL(context.Background(), "https://localhost.test", http.DefaultClient)
if err == nil {
t.Fatal("expected error")
}
})

t.Run("http.NewRequestWithContext error", func(t *testing.T) {
var ctx context.Context = nil
_, err := fetchCRL(ctx, "http://example.com", &http.Client{})
_, err := fetchCRL(ctx, "http://localhost.test", &http.Client{})
if err == nil {
t.Fatal("expected error")
}
})

t.Run("client.Do error", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "http://example.com", &http.Client{
_, err := fetchCRL(context.Background(), "http://localhost.test", &http.Client{
Transport: errorRoundTripperMock{},
})

Expand All @@ -324,7 +324,7 @@ func TestDownload(t *testing.T) {
})

t.Run("status code is not 2xx", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "http://example.com", &http.Client{
_, err := fetchCRL(context.Background(), "http://localhost.test", &http.Client{
Transport: serverErrorRoundTripperMock{},
})
if err == nil {
Expand All @@ -333,7 +333,7 @@ func TestDownload(t *testing.T) {
})

t.Run("readAll error", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "http://example.com", &http.Client{
_, err := fetchCRL(context.Background(), "http://localhost.test", &http.Client{
Transport: readFailedRoundTripperMock{},
})
if err == nil {
Expand All @@ -342,7 +342,7 @@ func TestDownload(t *testing.T) {
})

t.Run("exceed the size limit", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "http://example.com", &http.Client{
_, err := fetchCRL(context.Background(), "http://localhost.test", &http.Client{
Transport: expectedRoundTripperMock{Body: make([]byte, maxCRLSize+1)},
})
if err == nil {
Expand All @@ -351,7 +351,7 @@ func TestDownload(t *testing.T) {
})

t.Run("invalid crl", func(t *testing.T) {
_, err := fetchCRL(context.Background(), "http://example.com", &http.Client{
_, err := fetchCRL(context.Background(), "http://localhost.test", &http.Client{
Transport: expectedRoundTripperMock{Body: []byte("invalid crl")},
})
if err == nil {
Expand Down
16 changes: 8 additions & 8 deletions revocation/internal/crl/crl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestCertCheckStatus(t *testing.T) {

t.Run("fetcher is nil", func(t *testing.T) {
cert := &x509.Certificate{
CRLDistributionPoints: []string{"http://example.com"},
CRLDistributionPoints: []string{"http://localhost.test"},
}
r := CertCheckStatus(context.Background(), cert, &x509.Certificate{}, CertCheckStatusOptions{})
if r.ServerResults[0].Error.Error() != "CRL fetcher cannot be nil" {
Expand All @@ -57,7 +57,7 @@ func TestCertCheckStatus(t *testing.T) {
memoryCache := &memoryCache{}

cert := &x509.Certificate{
CRLDistributionPoints: []string{"http://example.com"},
CRLDistributionPoints: []string{"http://localhost.test"},
}
fetcher, err := crlutils.NewHTTPFetcher(
&http.Client{Transport: errorRoundTripperMock{}},
Expand All @@ -80,7 +80,7 @@ func TestCertCheckStatus(t *testing.T) {
memoryCache := &memoryCache{}

cert := &x509.Certificate{
CRLDistributionPoints: []string{"http://example.com"},
CRLDistributionPoints: []string{"http://localhost.test"},
}
fetcher, err := crlutils.NewHTTPFetcher(
&http.Client{Transport: expiredCRLRoundTripperMock{}},
Expand Down Expand Up @@ -253,11 +253,11 @@ func TestCertCheckStatus(t *testing.T) {
BaseCRL: base,
}

chain[0].Cert.CRLDistributionPoints = []string{"http://example.com"}
chain[0].Cert.CRLDistributionPoints = []string{"http://localhost.test"}

t.Run("invalid stale CRL cache, and re-download failed", func(t *testing.T) {
// save to cache
if err := memoryCache.Set(context.Background(), "http://example.com", bundle); err != nil {
if err := memoryCache.Set(context.Background(), "http://localhost.test", bundle); err != nil {
t.Fatal(err)
}

Expand All @@ -279,7 +279,7 @@ func TestCertCheckStatus(t *testing.T) {

t.Run("invalid stale CRL cache, re-download and still validate failed", func(t *testing.T) {
// save to cache
if err := memoryCache.Set(context.Background(), "http://example.com", bundle); err != nil {
if err := memoryCache.Set(context.Background(), "http://localhost.test", bundle); err != nil {
t.Fatal(err)
}

Expand All @@ -301,7 +301,7 @@ func TestCertCheckStatus(t *testing.T) {

t.Run("invalid stale CRL cache, re-download and validate seccessfully", func(t *testing.T) {
// save to cache
if err := memoryCache.Set(context.Background(), "http://example.com", bundle); err != nil {
if err := memoryCache.Set(context.Background(), "http://localhost.test", bundle); err != nil {
t.Fatal(err)
}

Expand Down Expand Up @@ -722,7 +722,7 @@ func marshalGeneralizedTimeToBytes(t time.Time) ([]byte, error) {
func TestSupported(t *testing.T) {
t.Run("supported", func(t *testing.T) {
cert := &x509.Certificate{
CRLDistributionPoints: []string{"http://example.com"},
CRLDistributionPoints: []string{"http://localhost.test"},
}
if !Supported(cert) {
t.Fatal("expected supported")
Expand Down
16 changes: 8 additions & 8 deletions revocation/internal/ocsp/ocsp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func TestCheckStatusFromServer(t *testing.T) {
ctx := context.Background()

t.Run("server url is not http", func(t *testing.T) {
server := "https://example.com"
server := "https://localhost.test"
serverResult := checkStatusFromServer(ctx, revokableCertTuple.Cert, revokableIssuerTuple.Cert, server, CertCheckStatusOptions{})
expectedResult := toServerResult(server, GenericError{Err: fmt.Errorf("OCSPServer protocol %s is not supported", "https")})
if serverResult.Result != expectedResult.Result {
Expand All @@ -169,7 +169,7 @@ func TestCheckStatusFromServer(t *testing.T) {
})

t.Run("request error", func(t *testing.T) {
server := "http://example.com"
server := "http://localhost.test"
serverResult := checkStatusFromServer(ctx, revokableCertTuple.Cert, revokableIssuerTuple.Cert, server, CertCheckStatusOptions{
HTTPClient: &http.Client{
Transport: &failedTransport{},
Expand All @@ -183,7 +183,7 @@ func TestCheckStatusFromServer(t *testing.T) {

t.Run("ocsp expired", func(t *testing.T) {
client := testhelper.MockClient([]testhelper.RSACertTuple{revokableCertTuple, revokableIssuerTuple}, []ocsp.ResponseStatus{ocsp.Good}, nil, true)
server := "http://example.com/expired_ocsp"
server := "http://localhost.test/expired_ocsp"
serverResult := checkStatusFromServer(ctx, revokableCertTuple.Cert, revokableIssuerTuple.Cert, server, CertCheckStatusOptions{
HTTPClient: client,
})
Expand All @@ -195,7 +195,7 @@ func TestCheckStatusFromServer(t *testing.T) {

t.Run("ocsp request roundtrip failed", func(t *testing.T) {
client := testhelper.MockClient([]testhelper.RSACertTuple{revokableCertTuple, revokableIssuerTuple}, []ocsp.ResponseStatus{ocsp.Good}, nil, true)
server := "http://example.com"
server := "http://localhost.test"
serverResult := checkStatusFromServer(nil, revokableCertTuple.Cert, revokableIssuerTuple.Cert, server, CertCheckStatusOptions{
HTTPClient: client,
})
Expand All @@ -206,7 +206,7 @@ func TestCheckStatusFromServer(t *testing.T) {
})

t.Run("ocsp request roundtrip timeout", func(t *testing.T) {
server := "http://example.com"
server := "http://localhost.test"
serverResult := checkStatusFromServer(ctx, revokableCertTuple.Cert, revokableIssuerTuple.Cert, server, CertCheckStatusOptions{
HTTPClient: &http.Client{
Timeout: 1 * time.Second,
Expand All @@ -224,7 +224,7 @@ func TestCheckStatusFromServer(t *testing.T) {

func TestPostRequest(t *testing.T) {
t.Run("failed to generate request", func(t *testing.T) {
_, err := postRequest(nil, nil, "http://example.com", &http.Client{
_, err := postRequest(nil, nil, "http://localhost.test", &http.Client{
Transport: &failedTransport{},
})
expectedErrMsg := "net/http: nil Context"
Expand All @@ -234,10 +234,10 @@ func TestPostRequest(t *testing.T) {
})

t.Run("failed to execute request", func(t *testing.T) {
_, err := postRequest(context.Background(), nil, "http://example.com", &http.Client{
_, err := postRequest(context.Background(), nil, "http://localhost.test", &http.Client{
Transport: &failedTransport{},
})
expectedErrMsg := "Post \"http://example.com\": failed to execute request"
expectedErrMsg := "Post \"http://localhost.test\": failed to execute request"
if err == nil || err.Error() != expectedErrMsg {
t.Errorf("Expected error %s, but got %s", expectedErrMsg, err)
}
Expand Down
8 changes: 4 additions & 4 deletions revocation/ocsp/ocsp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,13 +410,13 @@ func TestCheckStatusErrors(t *testing.T) {
expiredLeaf, _ := x509.ParseCertificate(revokableTuples[0].Cert.Raw)
expiredLeaf.IsCA = false
expiredLeaf.KeyUsage = x509.KeyUsageDigitalSignature
expiredLeaf.OCSPServer = []string{"http://example.com/expired_ocsp"}
expiredLeaf.OCSPServer = []string{"http://localhost.test/expired_ocsp"}
expiredChain := []*x509.Certificate{expiredLeaf, revokableTuples[1].Cert, revokableTuples[2].Cert}

noHTTPLeaf, _ := x509.ParseCertificate(revokableTuples[0].Cert.Raw)
noHTTPLeaf.IsCA = false
noHTTPLeaf.KeyUsage = x509.KeyUsageDigitalSignature
noHTTPLeaf.OCSPServer = []string{"ldap://ds.example.com:123/chain_ocsp/0"}
noHTTPLeaf.OCSPServer = []string{"ldap://ds.localhost.test:123/chain_ocsp/0"}
noHTTPChain := []*x509.Certificate{noHTTPLeaf, revokableTuples[1].Cert, revokableTuples[2].Cert}

timestampSigningCertErr := result.InvalidChainError{Err: errors.New("timestamp signing certificate with subject \"CN=Notation Test Revokable RSA Chain Cert 3,O=Notary,L=Seattle,ST=WA,C=US\" must have and only have Timestamping as extended key usage")}
Expand Down Expand Up @@ -633,15 +633,15 @@ func TestCheckOCSPInvalidChain(t *testing.T) {
for i, cert := range misorderedIntermediateChain {
if i != (len(misorderedIntermediateChain) - 1) {
// Skip root which won't have an OCSP Server
cert.OCSPServer[0] = fmt.Sprintf("http://example.com/chain_ocsp/%d", i)
cert.OCSPServer[0] = fmt.Sprintf("http://localhost.test/chain_ocsp/%d", i)
}
}

missingIntermediateChain := []*x509.Certificate{revokableTuples[0].Cert, revokableTuples[2].Cert, revokableTuples[3].Cert}
for i, cert := range missingIntermediateChain {
if i != (len(missingIntermediateChain) - 1) {
// Skip root which won't have an OCSP Server
cert.OCSPServer[0] = fmt.Sprintf("http://example.com/chain_ocsp/%d", i)
cert.OCSPServer[0] = fmt.Sprintf("http://localhost.test/chain_ocsp/%d", i)
}
}

Expand Down
43 changes: 27 additions & 16 deletions revocation/revocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -823,13 +823,13 @@ func TestCheckRevocationErrors(t *testing.T) {
expiredLeaf, _ := x509.ParseCertificate(revokableTuples[0].Cert.Raw)
expiredLeaf.IsCA = false
expiredLeaf.KeyUsage = x509.KeyUsageDigitalSignature
expiredLeaf.OCSPServer = []string{"http://example.com/expired_ocsp"}
expiredLeaf.OCSPServer = []string{"http://localhost.test/expired_ocsp"}
expiredChain := []*x509.Certificate{expiredLeaf, revokableTuples[1].Cert, revokableTuples[2].Cert}

noHTTPLeaf, _ := x509.ParseCertificate(revokableTuples[0].Cert.Raw)
noHTTPLeaf.IsCA = false
noHTTPLeaf.KeyUsage = x509.KeyUsageDigitalSignature
noHTTPLeaf.OCSPServer = []string{"ldap://ds.example.com:123/chain_ocsp/0"}
noHTTPLeaf.OCSPServer = []string{"ldap://ds.localhost.test:123/chain_ocsp/0"}
noHTTPChain := []*x509.Certificate{noHTTPLeaf, revokableTuples[1].Cert, revokableTuples[2].Cert}

backwardsChainErr := result.InvalidChainError{Err: errors.New("leaf certificate with subject \"CN=Notation Test Revokable RSA Chain Cert Root,O=Notary,L=Seattle,ST=WA,C=US\" is self-signed. Certificate chain must not contain self-signed leaf certificate")}
Expand Down Expand Up @@ -984,15 +984,15 @@ func TestCheckRevocationInvalidChain(t *testing.T) {
for i, cert := range misorderedIntermediateChain {
if i != (len(misorderedIntermediateChain) - 1) {
// Skip root which won't have an OCSP Server
cert.OCSPServer[0] = fmt.Sprintf("http://example.com/chain_ocsp/%d", i)
cert.OCSPServer[0] = fmt.Sprintf("http://localhost.test/chain_ocsp/%d", i)
}
}

missingIntermediateChain := []*x509.Certificate{revokableTuples[0].Cert, revokableTuples[2].Cert, revokableTuples[3].Cert}
for i, cert := range missingIntermediateChain {
if i != (len(missingIntermediateChain) - 1) {
// Skip root which won't have an OCSP Server
cert.OCSPServer[0] = fmt.Sprintf("http://example.com/chain_ocsp/%d", i)
cert.OCSPServer[0] = fmt.Sprintf("http://localhost.test/chain_ocsp/%d", i)
}
}

Expand Down Expand Up @@ -1069,15 +1069,15 @@ func TestCRL(t *testing.T) {
Result: result.ResultOK,
ServerResults: []*result.ServerResult{{
Result: result.ResultOK,
Server: "http://example.com/chain_crl/0",
Server: "http://localhost.test/chain_crl/0",
}},
RevocationMethod: result.RevocationMethodCRL,
},
{
Result: result.ResultOK,
ServerResults: []*result.ServerResult{{
Result: result.ResultOK,
Server: "http://example.com/chain_crl/1",
Server: "http://localhost.test/chain_crl/1",
}},
RevocationMethod: result.RevocationMethodCRL,
},
Expand Down Expand Up @@ -1128,7 +1128,7 @@ func TestCRL(t *testing.T) {
ServerResults: []*result.ServerResult{
{
Result: result.ResultRevoked,
Server: "http://example.com/chain_crl/0",
Server: "http://localhost.test/chain_crl/0",
},
},
RevocationMethod: result.RevocationMethodCRL,
Expand All @@ -1138,7 +1138,7 @@ func TestCRL(t *testing.T) {
ServerResults: []*result.ServerResult{
{
Result: result.ResultRevoked,
Server: "http://example.com/chain_crl/1",
Server: "http://localhost.test/chain_crl/1",
},
},
RevocationMethod: result.RevocationMethodCRL,
Expand All @@ -1164,7 +1164,9 @@ func TestCRL(t *testing.T) {
}

revocationClient, err := NewWithOptions(Options{
OCSPHTTPClient: &http.Client{},
OCSPHTTPClient: &http.Client{
Transport: &serverErrorTransport{},
},
CRLFetcher: fetcher,
CertChainPurpose: purpose.CodeSigning,
})
Expand All @@ -1190,13 +1192,13 @@ func TestCRL(t *testing.T) {
ServerResults: []*result.ServerResult{
{
Result: result.ResultUnknown,
Server: "http://example.com/chain_ocsp/0",
Server: "http://localhost.test/chain_ocsp/0",
Error: errors.New("failed to retrieve OCSP: response had status code 500"),
RevocationMethod: result.RevocationMethodOCSP,
},
{
Result: result.ResultRevoked,
Server: "http://example.com/chain_crl/0",
Server: "http://localhost.test/chain_crl/0",
RevocationMethod: result.RevocationMethodCRL,
},
},
Expand All @@ -1207,13 +1209,13 @@ func TestCRL(t *testing.T) {
ServerResults: []*result.ServerResult{
{
Result: result.ResultUnknown,
Server: "http://example.com/chain_ocsp/1",
Server: "http://localhost.test/chain_ocsp/1",
Error: errors.New("failed to retrieve OCSP: response had status code 500"),
RevocationMethod: result.RevocationMethodOCSPFallbackCRL,
},
{
Result: result.ResultRevoked,
Server: "http://example.com/chain_crl/1",
Server: "http://localhost.test/chain_crl/1",
RevocationMethod: result.RevocationMethodCRL,
},
},
Expand Down Expand Up @@ -1298,8 +1300,8 @@ type crlRoundTripper struct {
}

func (rt *crlRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
// e.g. ocsp URL: http://example.com/chain_ocsp/0
// e.g. crl URL: http://example.com/chain_crl/0
// e.g. ocsp URL: http://localhost.test/chain_ocsp/0
// e.g. crl URL: http://localhost.test/chain_crl/0
parts := strings.Split(req.URL.Path, "/")

isOCSP := parts[len(parts)-2] == "chain_ocsp"
Expand All @@ -1309,7 +1311,7 @@ func (rt *crlRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
}

// choose the cert suffix based on suffix of request url
// e.g. http://example.com/chain_crl/0 -> 0
// e.g. http://localhost.test/chain_crl/0 -> 0
i, err := strconv.Atoi(parts[len(parts)-1])
if err != nil {
return nil, err
Expand Down Expand Up @@ -1352,6 +1354,15 @@ func (t panicTransport) RoundTrip(req *http.Request) (*http.Response, error) {
panic("panic")
}

type serverErrorTransport struct{}

func (t serverErrorTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusInternalServerError,
Body: io.NopCloser(bytes.NewReader([]byte{})),
}, nil
}

func TestValidateContext(t *testing.T) {
r, err := NewWithOptions(Options{
OCSPHTTPClient: &http.Client{},
Expand Down
Loading

0 comments on commit 4819e1d

Please sign in to comment.