aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus.dahlberg@kau.se>2021-06-06 15:59:35 +0200
committerRasmus Dahlberg <rasmus.dahlberg@kau.se>2021-06-06 15:59:35 +0200
commit47bacfd5c5d22470340e0823c4ad37b45914b68e (patch)
tree0984b55ced1e537e8d1d681c77157f1a47e47cdc /cmd
parent0285454c34b0b3003bc8ede3e304b843ad949be8 (diff)
started using the refactored packages in siglog server
Diffstat (limited to 'cmd')
-rw-r--r--cmd/siglog_server/.gitignore1
-rw-r--r--cmd/siglog_server/README.md60
-rw-r--r--cmd/siglog_server/main.go176
-rw-r--r--cmd/tmp/README.md2
-rw-r--r--cmd/tmp/cosign/main.go56
-rw-r--r--cmd/tmp/keygen/main.go17
-rw-r--r--cmd/tmp/submit/main.go29
7 files changed, 341 insertions, 0 deletions
diff --git a/cmd/siglog_server/.gitignore b/cmd/siglog_server/.gitignore
new file mode 100644
index 0000000..254defd
--- /dev/null
+++ b/cmd/siglog_server/.gitignore
@@ -0,0 +1 @@
+server
diff --git a/cmd/siglog_server/README.md b/cmd/siglog_server/README.md
new file mode 100644
index 0000000..71bb3ac
--- /dev/null
+++ b/cmd/siglog_server/README.md
@@ -0,0 +1,60 @@
+# Run Trillian + STFE locally
+Trillian uses a database. So, we will need to set that up. It is documented
+[here](https://github.com/google/trillian#mysql-setup), and how to check that it
+is setup properly
+[here](https://github.com/google/certificate-transparency-go/blob/master/trillian/docs/ManualDeployment.md#data-storage).
+
+Other than the database we need the Trillian log signer, Trillian log server,
+and STFE server.
+```
+$ go install github.com/google/trillian/cmd/trillian_log_signer
+$ go install github.com/google/trillian/cmd/trillian_log_server
+$ go install
+```
+
+Start Trillian log signer:
+```
+trillian_log_signer --logtostderr -v 9 --force_master --rpc_endpoint=localhost:6961 --http_endpoint=localhost:6964 --num_sequencers 1 --sequencer_interval 100ms --batch_size 100
+```
+
+Start Trillian log server:
+```
+trillian_log_server --logtostderr -v 9 --rpc_endpoint=localhost:6962 --http_endpoint=localhost:6963
+```
+
+As described in more detail
+[here](https://github.com/google/certificate-transparency-go/blob/master/trillian/docs/ManualDeployment.md#trillian-services),
+we need to provision a Merkle tree once:
+```
+$ go install github.com/google/trillian/cmd/createtree
+$ createtree --admin_server localhost:6962
+<tree id>
+```
+
+Hang on to `<tree id>`. Our STFE server will use it when talking to the
+Trillian log server to specify which Merkle tree we are working against.
+
+(If you take a look in the `Trees` table you will see that the tree has been
+provisioned.)
+
+We will also need a public key-pair and log identifier for the STFE server.
+```
+$ go install github.com/system-transparency/stfe/types/cmd/new-namespace
+sk: <sk>
+vk: <vk>
+ed25519_v1: <namespace>
+```
+
+The log's identifier is `<namespace>` and contains the public verification key
+`<vk>`. The log's corresponding secret signing key is `<sk>`.
+
+Start STFE server:
+```
+$ ./server --logtostderr -v 9 --http_endpoint localhost:6965 --log_rpc_server localhost:6962 --trillian_id <tree id> --key <sk>
+```
+
+If the log is responsive on, e.g., `GET http://localhost:6965/st/v1/get-latest-sth` you
+may want to try running
+`github.com/system-transparency/stfe/client/cmd/example.sh`. You need to
+configure the log's id though for verification to work (flag `log_id`, which
+should be set to the `<namespace>` output above).
diff --git a/cmd/siglog_server/main.go b/cmd/siglog_server/main.go
new file mode 100644
index 0000000..368b0a7
--- /dev/null
+++ b/cmd/siglog_server/main.go
@@ -0,0 +1,176 @@
+// Package main provides an STFE server binary
+package main
+
+import (
+ "context"
+ "crypto"
+ "crypto/ed25519"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "net/http"
+ "os"
+ "os/signal"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/golang/glog"
+ "github.com/google/trillian"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ stfe "github.com/system-transparency/stfe/pkg/instance"
+ "github.com/system-transparency/stfe/pkg/state"
+ trillianWrapper "github.com/system-transparency/stfe/pkg/trillian"
+ "github.com/system-transparency/stfe/pkg/types"
+ "google.golang.org/grpc"
+)
+
+var (
+ httpEndpoint = flag.String("http_endpoint", "localhost:6965", "host:port specification of where stfe serves clients")
+ rpcBackend = flag.String("log_rpc_server", "localhost:6962", "host:port specification of where Trillian serves clients")
+ prefix = flag.String("prefix", "", "a prefix that proceeds /st/v0/<endpoint>")
+ trillianID = flag.Int64("trillian_id", 0, "log identifier in the Trillian database")
+ deadline = flag.Duration("deadline", time.Second*10, "deadline for backend requests")
+ key = flag.String("key", "", "hex-encoded Ed25519 signing key")
+ witnesses = flag.String("witnesses", "", "comma-separated list of trusted witness verification keys in hex")
+ maxRange = flag.Int64("max_range", 10, "maximum number of entries that can be retrived in a single request")
+ interval = flag.Duration("interval", time.Second*30, "interval used to rotate the log's cosigned STH")
+)
+
+func main() {
+ flag.Parse()
+ defer glog.Flush()
+
+ // wait for clean-up before exit
+ var wg sync.WaitGroup
+ defer wg.Wait()
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ glog.V(3).Infof("configuring stfe instance...")
+ instance, err := setupInstanceFromFlags()
+ if err != nil {
+ glog.Errorf("setupInstance: %v", err)
+ return
+ }
+
+ glog.V(3).Infof("spawning state manager")
+ go func() {
+ wg.Add(1)
+ defer wg.Done()
+ instance.Stateman.Run(ctx)
+ glog.Errorf("state manager shutdown")
+ cancel() // must have state manager running
+ }()
+
+ glog.V(3).Infof("spawning await")
+ server := http.Server{Addr: *httpEndpoint}
+ go await(ctx, func() {
+ wg.Add(1)
+ defer wg.Done()
+ ctxInner, _ := context.WithTimeout(ctx, time.Second*60)
+ glog.Infof("Shutting down HTTP server...")
+ server.Shutdown(ctxInner)
+ glog.V(3).Infof("HTTP server shutdown")
+ glog.Infof("Shutting down spawned go routines...")
+ cancel()
+ })
+
+ glog.Infof("Serving on %v/%v", *httpEndpoint, *prefix)
+ if err = server.ListenAndServe(); err != http.ErrServerClosed {
+ glog.Errorf("ListenAndServe: %v", err)
+ }
+}
+
+// SetupInstance sets up a new STFE instance from flags
+func setupInstanceFromFlags() (*stfe.Instance, error) {
+ var i stfe.Instance
+ var err error
+
+ // Setup log configuration
+ i.Signer, i.LogID, err = newLogIdentity(*key)
+ if err != nil {
+ return nil, fmt.Errorf("newLogIdentity: %v", err)
+ }
+ i.TreeID = *trillianID
+ i.Prefix = *prefix
+ i.MaxRange = *maxRange
+ i.Deadline = *deadline
+ i.Interval = *interval
+ i.Witnesses, err = newWitnessMap(*witnesses)
+ if err != nil {
+ return nil, fmt.Errorf("newWitnessMap: %v", err)
+ }
+
+ // Setup log client
+ dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(i.Deadline)}
+ conn, err := grpc.Dial(*rpcBackend, dialOpts...)
+ if err != nil {
+ return nil, fmt.Errorf("Dial: %v", err)
+ }
+ i.Client = &trillianWrapper.TrillianClient{
+ TreeID: i.TreeID,
+ GRPC: trillian.NewTrillianLogClient(conn),
+ }
+
+ // Setup state manager
+ i.Stateman, err = state.NewStateManagerSingle(i.Client, i.Signer, i.Interval, i.Deadline)
+ if err != nil {
+ return nil, fmt.Errorf("NewStateManager: %v", err)
+ }
+
+ // Register HTTP endpoints
+ mux := http.NewServeMux()
+ http.Handle("/", mux)
+ for _, handler := range i.Handlers() {
+ glog.V(3).Infof("adding handler: %s", handler.Path())
+ mux.Handle(handler.Path(), handler)
+ }
+ glog.V(3).Infof("Adding prometheus handler on path: /metrics")
+ http.Handle("/metrics", promhttp.Handler())
+
+ return &i, nil
+}
+
+func newLogIdentity(key string) (crypto.Signer, string, error) {
+ buf, err := hex.DecodeString(key)
+ if err != nil {
+ return nil, "", fmt.Errorf("DecodeString: %v", err)
+ }
+ sk := crypto.Signer(ed25519.PrivateKey(buf))
+ vk := sk.Public().(ed25519.PublicKey)
+ return sk, hex.EncodeToString([]byte(vk[:])), nil
+}
+
+// newWitnessMap creates a new map of trusted witnesses
+func newWitnessMap(witnesses string) (map[[types.HashSize]byte][types.VerificationKeySize]byte, error) {
+ w := make(map[[types.HashSize]byte][types.VerificationKeySize]byte)
+ if len(witnesses) > 0 {
+ for _, witness := range strings.Split(witnesses, ",") {
+ b, err := hex.DecodeString(witness)
+ if err != nil {
+ return nil, fmt.Errorf("DecodeString: %v", err)
+ }
+
+ var vk [types.VerificationKeySize]byte
+ if n := copy(vk[:], b); n != types.VerificationKeySize {
+ return nil, fmt.Errorf("Invalid verification key size: %v", n)
+ }
+ w[*types.Hash(vk[:])] = vk
+ }
+ }
+ return w, nil
+}
+
+// await waits for a shutdown signal and then runs a clean-up function
+func await(ctx context.Context, done func()) {
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+ select {
+ case <-sigs:
+ case <-ctx.Done():
+ }
+ glog.V(3).Info("received shutdown signal")
+ done()
+}
diff --git a/cmd/tmp/README.md b/cmd/tmp/README.md
new file mode 100644
index 0000000..30d5317
--- /dev/null
+++ b/cmd/tmp/README.md
@@ -0,0 +1,2 @@
+# Warning
+These basic commands will be moved or replaced by proper tooling.
diff --git a/cmd/tmp/cosign/main.go b/cmd/tmp/cosign/main.go
new file mode 100644
index 0000000..a51f17d
--- /dev/null
+++ b/cmd/tmp/cosign/main.go
@@ -0,0 +1,56 @@
+package main
+
+import (
+ "bytes"
+ "crypto/ed25519"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/system-transparency/stfe/pkg/types"
+)
+
+var (
+ url = flag.String("url", "http://localhost:6965/st/v0", "base url")
+ sk = flag.String("sk", "e1d7c494dacb0ddf809a17e4528b01f584af22e3766fa740ec52a1711c59500d711090dd2286040b50961b0fe09f58aa665ccee5cb7ee042d819f18f6ab5046b", "hex key")
+)
+
+func main() {
+ priv, err := hex.DecodeString(*sk)
+ if err != nil {
+ log.Fatalf("DecodeString: %v", err)
+ }
+ sk := ed25519.PrivateKey(priv)
+ vk := sk.Public().(ed25519.PublicKey)
+ fmt.Printf("sk: %x\nvk: %x\n", sk, vk)
+
+ rsp, err := http.Get(*url + "/get-tree-head-to-sign")
+ if err != nil {
+ log.Fatalf("Get: %v", err)
+ }
+ var sth types.SignedTreeHead
+ if err := sth.UnmarshalASCII(rsp.Body); err != nil {
+ log.Fatalf("UnmarshalASCII: %v", err)
+ }
+ fmt.Printf("%+v\n", sth)
+
+ msg := sth.TreeHead.Marshal()
+ sig := ed25519.Sign(sk, msg)
+ sigident := &types.SigIdent{
+ KeyHash: types.Hash(vk[:]),
+ Signature: &[types.SignatureSize]byte{},
+ }
+ copy(sigident.Signature[:], sig)
+
+ buf := bytes.NewBuffer(nil)
+ if err := sigident.MarshalASCII(buf); err != nil {
+ log.Fatalf("MarshalASCII: %v", err)
+ }
+ rsp, err = http.Post(*url+"/add-cosignature", "type/stfe", buf)
+ if err != nil {
+ log.Fatalf("Post: %v", err)
+ }
+ fmt.Printf("Status: %v\n", rsp.StatusCode)
+}
diff --git a/cmd/tmp/keygen/main.go b/cmd/tmp/keygen/main.go
new file mode 100644
index 0000000..c1c1b58
--- /dev/null
+++ b/cmd/tmp/keygen/main.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "crypto/ed25519"
+ "crypto/rand"
+ "fmt"
+ "log"
+)
+
+func main() {
+ vk, sk, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ log.Fatalf("GenerateKey: %v", err)
+ }
+ fmt.Printf("sk: %x\n", sk[:])
+ fmt.Printf("vk: %x\n", vk[:])
+}
diff --git a/cmd/tmp/submit/main.go b/cmd/tmp/submit/main.go
new file mode 100644
index 0000000..3dcaa97
--- /dev/null
+++ b/cmd/tmp/submit/main.go
@@ -0,0 +1,29 @@
+package main
+
+// go run . | bash
+
+import (
+ "crypto/ed25519"
+ "crypto/rand"
+ "fmt"
+
+ "github.com/system-transparency/stfe/pkg/types"
+)
+
+func main() {
+ checksum := [32]byte{}
+ msg := types.Message{
+ ShardHint: 0,
+ Checksum: &checksum,
+ }
+
+ vk, sk, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ fmt.Printf("ed25519.GenerateKey: %v\n", err)
+ return
+ }
+ sig := ed25519.Sign(sk, msg.Marshal())
+ //fmt.Printf("sk: %x\nvk: %x\n", sk[:], vk[:])
+
+ fmt.Printf("echo \"shard_hint=%d\nchecksum=%x\nsignature_over_message=%x\nverification_key=%x\ndomain_hint=%s\" | curl --data-binary @- localhost:6965/st/v0/add-leaf\n", msg.ShardHint, msg.Checksum[:], sig, vk[:], "example.com")
+}