mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
243 lines
6.2 KiB
Go
243 lines
6.2 KiB
Go
package ocsp
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cloudflare/cfssl/api"
|
|
"github.com/cloudflare/cfssl/ocsp"
|
|
goocsp "golang.org/x/crypto/ocsp"
|
|
|
|
"github.com/cloudflare/cfssl/helpers"
|
|
)
|
|
|
|
const (
|
|
testCaFile = "../../ocsp/testdata/ca.pem"
|
|
testRespCertFile = "../../ocsp/testdata/server.crt"
|
|
testKeyFile = "../../ocsp/testdata/server.key"
|
|
testCertFile = "../../ocsp/testdata/cert.pem"
|
|
)
|
|
|
|
func newTestHandler(t *testing.T) http.Handler {
|
|
// arbitrary duration
|
|
dur, _ := time.ParseDuration("1ms")
|
|
s, err := ocsp.NewSignerFromFile(testCaFile, testRespCertFile, testKeyFile, dur)
|
|
if err != nil {
|
|
t.Fatalf("Signer creation failed %v", err)
|
|
}
|
|
return NewHandler(s)
|
|
}
|
|
|
|
func TestNewHandler(t *testing.T) {
|
|
newTestHandler(t)
|
|
}
|
|
|
|
func newSignServer(t *testing.T) *httptest.Server {
|
|
ts := httptest.NewServer(newTestHandler(t))
|
|
return ts
|
|
}
|
|
|
|
func testSignFile(t *testing.T, certFile, status string, reason int, revokedAt string, hash string) (resp *http.Response, body []byte) {
|
|
ts := newSignServer(t)
|
|
defer ts.Close()
|
|
|
|
obj := map[string]interface{}{}
|
|
if certFile != "" {
|
|
c, err := ioutil.ReadFile(certFile)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
obj["certificate"] = string(c)
|
|
}
|
|
if status != "" {
|
|
obj["status"] = status
|
|
}
|
|
obj["reason"] = reason
|
|
if revokedAt != "" {
|
|
obj["revoked_at"] = revokedAt
|
|
}
|
|
obj["issuer_hash"] = hash
|
|
|
|
blob, err := json.Marshal(obj)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
resp, err = http.Post(ts.URL, "application/json", bytes.NewReader(blob))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
body, err = ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
type signTest struct {
|
|
CertificateFile string
|
|
Status string
|
|
Reason int
|
|
RevokedAt string
|
|
ExpectedHTTPStatus int
|
|
ExpectedSuccess bool
|
|
ExpectedErrorCode int
|
|
IssuerHash string
|
|
}
|
|
|
|
var signTests = []signTest{
|
|
{
|
|
CertificateFile: testCertFile,
|
|
ExpectedHTTPStatus: http.StatusOK,
|
|
ExpectedSuccess: true,
|
|
ExpectedErrorCode: 0,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
Status: "revoked",
|
|
Reason: 1,
|
|
ExpectedHTTPStatus: http.StatusOK,
|
|
ExpectedSuccess: true,
|
|
ExpectedErrorCode: 0,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
Status: "revoked",
|
|
RevokedAt: "now",
|
|
ExpectedHTTPStatus: http.StatusOK,
|
|
ExpectedSuccess: true,
|
|
ExpectedErrorCode: 0,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
Status: "revoked",
|
|
RevokedAt: "2015-08-15",
|
|
ExpectedHTTPStatus: http.StatusOK,
|
|
ExpectedSuccess: true,
|
|
ExpectedErrorCode: 0,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
Status: "revoked",
|
|
RevokedAt: "a",
|
|
ExpectedHTTPStatus: http.StatusBadRequest,
|
|
ExpectedSuccess: false,
|
|
ExpectedErrorCode: http.StatusBadRequest,
|
|
},
|
|
{
|
|
CertificateFile: "",
|
|
Status: "",
|
|
ExpectedHTTPStatus: http.StatusBadRequest,
|
|
ExpectedSuccess: false,
|
|
ExpectedErrorCode: http.StatusBadRequest,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
Status: "_",
|
|
ExpectedHTTPStatus: http.StatusBadRequest,
|
|
ExpectedSuccess: false,
|
|
ExpectedErrorCode: 8200,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
IssuerHash: "SHA256",
|
|
ExpectedHTTPStatus: http.StatusOK,
|
|
ExpectedSuccess: true,
|
|
ExpectedErrorCode: 0,
|
|
},
|
|
{
|
|
CertificateFile: testCertFile,
|
|
IssuerHash: "MD4",
|
|
ExpectedHTTPStatus: http.StatusBadRequest,
|
|
ExpectedSuccess: false,
|
|
ExpectedErrorCode: http.StatusBadRequest,
|
|
},
|
|
}
|
|
|
|
func TestSign(t *testing.T) {
|
|
for i, test := range signTests {
|
|
resp, body := testSignFile(t, test.CertificateFile, test.Status, test.Reason, test.RevokedAt, test.IssuerHash)
|
|
if resp.StatusCode != test.ExpectedHTTPStatus {
|
|
t.Logf("Test %d: expected: %d, have %d", i, test.ExpectedHTTPStatus, resp.StatusCode)
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
|
|
}
|
|
|
|
message := new(api.Response)
|
|
err := json.Unmarshal(body, message)
|
|
if err != nil {
|
|
t.Logf("failed to read response body: %v", err)
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
|
|
}
|
|
|
|
if test.ExpectedSuccess != message.Success {
|
|
t.Logf("Test %d: expected: %v, have %v", i, test.ExpectedSuccess, message.Success)
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
|
|
}
|
|
if !test.ExpectedSuccess {
|
|
if test.ExpectedErrorCode != message.Errors[0].Code {
|
|
t.Fatalf("Test %d: expected: %v, have %v", i, test.ExpectedErrorCode, message.Errors[0].Code)
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
|
|
}
|
|
continue
|
|
}
|
|
|
|
result, ok := message.Result.(map[string]interface{})
|
|
if !ok {
|
|
t.Logf("failed to read result")
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
|
|
}
|
|
b64Resp, ok := result["ocspResponse"].(string)
|
|
if !ok {
|
|
t.Logf("failed to find ocspResponse")
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
|
|
}
|
|
|
|
der, err := base64.StdEncoding.DecodeString(b64Resp)
|
|
if err != nil {
|
|
t.Logf("failed to decode base64")
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, b64Resp)
|
|
}
|
|
|
|
ocspResp, err := goocsp.ParseResponse(der, nil)
|
|
if err != nil {
|
|
t.Logf("failed to parse ocsp response: %v", err)
|
|
t.Fatal(resp.Status, test.ExpectedHTTPStatus, b64Resp)
|
|
}
|
|
|
|
//should default to good
|
|
if test.Status == "" {
|
|
test.Status = "good"
|
|
}
|
|
intStatus := ocsp.StatusCode[test.Status]
|
|
if ocspResp.Status != intStatus {
|
|
t.Fatalf("Test %d incorrect status: expected: %v, have %v", i, intStatus, ocspResp.Status)
|
|
t.Fatal(ocspResp.Status, intStatus, ocspResp)
|
|
}
|
|
|
|
if test.Status == "revoked" {
|
|
if ocspResp.RevocationReason != test.Reason {
|
|
t.Fatalf("Test %d incorrect reason: expected: %v, have %v", i, test.Reason, ocspResp.RevocationReason)
|
|
t.Fatal(ocspResp.RevocationReason, test.Reason, ocspResp)
|
|
}
|
|
|
|
var r time.Time
|
|
if test.RevokedAt == "" || test.RevokedAt == "now" {
|
|
r = time.Now().UTC().Truncate(helpers.OneDay)
|
|
} else {
|
|
r, _ = time.Parse("2006-01-02", test.RevokedAt)
|
|
}
|
|
|
|
if !ocspResp.RevokedAt.Truncate(helpers.OneDay).Equal(r) {
|
|
t.Fatalf("Test %d incorrect revokedAt: expected: %v, have %v", i, r, ocspResp.RevokedAt)
|
|
t.Fatal(ocspResp.RevokedAt, test.RevokedAt, ocspResp)
|
|
}
|
|
}
|
|
}
|
|
}
|