aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-12-02 17:05:45 +0100
committerRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-12-02 17:05:45 +0100
commit3f1489f4f4532f93f766fc849a2e3e2b65667747 (patch)
tree30adb41b1bce816cbce7c23454c89ae22ae89521
parentb540f681b4cdf740f9b8d1e584fd2b107fc1b090 (diff)
added instance and log parameter tests
-rw-r--r--handler_test.go6
-rw-r--r--instance.go45
-rw-r--r--instance_test.go178
-rw-r--r--server/main.go2
-rw-r--r--x509util/testdata/data.go5
5 files changed, 201 insertions, 35 deletions
diff --git a/handler_test.go b/handler_test.go
index 3bcc702..40fd562 100644
--- a/handler_test.go
+++ b/handler_test.go
@@ -23,6 +23,10 @@ import (
"github.com/system-transparency/stfe/x509util/testdata"
)
+var (
+ testDeadline = time.Second * 10
+)
+
type testHandler struct {
mockCtrl *gomock.Controller
client *mockclient.MockTrillianLogClient
@@ -36,7 +40,7 @@ func newTestHandler(t *testing.T, signer crypto.Signer) *testHandler {
mockCtrl: ctrl,
client: client,
instance: &Instance{
- Deadline: time.Second * 10,
+ Deadline: testDeadline,
Client: client,
LogParameters: makeTestLogParameters(t, signer),
},
diff --git a/instance.go b/instance.go
index b0a2d9e..122cb67 100644
--- a/instance.go
+++ b/instance.go
@@ -8,7 +8,6 @@ import (
"crypto/sha256"
"crypto/x509"
- "encoding/base64"
"net/http"
"github.com/google/trillian"
@@ -52,8 +51,8 @@ func (i Instance) String() string {
return fmt.Sprintf("%s Deadline(%v)\n", i.LogParameters, i.Deadline)
}
-func (p LogParameters) String() string {
- return fmt.Sprintf("LogId(%s) TreeId(%d) Prefix(%s) NumAnchors(%d)", base64.StdEncoding.EncodeToString(p.LogId), p.TreeId, p.Prefix, len(p.AnchorList))
+func (lp LogParameters) String() string {
+ return fmt.Sprintf("LogId(%s) TreeId(%d) Prefix(%s) MaxRange(%d) MaxChain(%d) NumAnchors(%d)", lp.id(), lp.TreeId, lp.Prefix, lp.MaxRange, lp.MaxChain, len(lp.AnchorList))
}
func (e Endpoint) String() string {
@@ -61,7 +60,7 @@ func (e Endpoint) String() string {
}
// NewInstance creates a new STFE instance
-func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, deadline time.Duration, mux *http.ServeMux) *Instance {
+func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, deadline time.Duration) *Instance {
return &Instance{
LogParameters: lp,
Client: client,
@@ -72,15 +71,21 @@ func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, deadline
// NewLogParameters creates new log parameters. Note that the signer is
// assumed to be an ed25519 signing key. Could be fixed at some point.
func NewLogParameters(treeId int64, prefix string, anchors []*x509.Certificate, signer crypto.Signer, maxRange, maxChain int64) (*LogParameters, error) {
- pub, err := x509.MarshalPKIXPublicKey(signer.Public())
- if err != nil {
- return nil, fmt.Errorf("failed DER encoding SubjectPublicKeyInfo: %v", err)
+ if signer == nil {
+ return nil, fmt.Errorf("need a signer but got none")
+ }
+ if len(anchors) < 1 {
+ return nil, fmt.Errorf("need at least one trust anchor")
}
if maxRange < 1 {
- return nil, fmt.Errorf("invalid max range: must be at least 1")
+ return nil, fmt.Errorf("max range must be at least one")
}
if maxChain < 1 {
- return nil, fmt.Errorf("invalid max chain: must be at least 1")
+ return nil, fmt.Errorf("max chain must be at least one")
+ }
+ pub, err := x509.MarshalPKIXPublicKey(signer.Public())
+ if err != nil {
+ return nil, fmt.Errorf("failed DER encoding SubjectPublicKeyInfo: %v", err)
}
hasher := sha256.New()
hasher.Write(pub)
@@ -98,17 +103,6 @@ func NewLogParameters(treeId int64, prefix string, anchors []*x509.Certificate,
}, nil
}
-// Path joins a number of components to form a full endpoint path, e.g., base
-// ("example.com"), prefix ("st/v1"), and the endpoint itself ("get-sth").
-func (e Endpoint) Path(components ...string) string {
- return strings.Join(append(components, string(e)), "/")
-}
-
-// TODO: id() docdoc
-func (i *LogParameters) id() string {
- return base64.StdEncoding.EncodeToString(i.LogId)
-}
-
// Handlers returns a list of STFE handlers
func (i *Instance) Handlers() []Handler {
return []Handler{
@@ -120,3 +114,14 @@ func (i *Instance) Handlers() []Handler {
Handler{instance: i, handler: getSth, endpoint: EndpointGetSth, method: http.MethodGet},
}
}
+
+// id formats the log's identifier as base64
+func (i *LogParameters) id() string {
+ return b64(i.LogId)
+}
+
+// Path joins a number of components to form a full endpoint path, e.g., base
+// ("example.com"), prefix ("st/v1"), and the endpoint itself ("get-sth").
+func (e Endpoint) Path(components ...string) string {
+ return strings.Join(append(components, string(e)), "/")
+}
diff --git a/instance_test.go b/instance_test.go
index b4b13c8..02424c6 100644
--- a/instance_test.go
+++ b/instance_test.go
@@ -1,11 +1,14 @@
package stfe
import (
+ "bytes"
"testing"
"crypto"
+ "crypto/sha256"
"crypto/x509"
+ cttestdata "github.com/google/certificate-transparency-go/trillian/testdata"
"github.com/system-transparency/stfe/x509util"
"github.com/system-transparency/stfe/x509util/testdata"
)
@@ -20,22 +23,149 @@ var (
testExtKeyUsage = []x509.ExtKeyUsage{}
)
-func makeTestLogParameters(t *testing.T, signer crypto.Signer) *LogParameters {
- anchorList, err := x509util.NewCertificateList(testdata.TrustAnchors)
+func TestNewLogParameters(t *testing.T) {
+ anchors, err := x509util.NewCertificateList(testdata.TrustAnchors)
if err != nil {
t.Fatalf("must decode trust anchors: %v", err)
}
- return &LogParameters{
- LogId: testLogId,
- TreeId: testTreeId,
- Prefix: testPrefix,
- MaxRange: testMaxRange,
- MaxChain: testMaxChain,
- AnchorPool: x509util.NewCertPool(anchorList),
- AnchorList: anchorList,
- KeyUsage: testExtKeyUsage,
- Signer: signer,
- HashType: testHashType,
+ signer, err := x509util.NewEd25519PrivateKey(testdata.LogPrivateKey)
+ if err != nil {
+ t.Fatalf("must decode private key: %v", err)
+ }
+ pub, err := x509.MarshalPKIXPublicKey(signer.Public())
+ if err != nil {
+ t.Fatalf("must encode public key: %v", err)
+ }
+ hasher := sha256.New()
+ hasher.Write(pub)
+ logId := hasher.Sum(nil)
+ for _, table := range []struct {
+ description string
+ treeId int64
+ prefix string
+ maxRange int64
+ maxChain int64
+ anchors []*x509.Certificate
+ signer crypto.Signer
+ wantErr bool
+ }{
+ {
+ description: "invalid signer: nil",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: 0,
+ maxChain: testMaxChain,
+ anchors: anchors,
+ signer: nil,
+ wantErr: true,
+ },
+ {
+ description: "no trust anchors",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: testMaxRange,
+ maxChain: testMaxChain,
+ anchors: []*x509.Certificate{},
+ signer: signer,
+ wantErr: true,
+ },
+ {
+ description: "invalid max range",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: 0,
+ maxChain: testMaxChain,
+ anchors: anchors,
+ signer: signer,
+ wantErr: true,
+ },
+ {
+ description: "invalid max chain",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: testMaxRange,
+ maxChain: 0,
+ anchors: anchors,
+ signer: signer,
+ wantErr: true,
+ },
+ {
+ description: "public key marshal failure",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: testMaxRange,
+ maxChain: testMaxChain,
+ anchors: []*x509.Certificate{},
+ signer: cttestdata.NewSignerWithFixedSig("no pub", testSignature),
+ wantErr: true,
+ },
+ {
+ description: "valid log parameters",
+ treeId: testTreeId,
+ prefix: testPrefix,
+ maxRange: testMaxRange,
+ maxChain: testMaxChain,
+ anchors: anchors,
+ signer: signer,
+ },
+ } {
+ lp, err := NewLogParameters(table.treeId, table.prefix, table.anchors, table.signer, table.maxRange, table.maxChain)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error=%v but wanted %v in test %q: %v", got, want, table.description, err)
+ }
+ if err != nil {
+ continue
+ }
+
+ if got, want := lp.LogId, logId; !bytes.Equal(got, want) {
+ t.Errorf("got log id %X but wanted %X in test %q", got, want, table.description)
+ }
+ if got, want := lp.TreeId, testTreeId; got != want {
+ t.Errorf("got tree id %d but wanted %d in test %q", got, want, table.description)
+ }
+ if got, want := lp.Prefix, testPrefix; got != want {
+ t.Errorf("got prefix %s but wanted %s in test %q", got, want, table.description)
+ }
+ if got, want := lp.MaxRange, testMaxRange; got != want {
+ t.Errorf("got max range %d but wanted %d in test %q", got, want, table.description)
+ }
+ if got, want := lp.MaxChain, testMaxChain; got != want {
+ t.Errorf("got max chain %d but wanted %d in test %q", got, want, table.description)
+ }
+ if got, want := lp.MaxChain, testMaxChain; got != want {
+ t.Errorf("got max chain %d but wanted %d in test %q", got, want, table.description)
+ }
+ if got, want := len(lp.AnchorList), len(anchors); got != want {
+ t.Errorf("got %d anchors but wanted %d in test %q", got, want, table.description)
+ }
+ if got, want := len(lp.AnchorPool.Subjects()), len(anchors); got != want {
+ t.Errorf("got %d anchors in pool but wanted %d in test %q", got, want, table.description)
+ }
+ }
+}
+
+// TestHandlers checks that we configured all endpoints and that there are no
+// unexpected ones.
+func TestHandlers(t *testing.T) {
+ endpoints := map[Endpoint]bool{
+ EndpointAddEntry: false,
+ EndpointGetEntries: false,
+ EndpointGetSth: false,
+ EndpointGetProofByHash: false,
+ EndpointGetConsistencyProof: false,
+ EndpointGetAnchors: false,
+ }
+ i := NewInstance(makeTestLogParameters(t, nil), nil, testDeadline)
+ for _, handler := range i.Handlers() {
+ if _, ok := endpoints[handler.endpoint]; !ok {
+ t.Errorf("got unexpected endpoint: %s", handler.endpoint)
+ }
+ endpoints[handler.endpoint] = true
+ }
+ for endpoint, ok := range endpoints {
+ if !ok {
+ t.Errorf("endpoint %s is not configured", endpoint)
+ }
}
}
@@ -78,3 +208,25 @@ func TestEndpointPath(t *testing.T) {
}
}
}
+
+// makeTestLogParameters makes a collection of test log parameters that
+// correspond to testLogId, testTreeId, testPrefix, testMaxRange, testMaxChain,
+// the anchors in testdata.TrustAnchors, testHashType, and an optional signer.
+func makeTestLogParameters(t *testing.T, signer crypto.Signer) *LogParameters {
+ anchors, err := x509util.NewCertificateList(testdata.TrustAnchors)
+ if err != nil {
+ t.Fatalf("must decode trust anchors: %v", err)
+ }
+ return &LogParameters{
+ LogId: testLogId,
+ TreeId: testTreeId,
+ Prefix: testPrefix,
+ MaxRange: testMaxRange,
+ MaxChain: testMaxChain,
+ AnchorPool: x509util.NewCertPool(anchors),
+ AnchorList: anchors,
+ KeyUsage: testExtKeyUsage,
+ Signer: signer,
+ HashType: testHashType,
+ }
+}
diff --git a/server/main.go b/server/main.go
index c60f95d..a82faa2 100644
--- a/server/main.go
+++ b/server/main.go
@@ -69,7 +69,7 @@ func main() {
glog.Fatalf("failed setting up log parameters: %v", err)
}
- i := stfe.NewInstance(lp, client, *rpcDeadline, mux)
+ i := stfe.NewInstance(lp, client, *rpcDeadline)
for _, handler := range i.Handlers() {
glog.Infof("adding handler: %s", handler.Path())
mux.Handle(handler.Path(), handler)
diff --git a/x509util/testdata/data.go b/x509util/testdata/data.go
index 832a3aa..6438ecc 100644
--- a/x509util/testdata/data.go
+++ b/x509util/testdata/data.go
@@ -164,6 +164,11 @@ MC4CAQAwBQYDK2VwBCIEIKQd3B84w9pB6zJLGljuDyGKfz9uPP6QBeLiFcw0EME4
// NumTrustAnchors is the number of test trust anchors
NumTrustAnchors = 2
+ // LogPrivateKey is an Ed25519 signing key
+ LogPrivateKey = []byte(`-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIAhqlhKgY/TiEyTIe5BcZKLELGa2kODtJ3S+oMP4JwsA
+-----END PRIVATE KEY-----`)
+
// ExpiredCertificate is a PEM-encoded certificate that is always expired,
// i.e., `Not Before`=`Not After`. It is signed by IntermediateCertificate.
ExpiredCertificate = []byte(`