2024-02-08 14:03:46 +00:00
package api
import (
"bytes"
"context"
"encoding/pem"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/go-chi/chi/v5"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/errs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_CRL ( t * testing . T ) {
data := [ ] byte { 1 , 2 , 3 , 4 }
pemData := pem . EncodeToMemory ( & pem . Block {
Type : "X509 CRL" ,
Bytes : data ,
} )
pemData = bytes . TrimSpace ( pemData )
emptyPEMData := pem . EncodeToMemory ( & pem . Block {
Type : "X509 CRL" ,
Bytes : nil ,
} )
emptyPEMData = bytes . TrimSpace ( emptyPEMData )
tests := [ ] struct {
name string
url string
err error
statusCode int
crlInfo * authority . CertificateRevocationListInfo
expectedBody [ ] byte
expectedHeaders http . Header
expectedErrorJSON string
} {
{ "ok" , "http://example.com/crl" , nil , http . StatusOK , & authority . CertificateRevocationListInfo { Data : data } , data , http . Header { "Content-Type" : [ ] string { "application/pkix-crl" } , "Content-Disposition" : [ ] string { ` attachment; filename="crl.der" ` } } , "" } ,
{ "ok/pem" , "http://example.com/crl?pem=true" , nil , http . StatusOK , & authority . CertificateRevocationListInfo { Data : data } , pemData , http . Header { "Content-Type" : [ ] string { "application/x-pem-file" } , "Content-Disposition" : [ ] string { ` attachment; filename="crl.pem" ` } } , "" } ,
{ "ok/empty" , "http://example.com/crl" , nil , http . StatusOK , & authority . CertificateRevocationListInfo { Data : nil } , nil , http . Header { "Content-Type" : [ ] string { "application/pkix-crl" } , "Content-Disposition" : [ ] string { ` attachment; filename="crl.der" ` } } , "" } ,
{ "ok/empty-pem" , "http://example.com/crl?pem=true" , nil , http . StatusOK , & authority . CertificateRevocationListInfo { Data : nil } , emptyPEMData , http . Header { "Content-Type" : [ ] string { "application/x-pem-file" } , "Content-Disposition" : [ ] string { ` attachment; filename="crl.pem" ` } } , "" } ,
{ "fail/internal" , "http://example.com/crl" , errs . Wrap ( http . StatusInternalServerError , errors . New ( "failure" ) , "authority.GetCertificateRevocationList" ) , http . StatusInternalServerError , nil , nil , http . Header { } , ` { "status":500,"message":"The certificate authority encountered an Internal Server Error. Please see the certificate authority logs for more info."} ` } ,
2024-02-14 09:49:18 +00:00
{ "fail/nil" , "http://example.com/crl" , nil , http . StatusNotFound , nil , nil , http . Header { } , ` { "status":404,"message":"no CRL available"} ` } ,
2024-02-08 14:03:46 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
mockMustAuthority ( t , & mockAuthority { ret1 : tt . crlInfo , err : tt . err } )
chiCtx := chi . NewRouteContext ( )
req := httptest . NewRequest ( "GET" , tt . url , http . NoBody )
req = req . WithContext ( context . WithValue ( context . Background ( ) , chi . RouteCtxKey , chiCtx ) )
w := httptest . NewRecorder ( )
CRL ( w , req )
res := w . Result ( )
assert . Equal ( t , tt . statusCode , res . StatusCode )
body , err := io . ReadAll ( res . Body )
res . Body . Close ( )
require . NoError ( t , err )
if tt . statusCode >= 300 {
assert . JSONEq ( t , tt . expectedErrorJSON , string ( bytes . TrimSpace ( body ) ) )
return
}
// check expected header values
for _ , h := range [ ] string { "content-type" , "content-disposition" } {
v := tt . expectedHeaders . Get ( h )
require . NotEmpty ( t , v )
actual := res . Header . Get ( h )
assert . Equal ( t , v , actual )
}
// check expires header value
assert . NotEmpty ( t , res . Header . Get ( "expires" ) )
t1 , err := time . Parse ( time . RFC1123 , res . Header . Get ( "expires" ) )
if assert . NoError ( t , err ) {
assert . False ( t , t1 . IsZero ( ) )
}
// check body contents
assert . Equal ( t , tt . expectedBody , bytes . TrimSpace ( body ) )
} )
}
}