From 20f3b169beccb1bc50dd468559452b795df083ff Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 12 Jul 2017 18:54:59 +0100 Subject: [PATCH 01/46] WIP: monitor binary Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's work in progress addressed some early review comments --- .../grpcc/grpc_client.go | 2 +- cmd/keytransparency-monitor/Dockerfile | 42 ++++ cmd/keytransparency-monitor/main.go | 160 ++++++++++++ core/mutation/mutation.go | 4 +- core/proto/keytransparency_v1_types/gen.go | 2 +- .../keytransparency_v1_types.pb.go | 185 +++++--------- .../keytransparency_v1_types.proto | 34 ++- docker-compose.yml | 12 + impl/monitor/monitor.go | 186 ++++++++++++++ impl/monitor/monitor_test.go | 24 ++ impl/mutation/mutation.go | 2 +- impl/proto/keytransparency_v1_service/gen.go | 4 +- impl/proto/monitor_v1_service/gen.go | 19 ++ .../monitor_v1_service.pb.go | 226 +++++++++++++++++ .../monitor_v1_service.pb.gw.go | 231 ++++++++++++++++++ .../monitor_v1_service.proto | 56 +++++ impl/proto/mutation_v1_service/gen.go | 4 +- 17 files changed, 1064 insertions(+), 129 deletions(-) create mode 100644 cmd/keytransparency-monitor/Dockerfile create mode 100644 cmd/keytransparency-monitor/main.go create mode 100644 impl/monitor/monitor.go create mode 100644 impl/monitor/monitor_test.go create mode 100644 impl/proto/monitor_v1_service/gen.go create mode 100644 impl/proto/monitor_v1_service/monitor_v1_service.pb.go create mode 100644 impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go create mode 100644 impl/proto/monitor_v1_service/monitor_v1_service.proto diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 646ee0052..129c5dc2d 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -53,7 +53,7 @@ const ( var ( // ErrRetry occurs when an update request has been submitted, but the - // results of the udpate are not visible on the server yet. The client + // results of the update are not visible on the server yet. The client // must retry until the request is visible. ErrRetry = errors.New("update not present on server yet") // ErrIncomplete occurs when the server indicates that requested epochs diff --git a/cmd/keytransparency-monitor/Dockerfile b/cmd/keytransparency-monitor/Dockerfile new file mode 100644 index 000000000..e62112ca7 --- /dev/null +++ b/cmd/keytransparency-monitor/Dockerfile @@ -0,0 +1,42 @@ +FROM golang + +ENV HOST=0.0.0.0 \ + RPC_PORT=8099 + +# TLS Certificate needs 0.0.0.0 to be in the SAN IP field. +ENV VRF_PUB=keytransparency/genfiles/vrf-key.pem \ + TLS_KEY_PATH=genfiles/server.key \ + TLS_CRT_PATH=genfiles/server.crt + +ENV KT_URL=kt-server:8080 + +ENV MAP_ID=0 \ + MAP_URL="" +ENV LOG_ID=0 \ + LOG_URL=localhost:8090 +ENV MONITOR_SIGN_KEY=TODO \ + POLL_PERIOD=5s + +ENV VERBOSITY=1 + +ADD keytransparency/genfiles/* /kt/ +ADD ./keytransparency /go/src/github.com/google/keytransparency +ADD ./trillian /go/src/github.com/google/trillian +WORKDIR /go/src/github.com/google/keytransparency + +RUN apt-get update && apt-get install -y libtool libltdl-dev +RUN go get -tags="mysql" ./cmd/keytransparency-monitor + +ENTRYPOINT /go/bin/keytransparency-monitor \ + --addr="$HOST:$RPC_PORT" --kt-url="$KT_URL" --poll-period="$POLL_PERIOD" \ + --vrf="$VRF_PUB" \ + --key="$TLS_KEY_PATH" --cert="$TLS_CRT_PATH" \ + --log-id="$LOG_ID" --log-key="$LOG_PUB_KEY" \ + --map-id="$MAP_ID" \ + --alsologtostderr \ + --v=${VERBOSITY} + +EXPOSE $RPC_PORT + +#HEALTHCHECK --interval=5m --timeout=3s \ +# CMD curl -f http://localhost:$RPC_PORT/TODO || exit 1 diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go new file mode 100644 index 000000000..fe1e256e4 --- /dev/null +++ b/cmd/keytransparency-monitor/main.go @@ -0,0 +1,160 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "net" + "net/http" + "strings" + "time" + + mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" + + "github.com/golang/glog" + "github.com/google/keytransparency/impl/monitor" + "github.com/grpc-ecosystem/go-grpc-prometheus" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/reflection" +) + +var ( + addr = flag.String("addr", ":8099", "The ip:port combination to listen on") + keyFile = flag.String("key", "genfiles/server.key", "TLS private key file") + certFile = flag.String("cert", "genfiles/server.pem", "TLS cert file") + + pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") + ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") + ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") + // TODO(ismail): are the IDs actually needed for verification operations? + mapID = flag.Int64("map-id", 0, "Trillian map ID") + logID = flag.Int64("log-id", 0, "Trillian Log ID") + + // TODO(ismail): expose prometheus metrics: a variable that tracks valid/invalid MHs + metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") +) + +func grpcGatewayMux(addr string) (*runtime.ServeMux, error) { + ctx := context.Background() + creds, err := credentials.NewClientTLSFromFile(*certFile, "") + if err != nil { + return nil, err + } + dopts := []grpc.DialOption{grpc.WithTransportCredentials(creds)} + gwmux := runtime.NewServeMux() + if err := mopb.RegisterMonitorServiceHandlerFromEndpoint(ctx, gwmux, addr, dopts); err != nil { + return nil, err + } + + return gwmux, nil +} + +// grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC +// connections or otherHandler otherwise. Copied from cockroachdb. +func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // This is a partial recreation of gRPC's internal checks. + // https://github.com/grpc/grpc-go/blob/master/transport/handler_server.go#L62 + if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { + grpcServer.ServeHTTP(w, r) + } else { + otherHandler.ServeHTTP(w, r) + } + }) +} + +func main() { + flag.Parse() + + creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + if err != nil { + glog.Exitf("Failed to load server credentials %v", err) + } + + // Create gRPC server. + grpcServer := grpc.NewServer( + grpc.Creds(creds), + grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), + grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), + ) + + // Connect to the kt-server's mutation API: + grpcc, err := dial(*ktURL, *ktPEM) + if err != nil { + glog.Fatalf("Error Dialing %v: %v", ktURL, err) + } + mcc := mupb.NewMutationServiceClient(grpcc) + + srv := monitor.New(mcc, *mapID, *pollPeriod) + + mopb.RegisterMonitorServiceServer(grpcServer, srv) + reflection.Register(grpcServer) + grpc_prometheus.Register(grpcServer) + grpc_prometheus.EnableHandlingTimeHistogram() + + // Create HTTP handlers and gRPC gateway. + gwmux, err := grpcGatewayMux(*addr) + if err != nil { + glog.Exitf("Failed setting up REST proxy: %v", err) + } + + // Insert handlers for other http paths here. + mux := http.NewServeMux() + mux.Handle("/", gwmux) + + go func() { + if err := srv.StartPolling(); err != nil { + glog.Fatalf("Could not start polling mutations.") + } + }() + + // Serve HTTP2 server over TLS. + glog.Infof("Listening on %v", *addr) + if err := http.ListenAndServeTLS(*addr, *certFile, *keyFile, + grpcHandlerFunc(grpcServer, mux)); err != nil { + glog.Errorf("ListenAndServeTLS: %v", err) + } +} + +func dial(ktURL, caFile string) (*grpc.ClientConn, error) { + var opts []grpc.DialOption + host, _, err := net.SplitHostPort(ktURL) + if err != nil { + return nil, err + } + var creds credentials.TransportCredentials + if caFile != "" { + var err error + creds, err = credentials.NewClientTLSFromFile(caFile, host) + if err != nil { + return nil, err + } + } else { + // Use the local set of root certs. + creds = credentials.NewClientTLSFromCert(nil, host) + } + opts = append(opts, grpc.WithTransportCredentials(creds)) + + // TODO(ismail): authenticate the monitor to the kt-server: + cc, err := grpc.Dial(ktURL, opts...) + if err != nil { + return nil, err + } + return cc, nil +} diff --git a/core/mutation/mutation.go b/core/mutation/mutation.go index 2501ccdd7..a8fa2e548 100644 --- a/core/mutation/mutation.go +++ b/core/mutation/mutation.go @@ -212,9 +212,9 @@ func (s *Server) inclusionProofs(ctx context.Context, indexes [][]byte, epoch in glog.Errorf("GetLeaves(): %v", err) return nil, grpc.Errorf(codes.Internal, "Failed fetching map leaf") } - if got, want := len(getResp.MapLeafInclusion), len(indexes); got != want { + if got, want := len(getResp.GetMapLeafInclusion()), len(indexes); got != want { glog.Errorf("GetLeaves() len: %v, want %v", got, want) return nil, grpc.Errorf(codes.Internal, "Failed fetching map leaf") } - return getResp.MapLeafInclusion, nil + return getResp.GetMapLeafInclusion(), nil } diff --git a/core/proto/keytransparency_v1_types/gen.go b/core/proto/keytransparency_v1_types/gen.go index 872643e35..38cf707a6 100644 --- a/core/proto/keytransparency_v1_types/gen.go +++ b/core/proto/keytransparency_v1_types/gen.go @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis --go_out=:. keytransparency_v1_types.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ -I=$GOPATH/src/github.com/google/trillian/ --go_out=:. keytransparency_v1_types.proto package keytransparency_v1_types diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go index 4f6d61237..4e4873512 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go @@ -29,6 +29,8 @@ It has these top-level messages: UpdateEntryResponse GetMutationsRequest GetMutationsResponse + GetMonitoringRequest + GetMonitoringResponse GetDomainInfoRequest GetDomainInfoResponse */ @@ -499,7 +501,7 @@ type ListEntryHistoryRequest struct { // app_id is the identifier for the application. AppId string `protobuf:"bytes,4,opt,name=app_id,json=appId" json:"app_id,omitempty"` // first_tree_size is the tree_size of the currently trusted log root. - // Omitting this field will ommit the log consistency proof from the response. + // Omitting this field will omit the log consistency proof from the response. FirstTreeSize int64 `protobuf:"varint,5,opt,name=first_tree_size,json=firstTreeSize" json:"first_tree_size,omitempty"` } @@ -618,7 +620,7 @@ func (m *UpdateEntryRequest) GetEntryUpdate() *EntryUpdate { } // UpdateEntryResponse contains a proof once the update has been included in -// the Merkel Tree. +// the Merkle Tree. type UpdateEntryResponse struct { // proof contains a proof that the update has been included in the tree. Proof *GetEntryResponse `protobuf:"bytes,1,opt,name=proof" json:"proof,omitempty"` @@ -759,52 +761,6 @@ func (m *GetMutationsResponse) GetNextPageToken() string { return "" } -// GetDomainInfoRequest contains an empty request to query the GetDomainInfo -// APIs. -type GetDomainInfoRequest struct { -} - -func (m *GetDomainInfoRequest) Reset() { *m = GetDomainInfoRequest{} } -func (m *GetDomainInfoRequest) String() string { return proto.CompactTextString(m) } -func (*GetDomainInfoRequest) ProtoMessage() {} -func (*GetDomainInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } - -// GetDomainInfoResponse contains the results of GetDomainInfo APIs. -type GetDomainInfoResponse struct { - // Log contains the Log-Tree's info. - Log *trillian.Tree `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` - // Map contains the Map-Tree's info. - Map *trillian.Tree `protobuf:"bytes,2,opt,name=map" json:"map,omitempty"` - // Vrf contains the VRF public key. - Vrf *keyspb.PublicKey `protobuf:"bytes,3,opt,name=vrf" json:"vrf,omitempty"` -} - -func (m *GetDomainInfoResponse) Reset() { *m = GetDomainInfoResponse{} } -func (m *GetDomainInfoResponse) String() string { return proto.CompactTextString(m) } -func (*GetDomainInfoResponse) ProtoMessage() {} -func (*GetDomainInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } - -func (m *GetDomainInfoResponse) GetLog() *trillian.Tree { - if m != nil { - return m.Log - } - return nil -} - -func (m *GetDomainInfoResponse) GetMap() *trillian.Tree { - if m != nil { - return m.Map - } - return nil -} - -func (m *GetDomainInfoResponse) GetVrf() *keyspb.PublicKey { - if m != nil { - return m.Vrf - } - return nil -} - func init() { proto.RegisterType((*Committed)(nil), "keytransparency.v1.types.Committed") proto.RegisterType((*EntryUpdate)(nil), "keytransparency.v1.types.EntryUpdate") @@ -821,79 +777,72 @@ func init() { proto.RegisterType((*UpdateEntryResponse)(nil), "keytransparency.v1.types.UpdateEntryResponse") proto.RegisterType((*GetMutationsRequest)(nil), "keytransparency.v1.types.GetMutationsRequest") proto.RegisterType((*GetMutationsResponse)(nil), "keytransparency.v1.types.GetMutationsResponse") - proto.RegisterType((*GetDomainInfoRequest)(nil), "keytransparency.v1.types.GetDomainInfoRequest") - proto.RegisterType((*GetDomainInfoResponse)(nil), "keytransparency.v1.types.GetDomainInfoResponse") } func init() { proto.RegisterFile("keytransparency_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1057 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdd, 0x4e, 0x1b, 0xc7, - 0x17, 0x8f, 0xbd, 0xd8, 0xd8, 0x87, 0xaf, 0xfc, 0x27, 0x04, 0xf6, 0xef, 0x2a, 0x11, 0x5a, 0xd4, - 0x36, 0xad, 0x2a, 0x37, 0x38, 0x82, 0x36, 0xe9, 0x45, 0xd3, 0x24, 0x55, 0x40, 0x80, 0x84, 0x86, - 0x84, 0x5e, 0xae, 0x06, 0x7b, 0xbc, 0x8c, 0x58, 0xef, 0x4c, 0x67, 0x66, 0xad, 0x2c, 0x52, 0xa5, - 0x3e, 0x40, 0xa5, 0x4a, 0x7d, 0x86, 0x3e, 0x43, 0x5f, 0xa0, 0x6f, 0xd1, 0xa7, 0xa9, 0xe6, 0x63, - 0xfd, 0x01, 0x26, 0x84, 0x5c, 0xf4, 0xc6, 0x9e, 0xf3, 0xb5, 0xe7, 0x9c, 0xdf, 0xf9, 0x9d, 0xd9, - 0x85, 0x87, 0xe7, 0xb4, 0xd0, 0x92, 0x64, 0x4a, 0x10, 0x49, 0xb3, 0x6e, 0x11, 0x0f, 0xb7, 0x62, - 0x5d, 0x08, 0xaa, 0xda, 0x42, 0x72, 0xcd, 0x51, 0x78, 0xc9, 0xde, 0x1e, 0x6e, 0xb5, 0xad, 0xbd, - 0xd5, 0xea, 0xca, 0x42, 0x68, 0xfe, 0xf5, 0x39, 0x2d, 0x94, 0x38, 0xf5, 0x7f, 0x2e, 0xaa, 0x15, - 0x7a, 0x9b, 0x62, 0x89, 0x38, 0x75, 0xbf, 0xde, 0xb2, 0xac, 0x25, 0x4b, 0x53, 0x46, 0x32, 0x2f, - 0xaf, 0x95, 0x72, 0x3c, 0x20, 0x22, 0x26, 0x82, 0x39, 0x7d, 0xb4, 0x05, 0xcd, 0x97, 0x7c, 0x30, - 0x60, 0x5a, 0xd3, 0x1e, 0xba, 0x0b, 0xc1, 0x39, 0x2d, 0xc2, 0xca, 0x46, 0xe5, 0xd1, 0x22, 0x36, - 0x47, 0x84, 0x60, 0xae, 0x47, 0x34, 0x09, 0xab, 0x56, 0x65, 0xcf, 0xd1, 0x6f, 0x15, 0x58, 0xf8, - 0x31, 0xd3, 0xb2, 0x78, 0x2b, 0x7a, 0x44, 0x53, 0xf4, 0x0c, 0xea, 0xb9, 0x3d, 0x59, 0xaf, 0x85, - 0x4e, 0xd4, 0xbe, 0xae, 0x97, 0xf6, 0x31, 0x4b, 0x32, 0xda, 0xdb, 0x3f, 0xc1, 0x3e, 0x02, 0xfd, - 0x00, 0xcd, 0x6e, 0x99, 0x3e, 0x0c, 0x6c, 0xf8, 0xe6, 0xf5, 0xe1, 0xa3, 0x4a, 0xf1, 0x38, 0x2a, - 0xca, 0xa1, 0x66, 0xab, 0x41, 0x0f, 0x01, 0x9c, 0x76, 0x40, 0x33, 0xed, 0x9b, 0x98, 0xd0, 0xa0, - 0x03, 0x58, 0x21, 0xb9, 0x3e, 0xe3, 0x92, 0x5d, 0xd0, 0x5e, 0x6c, 0x70, 0x0c, 0xab, 0x1b, 0xc1, - 0xfb, 0x33, 0x1e, 0xe5, 0xa7, 0x29, 0xeb, 0xee, 0xd3, 0x02, 0x2f, 0x8f, 0x63, 0xf7, 0x69, 0xa1, - 0xa2, 0x3f, 0x2b, 0xd0, 0x1c, 0x59, 0x51, 0x0b, 0xe6, 0x69, 0xaf, 0xb3, 0xbd, 0xbd, 0xf5, 0xd4, - 0x25, 0xde, 0xbd, 0x83, 0x4b, 0x05, 0xfa, 0x0e, 0xfe, 0x2f, 0x15, 0x89, 0x87, 0x54, 0xb2, 0x7e, - 0xc1, 0xb2, 0x24, 0x56, 0x67, 0xa4, 0xb3, 0xbd, 0x13, 0x3f, 0x79, 0xfc, 0x4d, 0xc7, 0x01, 0xbb, - 0x7b, 0x07, 0xaf, 0x49, 0x45, 0x4e, 0x4a, 0x8f, 0x63, 0xeb, 0x60, 0xec, 0xa8, 0x03, 0xab, 0xb4, - 0xdb, 0x9b, 0x0a, 0x17, 0x9d, 0xed, 0x1d, 0x8b, 0x95, 0x89, 0x43, 0xd6, 0x3a, 0x8a, 0x3c, 0xea, - 0x6c, 0xef, 0xbc, 0x00, 0x68, 0x9c, 0xd3, 0xc2, 0xd2, 0x2b, 0xea, 0x40, 0x63, 0x9f, 0x16, 0x27, - 0x24, 0xcd, 0xe9, 0x8c, 0xf1, 0xae, 0x42, 0x6d, 0x68, 0x4c, 0x7e, 0xbe, 0x4e, 0x88, 0xfe, 0xa8, - 0x42, 0xa3, 0x9c, 0x14, 0xfa, 0x1e, 0x9a, 0xe6, 0x61, 0xce, 0xad, 0x72, 0xd3, 0x80, 0xcb, 0x5c, - 0xd8, 0x54, 0xe0, 0xb2, 0x62, 0x00, 0xc5, 0x92, 0x8c, 0xe8, 0x5c, 0xd2, 0x12, 0xf1, 0xce, 0xcd, - 0x14, 0xb1, 0x07, 0x17, 0x64, 0xc7, 0x8b, 0x27, 0x9e, 0x82, 0x5a, 0xd0, 0x10, 0x92, 0x0e, 0x19, - 0xcf, 0x95, 0x43, 0x02, 0x8f, 0xe4, 0xd6, 0x5b, 0x58, 0xb9, 0x14, 0x3a, 0xd9, 0x78, 0xd3, 0x35, - 0xfe, 0xd5, 0x64, 0xe3, 0x0b, 0x9d, 0xb5, 0xb6, 0xdb, 0x9d, 0x57, 0x2c, 0x61, 0x9a, 0xa4, 0x69, - 0xe1, 0xaa, 0xf0, 0x80, 0x3c, 0xab, 0x7e, 0x5b, 0x89, 0xde, 0x41, 0xe3, 0x30, 0xd7, 0x44, 0x33, - 0x9e, 0x4d, 0x30, 0xbe, 0x72, 0x6b, 0xc6, 0x3f, 0x86, 0x9a, 0x90, 0x9c, 0xf7, 0x7d, 0xe6, 0x56, - 0x7b, 0xb4, 0xa8, 0x87, 0x44, 0x1c, 0x50, 0xd2, 0xdf, 0xcb, 0xba, 0x69, 0xae, 0x18, 0xcf, 0xb0, - 0x73, 0x8c, 0x18, 0xac, 0xbc, 0xa6, 0xda, 0x81, 0x40, 0x7f, 0xce, 0xa9, 0xd2, 0x68, 0x1d, 0xe6, - 0x73, 0x45, 0x65, 0xcc, 0x7a, 0xbe, 0xa9, 0xba, 0x11, 0xf7, 0x7a, 0xe8, 0x3e, 0xd4, 0x89, 0x10, - 0x46, 0x5f, 0xb5, 0xfa, 0x1a, 0x11, 0x62, 0xaf, 0x87, 0x3e, 0x83, 0x95, 0x3e, 0x93, 0x4a, 0xc7, - 0x5a, 0x52, 0x1a, 0x2b, 0x76, 0x41, 0x2d, 0x6c, 0x01, 0x5e, 0xb2, 0xea, 0x37, 0x92, 0xd2, 0x63, - 0x76, 0x41, 0xa3, 0x7f, 0xaa, 0x70, 0x77, 0x9c, 0x4b, 0x09, 0x9e, 0x29, 0x8a, 0x3e, 0x81, 0xe6, - 0x50, 0xf6, 0x63, 0x57, 0xb5, 0x23, 0x4f, 0x63, 0x28, 0xfb, 0x47, 0x46, 0x9e, 0x5e, 0xe0, 0xea, - 0xc7, 0x2c, 0x30, 0x7a, 0x0a, 0x90, 0x52, 0x52, 0x26, 0x08, 0x6e, 0x84, 0xa5, 0x69, 0xbc, 0x5d, - 0xf6, 0x2f, 0x20, 0x50, 0x03, 0x19, 0xce, 0xd9, 0x98, 0xf5, 0x71, 0x8c, 0x43, 0xfd, 0x90, 0x08, - 0xcc, 0xb9, 0xc6, 0xc6, 0x07, 0x75, 0xa0, 0x91, 0xf2, 0x24, 0x96, 0x9c, 0xeb, 0xb0, 0x36, 0xdb, - 0xff, 0x80, 0x27, 0xd6, 0x7f, 0x3e, 0x75, 0x07, 0xf4, 0x39, 0xac, 0x98, 0x98, 0x2e, 0xcf, 0x14, - 0x53, 0xda, 0xb4, 0x12, 0xd6, 0x37, 0x82, 0x47, 0x8b, 0x78, 0x39, 0xe5, 0xc9, 0xcb, 0xb1, 0x16, - 0x6d, 0xc2, 0x92, 0x71, 0x64, 0x65, 0x8d, 0xe1, 0xbc, 0x75, 0x5b, 0x4c, 0x79, 0x32, 0xaa, 0xdb, - 0xdc, 0x18, 0xeb, 0x07, 0x4c, 0x39, 0x74, 0x77, 0x99, 0xd2, 0xfc, 0x03, 0x06, 0xba, 0x0a, 0x35, - 0xa5, 0x89, 0xd4, 0x16, 0xdb, 0x00, 0x3b, 0xc1, 0x8c, 0x44, 0x90, 0x64, 0x62, 0x92, 0x35, 0xdc, - 0x30, 0x0a, 0x33, 0xc4, 0x09, 0x0e, 0xcc, 0xdd, 0xc0, 0x81, 0xda, 0x2c, 0x0e, 0xfc, 0x02, 0xe1, - 0xd5, 0x2a, 0x3d, 0x15, 0x5e, 0x40, 0xdd, 0x6e, 0x84, 0x0a, 0x2b, 0x76, 0x8f, 0xbf, 0xbc, 0x7e, - 0xd4, 0x97, 0x69, 0x84, 0x7d, 0x24, 0x7a, 0x00, 0x90, 0xd1, 0x77, 0x3a, 0x9e, 0x6c, 0xab, 0x69, - 0x34, 0xc7, 0x46, 0x11, 0xfd, 0x55, 0x01, 0xe4, 0x5e, 0x2c, 0xff, 0x05, 0xe3, 0xd1, 0x2e, 0x2c, - 0x52, 0x93, 0x27, 0xf6, 0x0b, 0xed, 0xa8, 0xf4, 0xe9, 0xf5, 0x7d, 0x4d, 0xbc, 0xf9, 0xf0, 0x02, - 0x1d, 0x0b, 0xd1, 0x4f, 0x70, 0x6f, 0xaa, 0x6e, 0x0f, 0xd9, 0xf3, 0x72, 0xdf, 0xdd, 0x55, 0x71, - 0x1b, 0xc4, 0xfc, 0xfe, 0xff, 0x5e, 0x81, 0x7b, 0xaf, 0xa9, 0x2e, 0x6f, 0x1f, 0x55, 0x42, 0xb2, - 0x0a, 0x35, 0x2a, 0x78, 0xf7, 0xcc, 0x3e, 0x39, 0xc0, 0x4e, 0x98, 0xd5, 0x78, 0x75, 0x56, 0xe3, - 0x0f, 0x00, 0x2c, 0x85, 0x34, 0x3f, 0xa7, 0x99, 0xc5, 0xa6, 0x89, 0x2d, 0xa9, 0xde, 0x18, 0xc5, - 0x34, 0xc3, 0xe6, 0xa6, 0x19, 0x16, 0xfd, 0x5d, 0x85, 0xd5, 0xe9, 0x8a, 0x7c, 0xb3, 0xb3, 0x4b, - 0xf2, 0x5b, 0x5a, 0xbd, 0xe5, 0x96, 0x06, 0x1f, 0xbf, 0xa5, 0x73, 0x1f, 0xb6, 0xa5, 0xb5, 0xab, - 0x5b, 0x8a, 0x9e, 0x43, 0x73, 0x50, 0xf6, 0x65, 0xb7, 0xfd, 0xbd, 0xd7, 0x7b, 0x09, 0x01, 0x1e, - 0x07, 0x99, 0x09, 0x58, 0x82, 0x4f, 0xc0, 0x3b, 0x6f, 0xe1, 0x5d, 0x32, 0xea, 0xa3, 0x12, 0xe2, - 0x68, 0xcd, 0x82, 0xf8, 0x8a, 0x0f, 0x08, 0xcb, 0xf6, 0xb2, 0x3e, 0xf7, 0x73, 0x8d, 0x7e, 0xad, - 0xc0, 0xfd, 0x4b, 0x06, 0x0f, 0xef, 0x06, 0x04, 0x29, 0x4f, 0x3c, 0x93, 0x96, 0xc7, 0xc0, 0x98, - 0xa1, 0x62, 0x63, 0x32, 0x1e, 0x03, 0x22, 0x3c, 0xd4, 0x57, 0x3c, 0x06, 0x44, 0xa0, 0x4d, 0x08, - 0x86, 0xb2, 0xbc, 0x66, 0xff, 0xd7, 0xf6, 0x9f, 0x93, 0xe3, 0xef, 0x1c, 0x63, 0x3d, 0xad, 0xdb, - 0x8f, 0xc3, 0x27, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x87, 0x52, 0x53, 0x62, 0xb6, 0x0a, 0x00, - 0x00, + // 985 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdf, 0x6e, 0xdb, 0xb6, + 0x17, 0xae, 0xed, 0xd8, 0xb1, 0x4e, 0xfe, 0x15, 0x6c, 0x7e, 0x89, 0x7e, 0x1e, 0x5a, 0x04, 0x2a, + 0xb6, 0x75, 0xc3, 0xe0, 0x35, 0x2a, 0x92, 0xad, 0xdd, 0xc5, 0xba, 0x76, 0x43, 0x13, 0x24, 0x01, + 0x02, 0xa6, 0xcd, 0x2e, 0x05, 0xc6, 0xa2, 0x15, 0x22, 0xb2, 0xc8, 0x91, 0x94, 0x51, 0x05, 0xd8, + 0x1b, 0x0c, 0x18, 0xb0, 0x67, 0xd8, 0x33, 0xec, 0x05, 0xf6, 0x16, 0x7b, 0x9a, 0x81, 0xa4, 0x64, + 0xcb, 0xa9, 0xd3, 0x34, 0xbd, 0xd8, 0x4d, 0xc0, 0x73, 0x78, 0x3e, 0x9d, 0x73, 0xbe, 0xf3, 0x1d, + 0x3a, 0xf0, 0xe0, 0x82, 0x16, 0x5a, 0x92, 0x4c, 0x09, 0x22, 0x69, 0x36, 0x28, 0xa2, 0xf1, 0x76, + 0xa4, 0x0b, 0x41, 0x55, 0x5f, 0x48, 0xae, 0x39, 0xf2, 0xaf, 0xdc, 0xf7, 0xc7, 0xdb, 0x7d, 0x7b, + 0xdf, 0xf3, 0x07, 0xb2, 0x10, 0x9a, 0x7f, 0xad, 0x58, 0x22, 0xce, 0xdc, 0x5f, 0x87, 0xe9, 0xad, + 0x6a, 0xc9, 0xd2, 0x94, 0x91, 0xac, 0xb4, 0x37, 0x2a, 0x3b, 0x1a, 0x11, 0x11, 0x11, 0xc1, 0x9c, + 0x3f, 0xd8, 0x06, 0xef, 0x25, 0x1f, 0x8d, 0x98, 0xd6, 0x34, 0x46, 0x77, 0xa1, 0x75, 0x41, 0x0b, + 0xbf, 0xb1, 0xd5, 0x78, 0xb4, 0x8c, 0xcd, 0x11, 0x21, 0x58, 0x88, 0x89, 0x26, 0x7e, 0xd3, 0xba, + 0xec, 0x39, 0xf8, 0xad, 0x01, 0x4b, 0x3f, 0x65, 0x5a, 0x16, 0x6f, 0x44, 0x4c, 0x34, 0x45, 0xcf, + 0xa0, 0x93, 0xdb, 0x93, 0x8d, 0x5a, 0x0a, 0x83, 0xfe, 0x75, 0xf5, 0xf6, 0x4f, 0x58, 0x92, 0xd1, + 0xf8, 0xe0, 0x14, 0x97, 0x08, 0xf4, 0x03, 0x78, 0x83, 0x2a, 0xbd, 0xdf, 0xb2, 0xf0, 0x87, 0xd7, + 0xc3, 0x27, 0x95, 0xe2, 0x29, 0x2a, 0xc8, 0xa1, 0x6d, 0xab, 0x41, 0x0f, 0x00, 0x9c, 0x77, 0x44, + 0x33, 0x5d, 0x36, 0x51, 0xf3, 0xa0, 0x43, 0x58, 0x23, 0xb9, 0x3e, 0xe7, 0x92, 0x5d, 0xd2, 0x38, + 0xba, 0xa0, 0x85, 0xf2, 0x9b, 0x5b, 0xad, 0xf7, 0x67, 0x3c, 0xce, 0xcf, 0x52, 0x36, 0x38, 0xa0, + 0x05, 0x5e, 0x9d, 0x62, 0x0f, 0x68, 0xa1, 0x82, 0x3f, 0x1b, 0xe0, 0x4d, 0x6e, 0x51, 0x0f, 0x16, + 0x69, 0x1c, 0xee, 0xec, 0x6c, 0x3f, 0x75, 0x89, 0xf7, 0xee, 0xe0, 0xca, 0x81, 0xbe, 0x83, 0xff, + 0x4b, 0x45, 0xa2, 0x31, 0x95, 0x6c, 0x58, 0xb0, 0x2c, 0x89, 0xd4, 0x39, 0x09, 0x77, 0x76, 0xa3, + 0x27, 0x8f, 0xbf, 0x09, 0x1d, 0xb1, 0x7b, 0x77, 0xf0, 0x86, 0x54, 0xe4, 0xb4, 0x8a, 0x38, 0xb1, + 0x01, 0xe6, 0x1e, 0x85, 0xb0, 0x4e, 0x07, 0xf1, 0x0c, 0x5c, 0x84, 0x3b, 0xbb, 0x96, 0x2b, 0x83, + 0x43, 0xf6, 0x76, 0x82, 0x3c, 0x0e, 0x77, 0x76, 0x5f, 0x00, 0x74, 0x2f, 0x68, 0x61, 0x25, 0x14, + 0x84, 0xd0, 0x3d, 0xa0, 0xc5, 0x29, 0x49, 0x73, 0x3a, 0x67, 0xbc, 0xeb, 0xd0, 0x1e, 0x9b, 0xab, + 0x72, 0xbe, 0xce, 0x08, 0xfe, 0x68, 0x42, 0xb7, 0x9a, 0x14, 0xfa, 0x1e, 0x3c, 0xf3, 0x31, 0x17, + 0xd6, 0xb8, 0x69, 0xc0, 0x55, 0x2e, 0x6c, 0x2a, 0x70, 0x59, 0x31, 0x80, 0x62, 0x49, 0x46, 0x74, + 0x2e, 0x69, 0xc5, 0x78, 0x78, 0xb3, 0x44, 0xec, 0xc1, 0x81, 0xec, 0x78, 0x71, 0xed, 0x2b, 0xa8, + 0x07, 0x5d, 0x21, 0xe9, 0x98, 0xf1, 0x5c, 0x39, 0x26, 0xf0, 0xc4, 0xee, 0xbd, 0x81, 0xb5, 0x2b, + 0xd0, 0x7a, 0xe3, 0x9e, 0x6b, 0xfc, 0xab, 0x7a, 0xe3, 0x4b, 0xe1, 0x46, 0xdf, 0xed, 0xce, 0x8f, + 0x2c, 0x61, 0x9a, 0xa4, 0x69, 0xe1, 0xaa, 0x28, 0x09, 0x79, 0xd6, 0xfc, 0xb6, 0x11, 0xbc, 0x85, + 0xee, 0x51, 0xae, 0x89, 0x66, 0x3c, 0xab, 0x29, 0xbe, 0x71, 0x6b, 0xc5, 0x3f, 0x86, 0xb6, 0x90, + 0x9c, 0x0f, 0xcb, 0xcc, 0xbd, 0xfe, 0x64, 0x51, 0x8f, 0x88, 0x38, 0xa4, 0x64, 0xb8, 0x9f, 0x0d, + 0xd2, 0x5c, 0x31, 0x9e, 0x61, 0x17, 0x18, 0x30, 0x58, 0x7b, 0x45, 0xb5, 0x23, 0x81, 0xfe, 0x92, + 0x53, 0xa5, 0xd1, 0x26, 0x2c, 0xe6, 0x8a, 0xca, 0x88, 0xc5, 0x65, 0x53, 0x1d, 0x63, 0xee, 0xc7, + 0xe8, 0x7f, 0xd0, 0x21, 0x42, 0x18, 0x7f, 0xd3, 0xfa, 0xdb, 0x44, 0x88, 0xfd, 0x18, 0x7d, 0x06, + 0x6b, 0x43, 0x26, 0x95, 0x8e, 0xb4, 0xa4, 0x34, 0x52, 0xec, 0x92, 0x5a, 0xda, 0x5a, 0x78, 0xc5, + 0xba, 0x5f, 0x4b, 0x4a, 0x4f, 0xd8, 0x25, 0x0d, 0xfe, 0x69, 0xc2, 0xdd, 0x69, 0x2e, 0x25, 0x78, + 0xa6, 0x28, 0xfa, 0x04, 0xbc, 0xb1, 0x1c, 0x46, 0xae, 0x6a, 0x27, 0x9e, 0xee, 0x58, 0x0e, 0x8f, + 0x8d, 0x3d, 0xbb, 0xc0, 0xcd, 0x8f, 0x59, 0x60, 0xf4, 0x14, 0x20, 0xa5, 0xa4, 0x4a, 0xd0, 0xba, + 0x91, 0x16, 0xcf, 0x44, 0xbb, 0xec, 0x5f, 0x40, 0x4b, 0x8d, 0xa4, 0xbf, 0x60, 0x31, 0x9b, 0x53, + 0x8c, 0x63, 0xfd, 0x88, 0x08, 0xcc, 0xb9, 0xc6, 0x26, 0x06, 0x85, 0xd0, 0x4d, 0x79, 0x12, 0x49, + 0xce, 0xb5, 0xdf, 0x9e, 0x1f, 0x7f, 0xc8, 0x13, 0x1b, 0xbf, 0x98, 0xba, 0x03, 0xfa, 0x1c, 0xd6, + 0x0c, 0x66, 0xc0, 0x33, 0xc5, 0x94, 0x36, 0xad, 0xf8, 0x9d, 0xad, 0xd6, 0xa3, 0x65, 0xbc, 0x9a, + 0xf2, 0xe4, 0xe5, 0xd4, 0x8b, 0x1e, 0xc2, 0x8a, 0x09, 0x64, 0x55, 0x8d, 0xfe, 0xa2, 0x0d, 0x5b, + 0x4e, 0x79, 0x32, 0xa9, 0xdb, 0xbc, 0x18, 0x9b, 0x87, 0x4c, 0x39, 0x76, 0xf7, 0x98, 0xd2, 0xfc, + 0x03, 0x06, 0xba, 0x0e, 0x6d, 0xa5, 0x89, 0xd4, 0x96, 0xdb, 0x16, 0x76, 0x86, 0x19, 0x89, 0x20, + 0x49, 0x6d, 0x92, 0x6d, 0xdc, 0x35, 0x0e, 0x33, 0xc4, 0x9a, 0x06, 0x16, 0x6e, 0xd0, 0x40, 0x7b, + 0x9e, 0x06, 0x7e, 0x05, 0xff, 0xdd, 0x2a, 0x4b, 0x29, 0xbc, 0x80, 0x8e, 0xdd, 0x08, 0xe5, 0x37, + 0xec, 0x1e, 0x7f, 0x79, 0xfd, 0xa8, 0xaf, 0xca, 0x08, 0x97, 0x48, 0x74, 0x1f, 0x20, 0xa3, 0x6f, + 0x75, 0x54, 0x6f, 0xcb, 0x33, 0x9e, 0x13, 0xe3, 0x08, 0xfe, 0x6a, 0x00, 0x72, 0x3f, 0x2c, 0xff, + 0x85, 0xe2, 0xd1, 0x1e, 0x2c, 0x53, 0x93, 0x27, 0x2a, 0x17, 0xda, 0x49, 0xe9, 0xd3, 0xeb, 0xfb, + 0xaa, 0xfd, 0xf2, 0xe1, 0x25, 0x3a, 0x35, 0x82, 0x9f, 0xe1, 0xde, 0x4c, 0xdd, 0x25, 0x65, 0xcf, + 0xab, 0x7d, 0x77, 0x4f, 0xc5, 0x6d, 0x18, 0x2b, 0xf7, 0xff, 0xf7, 0x06, 0xdc, 0x7b, 0x45, 0x75, + 0xf5, 0xfa, 0xa8, 0x8a, 0x92, 0x75, 0x68, 0x53, 0xc1, 0x07, 0xe7, 0xf6, 0xcb, 0x2d, 0xec, 0x8c, + 0x79, 0x8d, 0x37, 0xe7, 0x35, 0x7e, 0x1f, 0xc0, 0x4a, 0x48, 0xf3, 0x0b, 0x9a, 0x59, 0x6e, 0x3c, + 0x6c, 0x45, 0xf5, 0xda, 0x38, 0x66, 0x15, 0xb6, 0x30, 0xab, 0xb0, 0xe0, 0xef, 0x26, 0xac, 0xcf, + 0x56, 0x54, 0x36, 0x3b, 0xbf, 0xa4, 0x72, 0x4b, 0x9b, 0xb7, 0xdc, 0xd2, 0xd6, 0xc7, 0x6f, 0xe9, + 0xc2, 0x87, 0x6d, 0x69, 0xfb, 0xdd, 0x2d, 0x45, 0xcf, 0xc1, 0x1b, 0x55, 0x7d, 0xd9, 0x6d, 0x7f, + 0xef, 0xf3, 0x5e, 0x51, 0x80, 0xa7, 0x20, 0x33, 0x01, 0x2b, 0xf0, 0x1a, 0xbd, 0x8b, 0x96, 0xde, + 0x15, 0xe3, 0x3e, 0xae, 0x28, 0x3e, 0xeb, 0xd8, 0xff, 0xc0, 0x9e, 0xfc, 0x1b, 0x00, 0x00, 0xff, + 0xff, 0xbd, 0x88, 0x8a, 0x70, 0xff, 0x09, 0x00, 0x00, } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto index f406f5c8e..2308439b4 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto @@ -169,7 +169,7 @@ message ListEntryHistoryRequest { // app_id is the identifier for the application. string app_id = 4; // first_tree_size is the tree_size of the currently trusted log root. - // Omitting this field will ommit the log consistency proof from the response. + // Omitting this field will omit the log consistency proof from the response. int64 first_tree_size = 5; } @@ -196,7 +196,7 @@ message UpdateEntryRequest { } // UpdateEntryResponse contains a proof once the update has been included in -// the Merkel Tree. +// the Merkle Tree. message UpdateEntryResponse { // proof contains a proof that the update has been included in the tree. GetEntryResponse proof = 1; @@ -251,3 +251,33 @@ message GetDomainInfoResponse { // Vrf contains the VRF public key. keyspb.PublicKey vrf = 3; } + +// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. +message GetMonitoringRequest { + // start specifies the start epoch number from which monitoring results will + // be returned (ranging from [start, latestObserved] and starting at 1). + int64 start = 1; +} + +message GetMonitoringResponse { + // smr contains the map root for the sparse Merkle Tree signed with the + // monitor's key on success. If the checks were not successful the + // smr will be empty. The epochs are encoded into the smr map_revision. + trillian.SignedMapRoot smr = 1; + + // + // The following fields provide more information about each failure in this + // response, if any. + // + + // isValid signals if all verification steps for the requested epoch passed + // or not. + bool isValid = 2; + // invalidRootSig contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + trillian.SignedMapRoot invalidRootSig = 3; + // TODO(ismail): add field for the following cases: + // - Invalid mutation from epoch e to e+1 + // - Set of mutations does not produce new map root +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 861bf56ce..5aec32f19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -147,3 +147,15 @@ services: MIN_SIGN_PERIOD: 5s MAX_SIGN_PERIOD: 5m VERBOSITY: 5 + + kt-monitor: + depends_on: + - kt-server + - kt-signer + build: + context: .. + dockerfile: ./keytransparency/cmd/keytransparency-monitor/Dockerfile + image: us.gcr.io/key-transparency/keytransparency-monitor + restart: always + ports: + - "8099:8099" # gRPC / HTTPS diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go new file mode 100644 index 000000000..9e0f21e64 --- /dev/null +++ b/impl/monitor/monitor.go @@ -0,0 +1,186 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package monitor implements the monitor service. A monitor repeatedly polls a +// key-transparency server's Mutations API and signs Map Roots if it could +// reconstruct +// clients can query. +package monitor + +import ( + "time" + + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + + "github.com/google/trillian" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + tv "github.com/google/keytransparency/core/tree/sparse/verifier" + + mspb "github.com/google/keytransparency/impl/proto/monitor_v1_service" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" + + "bytes" + "github.com/google/keytransparency/core/tree/sparse" +) + +// Each page contains pageSize profiles. Each profile contains multiple +// keys. Assuming 2 keys per profile (each of size 2048-bit), a page of +// size 16 will contain about 8KB of data. +const pageSize = 16 + +// Server holds internal state for the monitor server. +type server struct { + client mupb.MutationServiceClient + pollPeriod time.Duration + + tree *tv.Verifier + // TODO(ismail) abstract this into a storage interface and have an in-memory version + seenSMRs []*trillian.SignedMapRoot + reconstructedSMRs []*trillian.SignedMapRoot +} + +// New creates a new instance of the monitor server. +func New(cli mupb.MutationServiceClient, mapID int64, poll time.Duration) *server { + return &server{ + client: cli, + pollPeriod: poll, + // TODO TestMapHasher (maphasher.Default) does not implement sparse.TreeHasher: + tree: tv.New(mapID, sparse.CONIKSHasher), + seenSMRs: make([]*trillian.SignedMapRoot, 256), + reconstructedSMRs: make([]*trillian.SignedMapRoot, 256), + } +} + +func (s *server) StartPolling() error { + t := time.NewTicker(s.pollPeriod) + for now := range t.C { + glog.Infof("Polling: %v", now) + ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) + if _, err := s.pollMutations(ctx); err != nil { + glog.Errorf("pollMutations(_): %v", err) + } + } + return nil +} + +// GetSignedMapRoot returns the latest reconstructed using the Mutations API and +// validated signed map root. +func (s *server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { + return &ktpb.GetMonitoringResponse{ + Smr: s.lastSMR(), + }, nil +} + +// GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. +func (s *server) GetSignedMapRootStream(in *ktpb.GetMonitoringRequest, stream mspb.MonitorService_GetSignedMapRootStreamServer) error { + // TODO(ismail): implement stream API + return grpc.Errorf(codes.Unimplemented, "GetSignedMapRootStream is unimplemented") +} + +func (s *server) GetSignedMapRootByRevision(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { + // TODO(ismail): implement by revision API + return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") +} + +func (s *server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { + req := &ktpb.GetMutationsRequest{PageSize: pageSize, Epoch: s.nextRevToQuery()} + resp, err := s.client.GetMutations(ctx, req, opts...) + if err != nil { + return nil, err + } + + // TODO(ismail): remember when we've actually requested and seen this SMR! + // publish delta (seen - actual) + if got, want := resp.GetSmr(), s.lastSeenSMR(); bytes.Equal(got.GetRootHash(), want.GetRootHash()) && + got.GetMapRevision() == want.GetMapRevision() { + // We already processed this SMR. Do not update seen SMRs. Do not scroll + // pages for further mutations. Return empty mutations list. + glog.Infof("Already processed this SMR with revision %v. Continuing.", got.GetMapRevision()) + return nil, nil + } + + mutations := make([]*ktpb.Mutation, pageSize*2) + mutations = append(mutations, resp.GetMutations()...) + s.pageMutations(ctx, resp, mutations, opts) + + // update seen SMRs: + s.seenSMRs = append(s.seenSMRs, resp.GetSmr()) + + // TODO(ismail): + // For each received mutation in epoch e: + // Verify that the provided leaf’s inclusion proof goes to epoch e -1. + // Verify the mutation’s validity against the previous leaf. + // Compute the new leaf and store the intermediate hashes locally. + // Compute the new root using local intermediate hashes from epoch e. + for _, m := range mutations { + idx := m.GetProof().GetLeaf().GetIndex() + nbrs := m.GetProof().GetInclusion() + if err := s.tree.VerifyProof(nbrs, idx, m.GetProof().GetLeaf().GetLeafValue(), + sparse.FromBytes(resp.GetSmr().GetRootHash())); err != nil { + glog.Errorf("VerifyProof(): %v", err) + // TODO return nil, err + } + } + + // TODO(ismail): sign and update reconstructedSMRs + // here we just add the kt-server signed SMR: + glog.Errorf("Got reponse: %v", resp.GetSmr()) + s.reconstructedSMRs = append(s.reconstructedSMRs, resp.GetSmr()) + + return mutations, nil +} + +// pageMutations iterates/pages through all mutations in the case there were +// more then maximum pageSize mutations in between epochs. +// It will modify the passed GetMutationsResponse resp and the passed list of +// mutations ms. +func (s *server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsResponse, + ms []*ktpb.Mutation, opts ...grpc.CallOption) error { + // Query all mutations in the current epoch + for resp.GetNextPageToken() != "" { + req := &ktpb.GetMutationsRequest{PageSize: pageSize} + resp, err := s.client.GetMutations(ctx, req, opts...) + if err != nil { + return err + } + ms = append(ms, resp.GetMutations()...) + } + return nil +} + +func (s *server) lastSeenSMR() *trillian.SignedMapRoot { + if len(s.seenSMRs) > 0 { + return s.seenSMRs[len(s.seenSMRs)-1] + } + return nil +} + +func (s *server) lastSMR() *trillian.SignedMapRoot { + if len(s.reconstructedSMRs) > 0 { + return s.reconstructedSMRs[len(s.reconstructedSMRs)-1] + } + return nil +} + +func (s *server) nextRevToQuery() int64 { + smr := s.lastSeenSMR() + if smr == nil { + return 1 + } + return smr.GetMapRevision() + 1 +} diff --git a/impl/monitor/monitor_test.go b/impl/monitor/monitor_test.go new file mode 100644 index 000000000..aff2c0091 --- /dev/null +++ b/impl/monitor/monitor_test.go @@ -0,0 +1,24 @@ +package monitor + +import ( + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "testing" +) + +func TestGetSignedMapRoot(t *testing.T) { + srv := server{} + _, err := srv.GetSignedMapRoot(context.TODO(), nil) + if got, want := grpc.Code(err), codes.Unimplemented; got != want { + t.Errorf("GetSignedMapRootStream(_, _): %v, want %v", got, want) + } +} + +func TestGetSignedMapRootStream(t *testing.T) { + srv := server{} + err := srv.GetSignedMapRootStream(nil, nil) + if got, want := grpc.Code(err), codes.Unimplemented; got != want { + t.Errorf("GetSignedMapRootStream(_, _): %v, want %v", got, want) + } +} diff --git a/impl/mutation/mutation.go b/impl/mutation/mutation.go index 9fae43072..8b816ef12 100644 --- a/impl/mutation/mutation.go +++ b/impl/mutation/mutation.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package mutation implements the monitor service. +// Package mutation implements the mutations service a monitor can query. package mutation import ( diff --git a/impl/proto/keytransparency_v1_service/gen.go b/impl/proto/keytransparency_v1_service/gen.go index e0bf325dd..3aa740059 100644 --- a/impl/proto/keytransparency_v1_service/gen.go +++ b/impl/proto/keytransparency_v1_service/gen.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --go_out=,plugins=grpc:. keytransparency_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --go_out=,plugins=grpc:. keytransparency_v1_service.proto -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --grpc-gateway_out=logtostderr=true:. keytransparency_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --grpc-gateway_out=logtostderr=true:. keytransparency_v1_service.proto package keytransparency_v1_service diff --git a/impl/proto/monitor_v1_service/gen.go b/impl/proto/monitor_v1_service/gen.go new file mode 100644 index 000000000..66b564cb3 --- /dev/null +++ b/impl/proto/monitor_v1_service/gen.go @@ -0,0 +1,19 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --go_out=,plugins=grpc:. monitor_v1_service.proto + +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --grpc-gateway_out=logtostderr=true:. monitor_v1_service.proto + +package monitor_v1_service diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go new file mode 100644 index 000000000..2cd4ab947 --- /dev/null +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go @@ -0,0 +1,226 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: monitor_v1_service.proto + +/* +Package monitor_v1_service is a generated protocol buffer package. + +TODO(ismail): detailed comment + +It is generated from these files: + monitor_v1_service.proto + +It has these top-level messages: +*/ +package monitor_v1_service + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import keytransparency_v1_types "github.com/google/keytransparency/core/proto/keytransparency_v1_types" +import _ "google.golang.org/genproto/googleapis/api/annotations" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for MonitorService service + +type MonitorServiceClient interface { + GetSignedMapRoot(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootStream(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (MonitorService_GetSignedMapRootStreamClient, error) +} + +type monitorServiceClient struct { + cc *grpc.ClientConn +} + +func NewMonitorServiceClient(cc *grpc.ClientConn) MonitorServiceClient { + return &monitorServiceClient{cc} +} + +func (c *monitorServiceClient) GetSignedMapRoot(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) { + out := new(keytransparency_v1_types.GetMonitoringResponse) + err := grpc.Invoke(ctx, "/monitor.v1.service.MonitorService/GetSignedMapRoot", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *monitorServiceClient) GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) { + out := new(keytransparency_v1_types.GetMonitoringResponse) + err := grpc.Invoke(ctx, "/monitor.v1.service.MonitorService/GetSignedMapRootByRevision", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *monitorServiceClient) GetSignedMapRootStream(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (MonitorService_GetSignedMapRootStreamClient, error) { + stream, err := grpc.NewClientStream(ctx, &_MonitorService_serviceDesc.Streams[0], c.cc, "/monitor.v1.service.MonitorService/GetSignedMapRootStream", opts...) + if err != nil { + return nil, err + } + x := &monitorServiceGetSignedMapRootStreamClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type MonitorService_GetSignedMapRootStreamClient interface { + Recv() (*keytransparency_v1_types.GetMonitoringResponse, error) + grpc.ClientStream +} + +type monitorServiceGetSignedMapRootStreamClient struct { + grpc.ClientStream +} + +func (x *monitorServiceGetSignedMapRootStreamClient) Recv() (*keytransparency_v1_types.GetMonitoringResponse, error) { + m := new(keytransparency_v1_types.GetMonitoringResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for MonitorService service + +type MonitorServiceServer interface { + GetSignedMapRoot(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootByRevision(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootStream(*keytransparency_v1_types.GetMonitoringRequest, MonitorService_GetSignedMapRootStreamServer) error +} + +func RegisterMonitorServiceServer(s *grpc.Server, srv MonitorServiceServer) { + s.RegisterService(&_MonitorService_serviceDesc, srv) +} + +func _MonitorService_GetSignedMapRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(keytransparency_v1_types.GetMonitoringRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MonitorServiceServer).GetSignedMapRoot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/monitor.v1.service.MonitorService/GetSignedMapRoot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MonitorServiceServer).GetSignedMapRoot(ctx, req.(*keytransparency_v1_types.GetMonitoringRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MonitorService_GetSignedMapRootByRevision_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(keytransparency_v1_types.GetMonitoringRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MonitorServiceServer).GetSignedMapRootByRevision(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/monitor.v1.service.MonitorService/GetSignedMapRootByRevision", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MonitorServiceServer).GetSignedMapRootByRevision(ctx, req.(*keytransparency_v1_types.GetMonitoringRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MonitorService_GetSignedMapRootStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(keytransparency_v1_types.GetMonitoringRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MonitorServiceServer).GetSignedMapRootStream(m, &monitorServiceGetSignedMapRootStreamServer{stream}) +} + +type MonitorService_GetSignedMapRootStreamServer interface { + Send(*keytransparency_v1_types.GetMonitoringResponse) error + grpc.ServerStream +} + +type monitorServiceGetSignedMapRootStreamServer struct { + grpc.ServerStream +} + +func (x *monitorServiceGetSignedMapRootStreamServer) Send(m *keytransparency_v1_types.GetMonitoringResponse) error { + return x.ServerStream.SendMsg(m) +} + +var _MonitorService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "monitor.v1.service.MonitorService", + HandlerType: (*MonitorServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetSignedMapRoot", + Handler: _MonitorService_GetSignedMapRoot_Handler, + }, + { + MethodName: "GetSignedMapRootByRevision", + Handler: _MonitorService_GetSignedMapRootByRevision_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetSignedMapRootStream", + Handler: _MonitorService_GetSignedMapRootStream_Handler, + ServerStreams: true, + }, + }, + Metadata: "monitor_v1_service.proto", +} + +func init() { proto.RegisterFile("monitor_v1_service.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 286 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x91, 0x31, 0x4a, 0xfc, 0x40, + 0x14, 0x87, 0xc9, 0xff, 0x0f, 0x16, 0x29, 0x44, 0x06, 0x59, 0x24, 0xa4, 0xda, 0x03, 0xcc, 0x18, + 0xed, 0x2c, 0x6d, 0xb6, 0xda, 0x26, 0x39, 0xc0, 0xf2, 0x92, 0x7d, 0xc4, 0xc1, 0xcd, 0xbc, 0x71, + 0xde, 0xdb, 0x81, 0x20, 0x36, 0xde, 0x40, 0xac, 0x2c, 0x3d, 0x93, 0x57, 0xd8, 0x83, 0xc8, 0x26, + 0x29, 0x24, 0x20, 0xd8, 0x88, 0xf5, 0x37, 0xfc, 0xbe, 0x6f, 0x66, 0xd2, 0x8b, 0x8e, 0x9c, 0x15, + 0x0a, 0x9b, 0x58, 0x6c, 0x18, 0x43, 0xb4, 0x0d, 0x6a, 0x1f, 0x48, 0x48, 0xa9, 0x89, 0xe8, 0x58, + 0xe8, 0x89, 0x64, 0xdb, 0xd6, 0xca, 0xdd, 0xbe, 0xd6, 0x0d, 0x75, 0xa6, 0x25, 0x6a, 0x77, 0x68, + 0xee, 0xb1, 0x97, 0x00, 0x8e, 0x3d, 0x04, 0x74, 0x4d, 0x6f, 0x1a, 0x0a, 0x68, 0x86, 0x85, 0x39, + 0x3a, 0x2a, 0xa4, 0xf7, 0xc8, 0xdf, 0x82, 0xd1, 0x9c, 0xe5, 0xd3, 0x34, 0x78, 0x6b, 0xc0, 0x39, + 0x12, 0x10, 0x4b, 0x6e, 0xa2, 0x57, 0x87, 0xff, 0xe9, 0xe9, 0x7a, 0x4c, 0xab, 0xc6, 0x2c, 0xf5, + 0x92, 0xa4, 0x67, 0x2b, 0x94, 0xca, 0xb6, 0x0e, 0xb7, 0x6b, 0xf0, 0x25, 0x91, 0x28, 0xad, 0x67, + 0x9a, 0xe3, 0x45, 0x46, 0xcd, 0x0a, 0x65, 0x5a, 0xb0, 0xae, 0x2d, 0xf1, 0x61, 0x8f, 0x2c, 0x99, + 0xf9, 0xf1, 0x79, 0xf6, 0xe4, 0x18, 0x97, 0xf9, 0xf3, 0xc7, 0xe1, 0xf5, 0xdf, 0x42, 0x9d, 0x9b, + 0x58, 0x98, 0x0e, 0xbc, 0x09, 0x44, 0xc2, 0x37, 0x3b, 0x10, 0x64, 0x51, 0xef, 0x49, 0x9a, 0xcd, + 0x9b, 0x6e, 0xfb, 0x12, 0xa3, 0x65, 0x4b, 0xee, 0xf7, 0xeb, 0x96, 0x43, 0x5d, 0xae, 0x32, 0x13, + 0x8b, 0x1a, 0x05, 0xbe, 0x24, 0x9a, 0x47, 0x16, 0x08, 0xf2, 0xa4, 0xde, 0x92, 0x74, 0x31, 0x6f, + 0xac, 0x24, 0x20, 0x74, 0x7f, 0xf6, 0x7a, 0x3c, 0xe8, 0x2f, 0x93, 0xfa, 0x64, 0xf8, 0xed, 0xeb, + 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x4b, 0x95, 0x94, 0xa1, 0x02, 0x00, 0x00, +} diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go new file mode 100644 index 000000000..1d345a4c8 --- /dev/null +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go @@ -0,0 +1,231 @@ +// Code generated by protoc-gen-grpc-gateway +// source: monitor_v1_service.proto +// DO NOT EDIT! + +/* +Package monitor_v1_service is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package monitor_v1_service + +import ( + "io" + "net/http" + + "github.com/golang/protobuf/proto" + "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" +) + +var _ codes.Code +var _ io.Reader +var _ = runtime.String +var _ = utilities.NewDoubleArray + +var ( + filter_MonitorService_GetSignedMapRoot_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_MonitorService_GetSignedMapRoot_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq keytransparency_v1_types.GetMonitoringRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_MonitorService_GetSignedMapRoot_0); err != nil { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetSignedMapRoot(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func request_MonitorService_GetSignedMapRootByRevision_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq keytransparency_v1_types.GetMonitoringRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["start"] + if !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", "start") + } + + protoReq.Start, err = runtime.Int64(val) + + if err != nil { + return nil, metadata, err + } + + msg, err := client.GetSignedMapRootByRevision(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +var ( + filter_MonitorService_GetSignedMapRootStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_MonitorService_GetSignedMapRootStream_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (MonitorService_GetSignedMapRootStreamClient, runtime.ServerMetadata, error) { + var protoReq keytransparency_v1_types.GetMonitoringRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_MonitorService_GetSignedMapRootStream_0); err != nil { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetSignedMapRootStream(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +// RegisterMonitorServiceHandlerFromEndpoint is same as RegisterMonitorServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterMonitorServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterMonitorServiceHandler(ctx, mux, conn) +} + +// RegisterMonitorServiceHandler registers the http handlers for service MonitorService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterMonitorServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + client := NewMonitorServiceClient(conn) + + mux.Handle("GET", pattern_MonitorService_GetSignedMapRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, req) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + } + resp, md, err := request_MonitorService_GetSignedMapRoot_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + return + } + + forward_MonitorService_GetSignedMapRoot_0(ctx, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_MonitorService_GetSignedMapRootByRevision_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, req) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + } + resp, md, err := request_MonitorService_GetSignedMapRootByRevision_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + return + } + + forward_MonitorService_GetSignedMapRootByRevision_0(ctx, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_MonitorService_GetSignedMapRootStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, req) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + } + resp, md, err := request_MonitorService_GetSignedMapRootStream_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, outboundMarshaler, w, req, err) + return + } + + forward_MonitorService_GetSignedMapRootStream_0(ctx, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_MonitorService_GetSignedMapRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "latest")) + + pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1beta1", "map", "roots", "start"}, "")) + + pattern_MonitorService_GetSignedMapRootStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "stream")) +) + +var ( + forward_MonitorService_GetSignedMapRoot_0 = runtime.ForwardResponseMessage + + forward_MonitorService_GetSignedMapRootByRevision_0 = runtime.ForwardResponseMessage + + forward_MonitorService_GetSignedMapRootStream_0 = runtime.ForwardResponseStream +) diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.proto b/impl/proto/monitor_v1_service/monitor_v1_service.proto new file mode 100644 index 000000000..db34dc4cd --- /dev/null +++ b/impl/proto/monitor_v1_service/monitor_v1_service.proto @@ -0,0 +1,56 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// Monitor Service +// +// The Key Transparency monitor server service consists of APIs to fetch +// monitor results queried using the mutations API. +package monitor.v1.service; + +import "github.com/google/keytransparency/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto"; +import "google/api/annotations.proto"; + +// The Monitor Service API allows clients to query the monitors observed and +// validated signed map roots. +// +// - Signed Map Roots can be collected using the GetSignedMapRoot APIs. +// - Monitor resources are named: +// /v1/map/roots/* /v1/map/roots:latest and v1/map/roots:stream. +// +service MonitorService { + // GetSignedMapRoot returns the latest valid signed map root the monitor + // observed. + // + // Returns the signed map root for the latest epoch the monitor observed. If + // the monitor could not reconstruct the map root given the set of mutations + // from the previous to the current epoch it won't sign the map root. + rpc GetSignedMapRoot(keytransparency.v1.types.GetMonitoringRequest) + returns (keytransparency.v1.types.GetMonitoringResponse) { + option (google.api.http) = { get: "/v1/map/roots:latest" }; + } + // TODO(ismail): comments + rpc GetSignedMapRootByRevision(keytransparency.v1.types.GetMonitoringRequest) + returns(keytransparency.v1.types.GetMonitoringResponse) { + option (google.api.http) = { get: "/v1/map/roots/{start}" }; + } + + rpc GetSignedMapRootStream(keytransparency.v1.types.GetMonitoringRequest) + returns (stream keytransparency.v1.types.GetMonitoringResponse) { + option (google.api.http) = { get: "/v1/map/roots:stream" }; + } +} + + diff --git a/impl/proto/mutation_v1_service/gen.go b/impl/proto/mutation_v1_service/gen.go index 4816f1586..6d15ee54e 100644 --- a/impl/proto/mutation_v1_service/gen.go +++ b/impl/proto/mutation_v1_service/gen.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --go_out=,plugins=grpc:. mutation_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --go_out=,plugins=grpc:. mutation_v1_service.proto -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --grpc-gateway_out=logtostderr=true:. mutation_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --grpc-gateway_out=logtostderr=true:. mutation_v1_service.proto package mutation_v1_service From f681eb8f46f1f196df3fc31ff87d7674254ae4b1 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 28 Jul 2017 10:43:17 +0100 Subject: [PATCH 02/46] revert local changes, add TODOs simplify monitor Dockerfile (non-opinionated) add argument to 'prepare script' such that the monitor can contact the kt-server if it isn't reachable via localhost add proto messages that proof certain errors occurred early review comments add signing capability move verification into separate function gofmt golint / presubmit.sh regenerate proto with correct dependency versions add script for generating monitor signing key Add comments to exported methods Add "observed at" timestamp, sign the root hash update test --- cmd/keytransparency-monitor/Dockerfile | 33 +- cmd/keytransparency-monitor/main.go | 22 +- core/proto/keytransparency_v1_types/gen.go | 2 +- .../keytransparency_v1_types.pb.go | 295 ++++++++++++++---- .../keytransparency_v1_types.proto | 42 ++- docker-compose.yml | 12 + impl/monitor/monitor.go | 153 ++++++--- impl/monitor/monitor_test.go | 26 +- .../monitor_v1_service.pb.go | 79 +++-- .../monitor_v1_service.pb.gw.go | 2 +- .../monitor_v1_service.proto | 18 +- scripts/gen_monitor_keys.sh | 48 +++ 12 files changed, 548 insertions(+), 184 deletions(-) create mode 100644 scripts/gen_monitor_keys.sh diff --git a/cmd/keytransparency-monitor/Dockerfile b/cmd/keytransparency-monitor/Dockerfile index e62112ca7..691703340 100644 --- a/cmd/keytransparency-monitor/Dockerfile +++ b/cmd/keytransparency-monitor/Dockerfile @@ -1,24 +1,5 @@ FROM golang -ENV HOST=0.0.0.0 \ - RPC_PORT=8099 - -# TLS Certificate needs 0.0.0.0 to be in the SAN IP field. -ENV VRF_PUB=keytransparency/genfiles/vrf-key.pem \ - TLS_KEY_PATH=genfiles/server.key \ - TLS_CRT_PATH=genfiles/server.crt - -ENV KT_URL=kt-server:8080 - -ENV MAP_ID=0 \ - MAP_URL="" -ENV LOG_ID=0 \ - LOG_URL=localhost:8090 -ENV MONITOR_SIGN_KEY=TODO \ - POLL_PERIOD=5s - -ENV VERBOSITY=1 - ADD keytransparency/genfiles/* /kt/ ADD ./keytransparency /go/src/github.com/google/keytransparency ADD ./trillian /go/src/github.com/google/trillian @@ -27,16 +8,6 @@ WORKDIR /go/src/github.com/google/keytransparency RUN apt-get update && apt-get install -y libtool libltdl-dev RUN go get -tags="mysql" ./cmd/keytransparency-monitor -ENTRYPOINT /go/bin/keytransparency-monitor \ - --addr="$HOST:$RPC_PORT" --kt-url="$KT_URL" --poll-period="$POLL_PERIOD" \ - --vrf="$VRF_PUB" \ - --key="$TLS_KEY_PATH" --cert="$TLS_CRT_PATH" \ - --log-id="$LOG_ID" --log-key="$LOG_PUB_KEY" \ - --map-id="$MAP_ID" \ - --alsologtostderr \ - --v=${VERBOSITY} - -EXPOSE $RPC_PORT +ENTRYPOINT ["/go/bin/keytransparency-monitor"] -#HEALTHCHECK --interval=5m --timeout=3s \ -# CMD curl -f http://localhost:$RPC_PORT/TODO || exit 1 +EXPOSE 8099 diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index fe1e256e4..bb9b626e1 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -26,6 +26,8 @@ import ( "github.com/golang/glog" "github.com/google/keytransparency/impl/monitor" + "github.com/google/trillian/crypto" + "github.com/google/trillian/crypto/keys" "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" "golang.org/x/net/context" @@ -35,16 +37,18 @@ import ( ) var ( - addr = flag.String("addr", ":8099", "The ip:port combination to listen on") - keyFile = flag.String("key", "genfiles/server.key", "TLS private key file") - certFile = flag.String("cert", "genfiles/server.pem", "TLS cert file") + addr = flag.String("addr", ":8099", "The ip:port combination to listen on") + keyFile = flag.String("key", "genfiles/server.key", "TLS private key file") + certFile = flag.String("cert", "genfiles/server.pem", "TLS cert file") + + signingKey = flag.String("sign-key", "genfiles/p256-key.pem", "Path to private key PEM for SMH signing") + signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") - // TODO(ismail): are the IDs actually needed for verification operations? + // TODO(ismail): remove mapID mapID = flag.Int64("map-id", 0, "Trillian map ID") - logID = flag.Int64("log-id", 0, "Trillian Log ID") // TODO(ismail): expose prometheus metrics: a variable that tracks valid/invalid MHs metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") @@ -101,7 +105,13 @@ func main() { } mcc := mupb.NewMutationServiceClient(grpcc) - srv := monitor.New(mcc, *mapID, *pollPeriod) + // Read signing key: + key, err := keys.NewFromPrivatePEMFile(*signingKey, *signingKeyPassword) + if err != nil { + glog.Fatalf("Could not create signer from %v: %v", *signingKey, err) + } + + srv := monitor.New(mcc, *crypto.NewSHA256Signer(key), *mapID, *pollPeriod) mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) diff --git a/core/proto/keytransparency_v1_types/gen.go b/core/proto/keytransparency_v1_types/gen.go index 38cf707a6..872643e35 100644 --- a/core/proto/keytransparency_v1_types/gen.go +++ b/core/proto/keytransparency_v1_types/gen.go @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ -I=$GOPATH/src/github.com/google/trillian/ --go_out=:. keytransparency_v1_types.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis --go_out=:. keytransparency_v1_types.proto package keytransparency_v1_types diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go index 4e4873512..2b1537acf 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go @@ -30,16 +30,15 @@ It has these top-level messages: GetMutationsRequest GetMutationsResponse GetMonitoringRequest + InvalidMutation + NotMatchingMapRootProof GetMonitoringResponse - GetDomainInfoRequest - GetDomainInfoResponse */ package keytransparency_v1_types import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" -import keyspb "github.com/google/trillian/crypto/keyspb" import sigpb "github.com/google/trillian/crypto/sigpb" import trillian "github.com/google/trillian" import trillian1 "github.com/google/trillian" @@ -761,6 +760,152 @@ func (m *GetMutationsResponse) GetNextPageToken() string { return "" } +// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. +type GetMonitoringRequest struct { + // start specifies the start epoch number from which monitoring results will + // be returned (ranging from [start, latestObserved] and starting at 1). + Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` +} + +func (m *GetMonitoringRequest) Reset() { *m = GetMonitoringRequest{} } +func (m *GetMonitoringRequest) String() string { return proto.CompactTextString(m) } +func (*GetMonitoringRequest) ProtoMessage() {} +func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +func (m *GetMonitoringRequest) GetStart() int64 { + if m != nil { + return m.Start + } + return 0 +} + +// InvalidMutation includes all information to reproduce that there was an +// invalid mutation from epoch e to e+1. +type InvalidMutation struct { + // old_leaf is the inclusion proof to the leaf at epoch e. + OldLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,1,opt,name=old_leaf,json=oldLeaf" json:"old_leaf,omitempty"` + // new_leaf is the inclusion proof to the leaf at epoch e+1. + NewLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,2,opt,name=new_leaf,json=newLeaf" json:"new_leaf,omitempty"` +} + +func (m *InvalidMutation) Reset() { *m = InvalidMutation{} } +func (m *InvalidMutation) String() string { return proto.CompactTextString(m) } +func (*InvalidMutation) ProtoMessage() {} +func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +func (m *InvalidMutation) GetOldLeaf() *trillian1.MapLeafInclusion { + if m != nil { + return m.OldLeaf + } + return nil +} + +func (m *InvalidMutation) GetNewLeaf() *trillian1.MapLeafInclusion { + if m != nil { + return m.NewLeaf + } + return nil +} + +// NotMatchingMapRootProof contains all data necessary to reproduce that set of +// mutations does not produce new expected map root. +type NotMatchingMapRootProof struct { + // map_root contains the map root hash the monitor observed. + MapRoot *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=map_root,json=mapRoot" json:"map_root,omitempty"` + // old_leafs is a list of inclusion proofs for the leafs in epoch e. + OldLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,2,rep,name=old_leafs,json=oldLeafs" json:"old_leafs,omitempty"` + // new_leafs is a list of inclusion proofs for changed leafs (from epoch e + // to epoch e+1). Hashing these produces a different hash than root hash in + // above's map_root. + NewLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,3,rep,name=new_leafs,json=newLeafs" json:"new_leafs,omitempty"` +} + +func (m *NotMatchingMapRootProof) Reset() { *m = NotMatchingMapRootProof{} } +func (m *NotMatchingMapRootProof) String() string { return proto.CompactTextString(m) } +func (*NotMatchingMapRootProof) ProtoMessage() {} +func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *NotMatchingMapRootProof) GetMapRoot() *trillian.SignedMapRoot { + if m != nil { + return m.MapRoot + } + return nil +} + +func (m *NotMatchingMapRootProof) GetOldLeafs() []*trillian1.MapLeafInclusion { + if m != nil { + return m.OldLeafs + } + return nil +} + +func (m *NotMatchingMapRootProof) GetNewLeafs() []*trillian1.MapLeafInclusion { + if m != nil { + return m.NewLeafs + } + return nil +} + +type GetMonitoringResponse struct { + // smr contains the map root for the sparse Merkle Tree signed with the + // monitor's key on success. If the checks were not successful the + // smr will be empty. The epochs are encoded into the smr map_revision. + Smr *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=smr" json:"smr,omitempty"` + // isValid signals if all verification steps for the requested epoch passed + // or not. + IsValid bool `protobuf:"varint,2,opt,name=isValid" json:"isValid,omitempty"` + // invalidRootSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + InvalidRootSigProof *trillian.SignedMapRoot `protobuf:"bytes,3,opt,name=invalidRootSigProof" json:"invalidRootSigProof,omitempty"` + // invalidMutation contains data to reproduce that there was an invalid + // mutation from epoch e to epoch e+1 + InvalidMutation *InvalidMutation `protobuf:"bytes,4,opt,name=invalidMutation" json:"invalidMutation,omitempty"` + // NotMatchingMapRoot contains all data to reproduce that the set of mutations + // does not produce observed new map root. + NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,5,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` +} + +func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } +func (m *GetMonitoringResponse) String() string { return proto.CompactTextString(m) } +func (*GetMonitoringResponse) ProtoMessage() {} +func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { + if m != nil { + return m.Smr + } + return nil +} + +func (m *GetMonitoringResponse) GetIsValid() bool { + if m != nil { + return m.IsValid + } + return false +} + +func (m *GetMonitoringResponse) GetInvalidRootSigProof() *trillian.SignedMapRoot { + if m != nil { + return m.InvalidRootSigProof + } + return nil +} + +func (m *GetMonitoringResponse) GetInvalidMutation() *InvalidMutation { + if m != nil { + return m.InvalidMutation + } + return nil +} + +func (m *GetMonitoringResponse) GetNotMatchingMapRoot() *NotMatchingMapRootProof { + if m != nil { + return m.NotMatchingMapRoot + } + return nil +} + func init() { proto.RegisterType((*Committed)(nil), "keytransparency.v1.types.Committed") proto.RegisterType((*EntryUpdate)(nil), "keytransparency.v1.types.EntryUpdate") @@ -777,72 +922,90 @@ func init() { proto.RegisterType((*UpdateEntryResponse)(nil), "keytransparency.v1.types.UpdateEntryResponse") proto.RegisterType((*GetMutationsRequest)(nil), "keytransparency.v1.types.GetMutationsRequest") proto.RegisterType((*GetMutationsResponse)(nil), "keytransparency.v1.types.GetMutationsResponse") + proto.RegisterType((*GetMonitoringRequest)(nil), "keytransparency.v1.types.GetMonitoringRequest") + proto.RegisterType((*InvalidMutation)(nil), "keytransparency.v1.types.InvalidMutation") + proto.RegisterType((*NotMatchingMapRootProof)(nil), "keytransparency.v1.types.NotMatchingMapRootProof") + proto.RegisterType((*GetMonitoringResponse)(nil), "keytransparency.v1.types.GetMonitoringResponse") } func init() { proto.RegisterFile("keytransparency_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 985 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdf, 0x6e, 0xdb, 0xb6, - 0x17, 0xae, 0xed, 0xd8, 0xb1, 0x4e, 0xfe, 0x15, 0x6c, 0x7e, 0x89, 0x7e, 0x1e, 0x5a, 0x04, 0x2a, - 0xb6, 0x75, 0xc3, 0xe0, 0x35, 0x2a, 0x92, 0xad, 0xdd, 0xc5, 0xba, 0x76, 0x43, 0x13, 0x24, 0x01, - 0x02, 0xa6, 0xcd, 0x2e, 0x05, 0xc6, 0xa2, 0x15, 0x22, 0xb2, 0xc8, 0x91, 0x94, 0x51, 0x05, 0xd8, - 0x1b, 0x0c, 0x18, 0xb0, 0x67, 0xd8, 0x33, 0xec, 0x05, 0xf6, 0x16, 0x7b, 0x9a, 0x81, 0xa4, 0x64, - 0xcb, 0xa9, 0xd3, 0x34, 0xbd, 0xd8, 0x4d, 0xc0, 0x73, 0x78, 0x3e, 0x9d, 0x73, 0xbe, 0xf3, 0x1d, - 0x3a, 0xf0, 0xe0, 0x82, 0x16, 0x5a, 0x92, 0x4c, 0x09, 0x22, 0x69, 0x36, 0x28, 0xa2, 0xf1, 0x76, - 0xa4, 0x0b, 0x41, 0x55, 0x5f, 0x48, 0xae, 0x39, 0xf2, 0xaf, 0xdc, 0xf7, 0xc7, 0xdb, 0x7d, 0x7b, - 0xdf, 0xf3, 0x07, 0xb2, 0x10, 0x9a, 0x7f, 0xad, 0x58, 0x22, 0xce, 0xdc, 0x5f, 0x87, 0xe9, 0xad, - 0x6a, 0xc9, 0xd2, 0x94, 0x91, 0xac, 0xb4, 0x37, 0x2a, 0x3b, 0x1a, 0x11, 0x11, 0x11, 0xc1, 0x9c, - 0x3f, 0xd8, 0x06, 0xef, 0x25, 0x1f, 0x8d, 0x98, 0xd6, 0x34, 0x46, 0x77, 0xa1, 0x75, 0x41, 0x0b, - 0xbf, 0xb1, 0xd5, 0x78, 0xb4, 0x8c, 0xcd, 0x11, 0x21, 0x58, 0x88, 0x89, 0x26, 0x7e, 0xd3, 0xba, - 0xec, 0x39, 0xf8, 0xad, 0x01, 0x4b, 0x3f, 0x65, 0x5a, 0x16, 0x6f, 0x44, 0x4c, 0x34, 0x45, 0xcf, - 0xa0, 0x93, 0xdb, 0x93, 0x8d, 0x5a, 0x0a, 0x83, 0xfe, 0x75, 0xf5, 0xf6, 0x4f, 0x58, 0x92, 0xd1, - 0xf8, 0xe0, 0x14, 0x97, 0x08, 0xf4, 0x03, 0x78, 0x83, 0x2a, 0xbd, 0xdf, 0xb2, 0xf0, 0x87, 0xd7, - 0xc3, 0x27, 0x95, 0xe2, 0x29, 0x2a, 0xc8, 0xa1, 0x6d, 0xab, 0x41, 0x0f, 0x00, 0x9c, 0x77, 0x44, - 0x33, 0x5d, 0x36, 0x51, 0xf3, 0xa0, 0x43, 0x58, 0x23, 0xb9, 0x3e, 0xe7, 0x92, 0x5d, 0xd2, 0x38, - 0xba, 0xa0, 0x85, 0xf2, 0x9b, 0x5b, 0xad, 0xf7, 0x67, 0x3c, 0xce, 0xcf, 0x52, 0x36, 0x38, 0xa0, - 0x05, 0x5e, 0x9d, 0x62, 0x0f, 0x68, 0xa1, 0x82, 0x3f, 0x1b, 0xe0, 0x4d, 0x6e, 0x51, 0x0f, 0x16, - 0x69, 0x1c, 0xee, 0xec, 0x6c, 0x3f, 0x75, 0x89, 0xf7, 0xee, 0xe0, 0xca, 0x81, 0xbe, 0x83, 0xff, - 0x4b, 0x45, 0xa2, 0x31, 0x95, 0x6c, 0x58, 0xb0, 0x2c, 0x89, 0xd4, 0x39, 0x09, 0x77, 0x76, 0xa3, - 0x27, 0x8f, 0xbf, 0x09, 0x1d, 0xb1, 0x7b, 0x77, 0xf0, 0x86, 0x54, 0xe4, 0xb4, 0x8a, 0x38, 0xb1, - 0x01, 0xe6, 0x1e, 0x85, 0xb0, 0x4e, 0x07, 0xf1, 0x0c, 0x5c, 0x84, 0x3b, 0xbb, 0x96, 0x2b, 0x83, - 0x43, 0xf6, 0x76, 0x82, 0x3c, 0x0e, 0x77, 0x76, 0x5f, 0x00, 0x74, 0x2f, 0x68, 0x61, 0x25, 0x14, - 0x84, 0xd0, 0x3d, 0xa0, 0xc5, 0x29, 0x49, 0x73, 0x3a, 0x67, 0xbc, 0xeb, 0xd0, 0x1e, 0x9b, 0xab, - 0x72, 0xbe, 0xce, 0x08, 0xfe, 0x68, 0x42, 0xb7, 0x9a, 0x14, 0xfa, 0x1e, 0x3c, 0xf3, 0x31, 0x17, - 0xd6, 0xb8, 0x69, 0xc0, 0x55, 0x2e, 0x6c, 0x2a, 0x70, 0x59, 0x31, 0x80, 0x62, 0x49, 0x46, 0x74, - 0x2e, 0x69, 0xc5, 0x78, 0x78, 0xb3, 0x44, 0xec, 0xc1, 0x81, 0xec, 0x78, 0x71, 0xed, 0x2b, 0xa8, - 0x07, 0x5d, 0x21, 0xe9, 0x98, 0xf1, 0x5c, 0x39, 0x26, 0xf0, 0xc4, 0xee, 0xbd, 0x81, 0xb5, 0x2b, - 0xd0, 0x7a, 0xe3, 0x9e, 0x6b, 0xfc, 0xab, 0x7a, 0xe3, 0x4b, 0xe1, 0x46, 0xdf, 0xed, 0xce, 0x8f, - 0x2c, 0x61, 0x9a, 0xa4, 0x69, 0xe1, 0xaa, 0x28, 0x09, 0x79, 0xd6, 0xfc, 0xb6, 0x11, 0xbc, 0x85, - 0xee, 0x51, 0xae, 0x89, 0x66, 0x3c, 0xab, 0x29, 0xbe, 0x71, 0x6b, 0xc5, 0x3f, 0x86, 0xb6, 0x90, - 0x9c, 0x0f, 0xcb, 0xcc, 0xbd, 0xfe, 0x64, 0x51, 0x8f, 0x88, 0x38, 0xa4, 0x64, 0xb8, 0x9f, 0x0d, - 0xd2, 0x5c, 0x31, 0x9e, 0x61, 0x17, 0x18, 0x30, 0x58, 0x7b, 0x45, 0xb5, 0x23, 0x81, 0xfe, 0x92, - 0x53, 0xa5, 0xd1, 0x26, 0x2c, 0xe6, 0x8a, 0xca, 0x88, 0xc5, 0x65, 0x53, 0x1d, 0x63, 0xee, 0xc7, - 0xe8, 0x7f, 0xd0, 0x21, 0x42, 0x18, 0x7f, 0xd3, 0xfa, 0xdb, 0x44, 0x88, 0xfd, 0x18, 0x7d, 0x06, - 0x6b, 0x43, 0x26, 0x95, 0x8e, 0xb4, 0xa4, 0x34, 0x52, 0xec, 0x92, 0x5a, 0xda, 0x5a, 0x78, 0xc5, - 0xba, 0x5f, 0x4b, 0x4a, 0x4f, 0xd8, 0x25, 0x0d, 0xfe, 0x69, 0xc2, 0xdd, 0x69, 0x2e, 0x25, 0x78, - 0xa6, 0x28, 0xfa, 0x04, 0xbc, 0xb1, 0x1c, 0x46, 0xae, 0x6a, 0x27, 0x9e, 0xee, 0x58, 0x0e, 0x8f, - 0x8d, 0x3d, 0xbb, 0xc0, 0xcd, 0x8f, 0x59, 0x60, 0xf4, 0x14, 0x20, 0xa5, 0xa4, 0x4a, 0xd0, 0xba, - 0x91, 0x16, 0xcf, 0x44, 0xbb, 0xec, 0x5f, 0x40, 0x4b, 0x8d, 0xa4, 0xbf, 0x60, 0x31, 0x9b, 0x53, - 0x8c, 0x63, 0xfd, 0x88, 0x08, 0xcc, 0xb9, 0xc6, 0x26, 0x06, 0x85, 0xd0, 0x4d, 0x79, 0x12, 0x49, - 0xce, 0xb5, 0xdf, 0x9e, 0x1f, 0x7f, 0xc8, 0x13, 0x1b, 0xbf, 0x98, 0xba, 0x03, 0xfa, 0x1c, 0xd6, - 0x0c, 0x66, 0xc0, 0x33, 0xc5, 0x94, 0x36, 0xad, 0xf8, 0x9d, 0xad, 0xd6, 0xa3, 0x65, 0xbc, 0x9a, - 0xf2, 0xe4, 0xe5, 0xd4, 0x8b, 0x1e, 0xc2, 0x8a, 0x09, 0x64, 0x55, 0x8d, 0xfe, 0xa2, 0x0d, 0x5b, - 0x4e, 0x79, 0x32, 0xa9, 0xdb, 0xbc, 0x18, 0x9b, 0x87, 0x4c, 0x39, 0x76, 0xf7, 0x98, 0xd2, 0xfc, - 0x03, 0x06, 0xba, 0x0e, 0x6d, 0xa5, 0x89, 0xd4, 0x96, 0xdb, 0x16, 0x76, 0x86, 0x19, 0x89, 0x20, - 0x49, 0x6d, 0x92, 0x6d, 0xdc, 0x35, 0x0e, 0x33, 0xc4, 0x9a, 0x06, 0x16, 0x6e, 0xd0, 0x40, 0x7b, - 0x9e, 0x06, 0x7e, 0x05, 0xff, 0xdd, 0x2a, 0x4b, 0x29, 0xbc, 0x80, 0x8e, 0xdd, 0x08, 0xe5, 0x37, - 0xec, 0x1e, 0x7f, 0x79, 0xfd, 0xa8, 0xaf, 0xca, 0x08, 0x97, 0x48, 0x74, 0x1f, 0x20, 0xa3, 0x6f, - 0x75, 0x54, 0x6f, 0xcb, 0x33, 0x9e, 0x13, 0xe3, 0x08, 0xfe, 0x6a, 0x00, 0x72, 0x3f, 0x2c, 0xff, - 0x85, 0xe2, 0xd1, 0x1e, 0x2c, 0x53, 0x93, 0x27, 0x2a, 0x17, 0xda, 0x49, 0xe9, 0xd3, 0xeb, 0xfb, - 0xaa, 0xfd, 0xf2, 0xe1, 0x25, 0x3a, 0x35, 0x82, 0x9f, 0xe1, 0xde, 0x4c, 0xdd, 0x25, 0x65, 0xcf, - 0xab, 0x7d, 0x77, 0x4f, 0xc5, 0x6d, 0x18, 0x2b, 0xf7, 0xff, 0xf7, 0x06, 0xdc, 0x7b, 0x45, 0x75, - 0xf5, 0xfa, 0xa8, 0x8a, 0x92, 0x75, 0x68, 0x53, 0xc1, 0x07, 0xe7, 0xf6, 0xcb, 0x2d, 0xec, 0x8c, - 0x79, 0x8d, 0x37, 0xe7, 0x35, 0x7e, 0x1f, 0xc0, 0x4a, 0x48, 0xf3, 0x0b, 0x9a, 0x59, 0x6e, 0x3c, - 0x6c, 0x45, 0xf5, 0xda, 0x38, 0x66, 0x15, 0xb6, 0x30, 0xab, 0xb0, 0xe0, 0xef, 0x26, 0xac, 0xcf, - 0x56, 0x54, 0x36, 0x3b, 0xbf, 0xa4, 0x72, 0x4b, 0x9b, 0xb7, 0xdc, 0xd2, 0xd6, 0xc7, 0x6f, 0xe9, - 0xc2, 0x87, 0x6d, 0x69, 0xfb, 0xdd, 0x2d, 0x45, 0xcf, 0xc1, 0x1b, 0x55, 0x7d, 0xd9, 0x6d, 0x7f, - 0xef, 0xf3, 0x5e, 0x51, 0x80, 0xa7, 0x20, 0x33, 0x01, 0x2b, 0xf0, 0x1a, 0xbd, 0x8b, 0x96, 0xde, - 0x15, 0xe3, 0x3e, 0xae, 0x28, 0x3e, 0xeb, 0xd8, 0xff, 0xc0, 0x9e, 0xfc, 0x1b, 0x00, 0x00, 0xff, - 0xff, 0xbd, 0x88, 0x8a, 0x70, 0xff, 0x09, 0x00, 0x00, + // 1204 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xdd, 0x6e, 0xdb, 0x36, + 0x14, 0xae, 0xec, 0x38, 0x96, 0x4f, 0xd2, 0xba, 0x60, 0xd3, 0x46, 0xcb, 0xd0, 0xa2, 0x50, 0xb1, + 0xad, 0x1d, 0x0a, 0xa7, 0x51, 0x91, 0x76, 0xed, 0x2e, 0xd6, 0xb5, 0x1b, 0x9a, 0x20, 0xc9, 0x10, + 0xd0, 0x6d, 0x76, 0x29, 0x30, 0x16, 0xad, 0x10, 0x91, 0x45, 0x4d, 0xa4, 0xdc, 0xaa, 0xc0, 0xb0, + 0x17, 0x18, 0x30, 0x60, 0xcf, 0xb0, 0x67, 0xd8, 0xed, 0x2e, 0xf6, 0x16, 0xbb, 0xd9, 0xab, 0x0c, + 0x24, 0x25, 0x5b, 0x76, 0xfd, 0x93, 0xf6, 0x62, 0x37, 0x01, 0x79, 0x74, 0x3e, 0x9e, 0x73, 0xbe, + 0xf3, 0x1d, 0xd2, 0x81, 0x5b, 0xe7, 0x34, 0x97, 0x29, 0x89, 0x45, 0x42, 0x52, 0x1a, 0xf7, 0x72, + 0x7f, 0xb8, 0xe3, 0xcb, 0x3c, 0xa1, 0xa2, 0x93, 0xa4, 0x5c, 0x72, 0xe4, 0x4c, 0x7d, 0xef, 0x0c, + 0x77, 0x3a, 0xfa, 0xfb, 0xd6, 0xc3, 0x90, 0xc9, 0xb3, 0xec, 0xb4, 0xd3, 0xe3, 0x83, 0xed, 0x90, + 0xf3, 0x30, 0xa2, 0xdb, 0x32, 0x65, 0x51, 0xc4, 0x48, 0xbc, 0xdd, 0x4b, 0xf3, 0x44, 0xf2, 0x6d, + 0xc1, 0xc2, 0xe4, 0xd4, 0xfc, 0x35, 0xc7, 0x6d, 0xdd, 0x5b, 0x00, 0x2a, 0x17, 0x85, 0xeb, 0xce, + 0x05, 0x5c, 0xfd, 0x01, 0x49, 0x7c, 0x92, 0x30, 0x03, 0x71, 0x77, 0xa0, 0xf5, 0x82, 0x0f, 0x06, + 0x4c, 0x4a, 0x1a, 0xa0, 0xab, 0x50, 0x3f, 0xa7, 0xb9, 0x63, 0xdd, 0xb6, 0xee, 0xae, 0x63, 0xb5, + 0x44, 0x08, 0x56, 0x02, 0x22, 0x89, 0x53, 0xd3, 0x26, 0xbd, 0x76, 0x7f, 0xb5, 0x60, 0xed, 0xfb, + 0x58, 0xa6, 0xf9, 0xeb, 0x24, 0x20, 0x92, 0xa2, 0xa7, 0xb0, 0x9a, 0xe9, 0x95, 0xf6, 0x5a, 0xf3, + 0xdc, 0xce, 0x3c, 0x02, 0x3a, 0x5d, 0x16, 0xc6, 0x34, 0x38, 0x38, 0xc1, 0x05, 0x02, 0x7d, 0x0b, + 0xad, 0x5e, 0x19, 0xde, 0xa9, 0x6b, 0xf8, 0x9d, 0xf9, 0xf0, 0x51, 0xa6, 0x78, 0x8c, 0x72, 0x33, + 0x68, 0xe8, 0x6c, 0xd0, 0x2d, 0x00, 0x63, 0x1d, 0xd0, 0x58, 0x16, 0x45, 0x54, 0x2c, 0xe8, 0x10, + 0xda, 0x24, 0x93, 0x67, 0x3c, 0x65, 0xef, 0x68, 0xe0, 0x9f, 0xd3, 0x5c, 0x38, 0xb5, 0xdb, 0xf5, + 0xc5, 0x11, 0x8f, 0xb3, 0xd3, 0x88, 0xf5, 0x0e, 0x68, 0x8e, 0xaf, 0x8c, 0xb1, 0x07, 0x34, 0x17, + 0xee, 0x1f, 0x16, 0xb4, 0x46, 0x5f, 0xd1, 0x16, 0x34, 0x69, 0xe0, 0xed, 0xee, 0xee, 0x3c, 0x31, + 0x81, 0xf7, 0x2e, 0xe1, 0xd2, 0x80, 0xbe, 0x86, 0x4f, 0x52, 0x41, 0xfc, 0x21, 0x4d, 0x59, 0x3f, + 0x67, 0x71, 0xe8, 0x8b, 0x33, 0xe2, 0xed, 0x3e, 0xf2, 0x1f, 0x3e, 0x78, 0xec, 0x19, 0x62, 0xf7, + 0x2e, 0xe1, 0x1b, 0xa9, 0x20, 0x27, 0xa5, 0x47, 0x57, 0x3b, 0xa8, 0xef, 0xc8, 0x83, 0x0d, 0xda, + 0x0b, 0x26, 0xe0, 0x89, 0xb7, 0xfb, 0x48, 0x73, 0xa5, 0x70, 0x48, 0x7f, 0x1d, 0x21, 0x8f, 0xbd, + 0xdd, 0x47, 0xcf, 0x01, 0xec, 0x73, 0x9a, 0x6b, 0x4d, 0xba, 0x1e, 0xd8, 0x07, 0x34, 0x3f, 0x21, + 0x51, 0x46, 0x67, 0xb4, 0x77, 0x03, 0x1a, 0x43, 0xf5, 0xa9, 0xe8, 0xaf, 0xd9, 0xb8, 0xbf, 0xd7, + 0xc0, 0x2e, 0x3b, 0x85, 0xbe, 0x81, 0x96, 0x3a, 0xcc, 0xb8, 0x59, 0xcb, 0x1a, 0x5c, 0xc6, 0xc2, + 0x2a, 0x03, 0x13, 0x15, 0x03, 0x08, 0x16, 0xc6, 0x44, 0x66, 0x29, 0x2d, 0x19, 0xf7, 0x96, 0x4b, + 0x44, 0x2f, 0x0c, 0x48, 0xb7, 0x17, 0x57, 0x4e, 0x41, 0x5b, 0x60, 0x27, 0x29, 0x1d, 0x32, 0x9e, + 0x09, 0xc3, 0x04, 0x1e, 0xed, 0xb7, 0x5e, 0x43, 0x7b, 0x0a, 0x5a, 0x2d, 0xbc, 0x65, 0x0a, 0xbf, + 0x5f, 0x2d, 0x7c, 0xcd, 0xbb, 0xd1, 0x31, 0x13, 0xf7, 0x1d, 0x0b, 0x99, 0x24, 0x51, 0x94, 0x9b, + 0x2c, 0x0a, 0x42, 0x9e, 0xd6, 0xbe, 0xb2, 0xdc, 0xb7, 0x60, 0x1f, 0x65, 0x92, 0x48, 0xc6, 0xe3, + 0x8a, 0xe2, 0xad, 0x0f, 0x56, 0xfc, 0x03, 0x68, 0x24, 0x29, 0xe7, 0xfd, 0x22, 0xf2, 0x56, 0x67, + 0x34, 0xc3, 0x47, 0x24, 0x39, 0xa4, 0xa4, 0xbf, 0x1f, 0xf7, 0xa2, 0x4c, 0x30, 0x1e, 0x63, 0xe3, + 0xe8, 0x32, 0x68, 0xbf, 0xa4, 0xd2, 0x90, 0x40, 0x7f, 0xca, 0xa8, 0x90, 0x68, 0x13, 0x9a, 0x99, + 0xa0, 0xa9, 0xcf, 0x82, 0xa2, 0xa8, 0x55, 0xb5, 0xdd, 0x0f, 0xd0, 0x75, 0x58, 0x25, 0x49, 0xa2, + 0xec, 0x35, 0x6d, 0x6f, 0x90, 0x24, 0xd9, 0x0f, 0xd0, 0xe7, 0xd0, 0xee, 0xb3, 0x54, 0x48, 0x5f, + 0xa6, 0x94, 0xfa, 0x82, 0xbd, 0xa3, 0x9a, 0xb6, 0x3a, 0xbe, 0xac, 0xcd, 0xaf, 0x52, 0x4a, 0xbb, + 0xec, 0x1d, 0x75, 0xff, 0xa9, 0xc1, 0xd5, 0x71, 0x2c, 0x91, 0xf0, 0x58, 0x50, 0xf4, 0x29, 0xb4, + 0x86, 0x69, 0xdf, 0x37, 0x59, 0x1b, 0xf1, 0xd8, 0xc3, 0xb4, 0x7f, 0xac, 0xf6, 0x93, 0x03, 0x5c, + 0xfb, 0x98, 0x01, 0x46, 0x4f, 0x00, 0x22, 0x4a, 0xca, 0x00, 0xf5, 0xa5, 0xb4, 0xb4, 0x94, 0xb7, + 0x89, 0x7e, 0x0f, 0xea, 0x62, 0x90, 0x3a, 0x2b, 0x1a, 0xb3, 0x39, 0xc6, 0x18, 0xd6, 0x8f, 0x48, + 0x82, 0x39, 0x97, 0x58, 0xf9, 0x20, 0x0f, 0xec, 0x88, 0x87, 0x7e, 0xca, 0xb9, 0x74, 0x1a, 0xb3, + 0xfd, 0x0f, 0x79, 0xa8, 0xfd, 0x9b, 0x91, 0x59, 0xa0, 0x2f, 0xa0, 0xad, 0x30, 0x3d, 0x1e, 0x0b, + 0x26, 0xa4, 0x2a, 0xc5, 0x59, 0xbd, 0x5d, 0xbf, 0xbb, 0x8e, 0xaf, 0x44, 0x3c, 0x7c, 0x31, 0xb6, + 0xa2, 0x3b, 0x70, 0x59, 0x39, 0xb2, 0x32, 0x47, 0xa7, 0xa9, 0xdd, 0xd6, 0x23, 0x1e, 0x8e, 0xf2, + 0x56, 0x37, 0xc6, 0xe6, 0x21, 0x13, 0x86, 0xdd, 0x3d, 0x26, 0x24, 0xbf, 0x40, 0x43, 0x37, 0xa0, + 0x21, 0x24, 0x49, 0xa5, 0xe6, 0xb6, 0x8e, 0xcd, 0x46, 0xb5, 0x24, 0x21, 0x61, 0xa5, 0x93, 0x0d, + 0x6c, 0x2b, 0x83, 0x6a, 0x62, 0x45, 0x03, 0x2b, 0x4b, 0x34, 0xd0, 0x98, 0xa5, 0x81, 0x9f, 0xc1, + 0x79, 0x3f, 0xcb, 0x42, 0x0a, 0xcf, 0x61, 0x55, 0x4f, 0x84, 0x70, 0x2c, 0x3d, 0xc7, 0x5f, 0xce, + 0x6f, 0xf5, 0xb4, 0x8c, 0x70, 0x81, 0x44, 0x37, 0x01, 0x62, 0xfa, 0x56, 0xfa, 0xd5, 0xb2, 0x5a, + 0xca, 0xd2, 0x55, 0x06, 0xf7, 0x4f, 0x0b, 0x90, 0x79, 0x58, 0xfe, 0x0f, 0xc5, 0xa3, 0x3d, 0x58, + 0xa7, 0x2a, 0x8e, 0x5f, 0x0c, 0xb4, 0x91, 0xd2, 0x67, 0xf3, 0xeb, 0xaa, 0xbc, 0x7c, 0x78, 0x8d, + 0x8e, 0x37, 0xee, 0x8f, 0x70, 0x6d, 0x22, 0xef, 0x82, 0xb2, 0x67, 0xe5, 0xbc, 0x9b, 0xab, 0xe2, + 0x43, 0x18, 0x2b, 0xe6, 0xff, 0x37, 0x0b, 0xae, 0xbd, 0xa4, 0xb2, 0xbc, 0x7d, 0x44, 0x49, 0xc9, + 0x06, 0x34, 0x68, 0xc2, 0x7b, 0x67, 0xfa, 0xe4, 0x3a, 0x36, 0x9b, 0x59, 0x85, 0xd7, 0x66, 0x15, + 0x7e, 0x13, 0x40, 0x4b, 0x48, 0xf2, 0x73, 0x1a, 0x6b, 0x6e, 0x5a, 0x58, 0x8b, 0xea, 0x95, 0x32, + 0x4c, 0x2a, 0x6c, 0x65, 0x52, 0x61, 0xee, 0xdf, 0x35, 0xd8, 0x98, 0xcc, 0xa8, 0x28, 0x76, 0x76, + 0x4a, 0xc5, 0x94, 0xd6, 0x3e, 0x70, 0x4a, 0xeb, 0x1f, 0x3f, 0xa5, 0x2b, 0x17, 0x9b, 0xd2, 0xc6, + 0xfb, 0x53, 0x8a, 0x9e, 0x41, 0x6b, 0x50, 0xd6, 0xa5, 0xa7, 0x7d, 0xe1, 0xf5, 0x5e, 0x52, 0x80, + 0xc7, 0x20, 0xd5, 0x01, 0x2d, 0xf0, 0x0a, 0xbd, 0x4d, 0x4d, 0xef, 0x65, 0x65, 0x3e, 0x2e, 0x29, + 0x76, 0xef, 0x1b, 0x12, 0x79, 0xcc, 0x24, 0x4f, 0x59, 0x1c, 0x56, 0xfa, 0x6a, 0x66, 0xc3, 0xaa, + 0x8c, 0xbc, 0xfb, 0x0b, 0xb4, 0xf7, 0xe3, 0x21, 0x89, 0x58, 0x30, 0x7a, 0x86, 0x76, 0xc1, 0xe6, + 0x51, 0xe0, 0xab, 0xeb, 0xb0, 0x50, 0xd7, 0xa2, 0x6b, 0xb3, 0xc9, 0xa3, 0x40, 0x59, 0x14, 0x2c, + 0xa6, 0x6f, 0x0c, 0x6c, 0xf9, 0x23, 0xd4, 0x8c, 0xe9, 0x1b, 0x65, 0x71, 0xff, 0xb2, 0x60, 0xf3, + 0x07, 0x2e, 0x8f, 0x88, 0xec, 0x9d, 0xb1, 0x38, 0x2c, 0xda, 0x66, 0xee, 0x61, 0x0f, 0x6c, 0xf5, + 0xb3, 0x52, 0xb7, 0xcd, 0x5a, 0xdc, 0xe6, 0xe6, 0xc0, 0x2c, 0xd0, 0x63, 0x68, 0x95, 0xd9, 0x97, + 0x3f, 0x0b, 0x16, 0xe5, 0x61, 0x17, 0xe9, 0x0b, 0x05, 0x2c, 0xf3, 0x57, 0xaf, 0xff, 0x52, 0x60, + 0x51, 0x80, 0x70, 0xff, 0xad, 0xc1, 0xf5, 0x29, 0xc6, 0x0b, 0xdd, 0x16, 0x0a, 0xb5, 0x2e, 0xa0, + 0x50, 0x07, 0x9a, 0x4c, 0x9c, 0xa8, 0x3e, 0x68, 0xf2, 0x6c, 0x5c, 0x6e, 0xd1, 0x3e, 0x5c, 0x63, + 0xa6, 0x43, 0xca, 0xbb, 0xcb, 0xc2, 0xe3, 0xca, 0x83, 0x36, 0xf7, 0xd0, 0x59, 0x18, 0xd4, 0x85, + 0x36, 0x9b, 0x6c, 0x76, 0x71, 0x31, 0xdd, 0x9b, 0x2f, 0xc5, 0x29, 0x75, 0xe0, 0xe9, 0x13, 0x10, + 0x01, 0x14, 0xbf, 0xd7, 0xbf, 0xe2, 0x2d, 0xdc, 0x99, 0x7f, 0xee, 0x9c, 0x9e, 0xe3, 0x19, 0x87, + 0x9d, 0xae, 0xea, 0x7f, 0x2a, 0x1e, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x8d, 0x71, 0xa8, + 0x23, 0x0d, 0x00, 0x00, } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto index 2308439b4..8520d7d12 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto @@ -259,12 +259,39 @@ message GetMonitoringRequest { int64 start = 1; } +// InvalidMutation includes all information to reproduce that there was an +// invalid mutation from epoch e to e+1. +message InvalidMutation { + // old_leaf is the inclusion proof to the leaf at epoch e. + trillian.MapLeafInclusion old_leaf = 1; + // new_leaf is the inclusion proof to the leaf at epoch e+1. + trillian.MapLeafInclusion new_leaf = 2; +} + +// NotMatchingMapRootProof contains all data necessary to reproduce that set of +// mutations does not produce new expected map root. +message NotMatchingMapRootProof { + // map_root contains the map root hash the monitor observed. + trillian.SignedMapRoot map_root = 1; + // old_leafs is a list of inclusion proofs for the leafs in epoch e. + repeated trillian.MapLeafInclusion old_leafs = 2; + // new_leafs is a list of inclusion proofs for changed leafs (from epoch e + // to epoch e+1). Hashing these produces a different hash than root hash in + // above's map_root. + repeated trillian.MapLeafInclusion new_leafs = 3; +} + message GetMonitoringResponse { // smr contains the map root for the sparse Merkle Tree signed with the // monitor's key on success. If the checks were not successful the // smr will be empty. The epochs are encoded into the smr map_revision. trillian.SignedMapRoot smr = 1; + // seen_timestamp_nanos contains the time in nanoseconds where this particular + // signed map root was retrieved and processed. The actual timestamp of the + // smr returned by the server is contained in above smr field. + int64 seen_timestamp_nanos = 2; + // // The following fields provide more information about each failure in this // response, if any. @@ -272,12 +299,15 @@ message GetMonitoringResponse { // isValid signals if all verification steps for the requested epoch passed // or not. - bool isValid = 2; - // invalidRootSig contains the signed map root received by the + bool isValid = 3; + // invalidRootSigProof contains the signed map root received by the // key-transparency server, if and only if the key-server's signature was // invalid. - trillian.SignedMapRoot invalidRootSig = 3; - // TODO(ismail): add field for the following cases: - // - Invalid mutation from epoch e to e+1 - // - Set of mutations does not produce new map root + trillian.SignedMapRoot invalidRootSigProof = 4; + // invalidMutation contains data to reproduce that there was an invalid + // mutation from epoch e to epoch e+1 + InvalidMutation invalidMutation = 5; + // NotMatchingMapRoot contains all data to reproduce that the set of mutations + // does not produce observed new map root. + NotMatchingMapRootProof notMatchingMapRoot = 6; } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 5aec32f19..ff5c6fac1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -155,6 +155,18 @@ services: build: context: .. dockerfile: ./keytransparency/cmd/keytransparency-monitor/Dockerfile + entrypoint: + - /go/bin/keytransparency-monitor + - --addr=0.0.0.0:8099 + - --kt-url=kt-server:8080 + - --poll-period=5s + - --key=genfiles/server.key + - --cert=genfiles/server.crt + - --sign-key=/kt/p256-monitor_sign-key.pem + - --password=towel + - --map-id=$MAP_ID + - --alsologtostderr + - --v=3 image: us.gcr.io/key-transparency/keytransparency-monitor restart: always ports: diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 9e0f21e64..84b795ce3 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -1,4 +1,4 @@ -// Copyright 2016 Google Inc. All Rights Reserved. +// Copyright 2017 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,9 @@ package monitor import ( + "bytes" + "errors" + "fmt" "time" "github.com/golang/glog" @@ -27,6 +30,7 @@ import ( "google.golang.org/grpc/codes" "github.com/google/trillian" + "github.com/google/trillian/crypto" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" tv "github.com/google/keytransparency/core/tree/sparse/verifier" @@ -34,7 +38,6 @@ import ( mspb "github.com/google/keytransparency/impl/proto/monitor_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" - "bytes" "github.com/google/keytransparency/core/tree/sparse" ) @@ -43,30 +46,45 @@ import ( // size 16 will contain about 8KB of data. const pageSize = 16 +var ( + // ErrInvalidMutation occurs when verification failed because of an invalid + // mutation. + ErrInvalidMutation = errors.New("Invalid mutation") + // ErrNotMatchingRoot occurs when the reconstructed root differs from the one + // we received from the server. + ErrNotMatchingRoot = errors.New("Recreated root does not match") + // ErrInvalidSignature occurs when the signature on the observed map root is + // invalid. + ErrInvalidSignature = errors.New("Recreated root does not match") + // ErrNothingProcessed occurs when the monitor did not process any mutations / + // smrs yet. + ErrNothingProcessed = errors.New("did not process any mutations yet") +) + // Server holds internal state for the monitor server. -type server struct { +type Server struct { client mupb.MutationServiceClient pollPeriod time.Duration - tree *tv.Verifier - // TODO(ismail) abstract this into a storage interface and have an in-memory version - seenSMRs []*trillian.SignedMapRoot - reconstructedSMRs []*trillian.SignedMapRoot + tree *tv.Verifier + signer crypto.Signer + proccessedSMRs []*ktpb.GetMonitoringResponse } // New creates a new instance of the monitor server. -func New(cli mupb.MutationServiceClient, mapID int64, poll time.Duration) *server { - return &server{ +func New(cli mupb.MutationServiceClient, signer crypto.Signer, mapID int64, poll time.Duration) *Server { + return &Server{ client: cli, pollPeriod: poll, // TODO TestMapHasher (maphasher.Default) does not implement sparse.TreeHasher: - tree: tv.New(mapID, sparse.CONIKSHasher), - seenSMRs: make([]*trillian.SignedMapRoot, 256), - reconstructedSMRs: make([]*trillian.SignedMapRoot, 256), + tree: tv.New(mapID, sparse.CONIKSHasher), + signer: signer, + proccessedSMRs: make([]*ktpb.GetMonitoringResponse, 256), } } -func (s *server) StartPolling() error { +// StartPolling initiates polling and processing mutations every pollPeriod. +func (s *Server) StartPolling() error { t := time.NewTicker(s.pollPeriod) for now := range t.C { glog.Infof("Polling: %v", now) @@ -78,34 +96,47 @@ func (s *server) StartPolling() error { return nil } -// GetSignedMapRoot returns the latest reconstructed using the Mutations API and -// validated signed map root. -func (s *server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { - return &ktpb.GetMonitoringResponse{ - Smr: s.lastSMR(), - }, nil +// GetSignedMapRoot returns the latest valid signed map root the monitor +// observed. Additionally, the response contains additional data necessary to +// reproduce errors on failure. +// +// Returns the signed map root for the latest epoch the monitor observed. If +// the monitor could not reconstruct the map root given the set of mutations +// from the previous to the current epoch it won't sign the map root and +// additional data will be provided to reproduce the failure. +func (s *Server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { + if len(s.proccessedSMRs) > 0 { + return s.proccessedSMRs[len(s.proccessedSMRs)-1], nil + } + return nil, ErrNothingProcessed } // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. -func (s *server) GetSignedMapRootStream(in *ktpb.GetMonitoringRequest, stream mspb.MonitorService_GetSignedMapRootStreamServer) error { +func (s *Server) GetSignedMapRootStream(in *ktpb.GetMonitoringRequest, stream mspb.MonitorService_GetSignedMapRootStreamServer) error { // TODO(ismail): implement stream API return grpc.Errorf(codes.Unimplemented, "GetSignedMapRootStream is unimplemented") } -func (s *server) GetSignedMapRootByRevision(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { +// GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns +// the monitor's result for a specific map revision. +// +// Returns the signed map root for the specified epoch the monitor observed. +// If the monitor could not reconstruct the map root given the set of +// mutations from the previous to the current epoch it won't sign the map root +// and additional data will be provided to reproduce the failure. +func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { // TODO(ismail): implement by revision API return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") } -func (s *server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { +func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { req := &ktpb.GetMutationsRequest{PageSize: pageSize, Epoch: s.nextRevToQuery()} resp, err := s.client.GetMutations(ctx, req, opts...) if err != nil { return nil, err } - // TODO(ismail): remember when we've actually requested and seen this SMR! - // publish delta (seen - actual) + seen := time.Now().UnixNano() if got, want := resp.GetSmr(), s.lastSeenSMR(); bytes.Equal(got.GetRootHash(), want.GetRootHash()) && got.GetMapRevision() == want.GetMapRevision() { // We already processed this SMR. Do not update seen SMRs. Do not scroll @@ -116,40 +147,77 @@ func (s *server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] mutations := make([]*ktpb.Mutation, pageSize*2) mutations = append(mutations, resp.GetMutations()...) - s.pageMutations(ctx, resp, mutations, opts) + if err := s.pageMutations(ctx, resp, mutations, opts...); err != nil { + glog.Errorf("s.pageMutations(_): %v", err) + return nil, err + } // update seen SMRs: - s.seenSMRs = append(s.seenSMRs, resp.GetSmr()) + // TODO: this should be + + rh := resp.GetSmr().GetRootHash() + switch err := s.verifyMutations(mutations, rh); err { + // TODO(ismail): return proper data for failure cases: + case ErrInvalidMutation: + glog.Errorf("TODO: handle this ErrInvalidMutation properly") + case ErrInvalidSignature: + glog.Errorf("TODO: handle this ErrInvalidSignature properly (return SMR)") + case ErrNotMatchingRoot: + glog.Errorf("TODO: handle this ErrNotMatchingRoot properly") + case nil: + glog.Info("TODO: Successfully verified.") + default: + glog.Errorf("Unexpected error: %v", err) + } + // TODO(ismail): Sign reconstructed Hash instead of response hash: + sig, err := s.signer.SignObject(resp.GetSmr().GetRootHash()) + if err != nil { + return nil, fmt.Errorf("s.signer.SignObject(_): %v", err) + } + // Update seen/processed signed map roots: + s.proccessedSMRs = append(s.proccessedSMRs, + &ktpb.GetMonitoringResponse{ + Smr: &trillian.SignedMapRoot{ + Signature: sig, + TimestampNanos: resp.GetSmr().GetTimestampNanos(), + RootHash: resp.GetSmr().GetRootHash(), + Metadata: resp.GetSmr().GetMetadata(), + MapId: resp.GetSmr().GetMapId(), + MapRevision: resp.GetSmr().GetMapRevision(), + }, + IsValid: true, + SeenTimestampNanos: seen, + }) + + return mutations, nil +} + +func (s *Server) verifyMutations(ms []*ktpb.Mutation, expectedRoot []byte) error { // TODO(ismail): // For each received mutation in epoch e: // Verify that the provided leaf’s inclusion proof goes to epoch e -1. // Verify the mutation’s validity against the previous leaf. // Compute the new leaf and store the intermediate hashes locally. // Compute the new root using local intermediate hashes from epoch e. - for _, m := range mutations { + for _, m := range ms { idx := m.GetProof().GetLeaf().GetIndex() nbrs := m.GetProof().GetInclusion() if err := s.tree.VerifyProof(nbrs, idx, m.GetProof().GetLeaf().GetLeafValue(), - sparse.FromBytes(resp.GetSmr().GetRootHash())); err != nil { + sparse.FromBytes(expectedRoot)); err != nil { glog.Errorf("VerifyProof(): %v", err) // TODO return nil, err } } - // TODO(ismail): sign and update reconstructedSMRs - // here we just add the kt-server signed SMR: - glog.Errorf("Got reponse: %v", resp.GetSmr()) - s.reconstructedSMRs = append(s.reconstructedSMRs, resp.GetSmr()) - - return mutations, nil + return nil } // pageMutations iterates/pages through all mutations in the case there were // more then maximum pageSize mutations in between epochs. // It will modify the passed GetMutationsResponse resp and the passed list of // mutations ms. -func (s *server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsResponse, +func (s *Server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsResponse, ms []*ktpb.Mutation, opts ...grpc.CallOption) error { // Query all mutations in the current epoch for resp.GetNextPageToken() != "" { @@ -163,21 +231,14 @@ func (s *server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsRespo return nil } -func (s *server) lastSeenSMR() *trillian.SignedMapRoot { - if len(s.seenSMRs) > 0 { - return s.seenSMRs[len(s.seenSMRs)-1] - } - return nil -} - -func (s *server) lastSMR() *trillian.SignedMapRoot { - if len(s.reconstructedSMRs) > 0 { - return s.reconstructedSMRs[len(s.reconstructedSMRs)-1] +func (s *Server) lastSeenSMR() *trillian.SignedMapRoot { + if len(s.proccessedSMRs) > 0 { + return s.proccessedSMRs[len(s.proccessedSMRs)-1].GetSmr() } return nil } -func (s *server) nextRevToQuery() int64 { +func (s *Server) nextRevToQuery() int64 { smr := s.lastSeenSMR() if smr == nil { return 1 diff --git a/impl/monitor/monitor_test.go b/impl/monitor/monitor_test.go index aff2c0091..5c183e74b 100644 --- a/impl/monitor/monitor_test.go +++ b/impl/monitor/monitor_test.go @@ -1,3 +1,21 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package monitor implements the monitor service. A monitor repeatedly polls a +// key-transparency server's Mutations API and signs Map Roots if it could +// reconstruct +// clients can query. package monitor import ( @@ -8,15 +26,15 @@ import ( ) func TestGetSignedMapRoot(t *testing.T) { - srv := server{} + srv := Server{} _, err := srv.GetSignedMapRoot(context.TODO(), nil) - if got, want := grpc.Code(err), codes.Unimplemented; got != want { - t.Errorf("GetSignedMapRootStream(_, _): %v, want %v", got, want) + if got, want := err, ErrNothingProcessed; got != want { + t.Errorf("GetSignedMapRoot(_, _): %v, want %v", got, want) } } func TestGetSignedMapRootStream(t *testing.T) { - srv := server{} + srv := Server{} err := srv.GetSignedMapRootStream(nil, nil) if got, want := grpc.Code(err), codes.Unimplemented; got != want { t.Errorf("GetSignedMapRootStream(_, _): %v, want %v", got, want) diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go index 2cd4ab947..5550c914a 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go @@ -4,7 +4,10 @@ /* Package monitor_v1_service is a generated protocol buffer package. -TODO(ismail): detailed comment +Monitor Service + +The Key Transparency monitor server service consists of APIs to fetch +monitor results queried using the mutations API. It is generated from these files: monitor_v1_service.proto @@ -46,8 +49,26 @@ const _ = grpc.SupportPackageIsVersion4 // Client API for MonitorService service type MonitorServiceClient interface { + // GetSignedMapRoot returns the latest valid signed map root the monitor + // observed. Additionally, the response contains additional data necessary to + // reproduce errors on failure. + // + // Returns the signed map root for the latest epoch the monitor observed. If + // the monitor could not reconstruct the map root given the set of mutations + // from the previous to the current epoch it won't sign the map root and + // additional data will be provided to reproduce the failure. GetSignedMapRoot(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns + // the monitor's result for a specific map revision. + // + // Returns the signed map root for the specified epoch the monitor observed. + // If the monitor could not reconstruct the map root given the set of + // mutations from the previous to the current epoch it won't sign the map root + // and additional data will be provided to reproduce the failure. GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. + // + // Returns a list of SMRs along with data to reproduce any errors. GetSignedMapRootStream(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (MonitorService_GetSignedMapRootStreamClient, error) } @@ -112,8 +133,26 @@ func (x *monitorServiceGetSignedMapRootStreamClient) Recv() (*keytransparency_v1 // Server API for MonitorService service type MonitorServiceServer interface { + // GetSignedMapRoot returns the latest valid signed map root the monitor + // observed. Additionally, the response contains additional data necessary to + // reproduce errors on failure. + // + // Returns the signed map root for the latest epoch the monitor observed. If + // the monitor could not reconstruct the map root given the set of mutations + // from the previous to the current epoch it won't sign the map root and + // additional data will be provided to reproduce the failure. GetSignedMapRoot(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns + // the monitor's result for a specific map revision. + // + // Returns the signed map root for the specified epoch the monitor observed. + // If the monitor could not reconstruct the map root given the set of + // mutations from the previous to the current epoch it won't sign the map root + // and additional data will be provided to reproduce the failure. GetSignedMapRootByRevision(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. + // + // Returns a list of SMRs along with data to reproduce any errors. GetSignedMapRootStream(*keytransparency_v1_types.GetMonitoringRequest, MonitorService_GetSignedMapRootStreamServer) error } @@ -204,23 +243,23 @@ var _MonitorService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("monitor_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 286 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x91, 0x31, 0x4a, 0xfc, 0x40, - 0x14, 0x87, 0xc9, 0xff, 0x0f, 0x16, 0x29, 0x44, 0x06, 0x59, 0x24, 0xa4, 0xda, 0x03, 0xcc, 0x18, - 0xed, 0x2c, 0x6d, 0xb6, 0xda, 0x26, 0x39, 0xc0, 0xf2, 0x92, 0x7d, 0xc4, 0xc1, 0xcd, 0xbc, 0x71, - 0xde, 0xdb, 0x81, 0x20, 0x36, 0xde, 0x40, 0xac, 0x2c, 0x3d, 0x93, 0x57, 0xd8, 0x83, 0xc8, 0x26, - 0x29, 0x24, 0x20, 0xd8, 0x88, 0xf5, 0x37, 0xfc, 0xbe, 0x6f, 0x66, 0xd2, 0x8b, 0x8e, 0x9c, 0x15, - 0x0a, 0x9b, 0x58, 0x6c, 0x18, 0x43, 0xb4, 0x0d, 0x6a, 0x1f, 0x48, 0x48, 0xa9, 0x89, 0xe8, 0x58, - 0xe8, 0x89, 0x64, 0xdb, 0xd6, 0xca, 0xdd, 0xbe, 0xd6, 0x0d, 0x75, 0xa6, 0x25, 0x6a, 0x77, 0x68, - 0xee, 0xb1, 0x97, 0x00, 0x8e, 0x3d, 0x04, 0x74, 0x4d, 0x6f, 0x1a, 0x0a, 0x68, 0x86, 0x85, 0x39, - 0x3a, 0x2a, 0xa4, 0xf7, 0xc8, 0xdf, 0x82, 0xd1, 0x9c, 0xe5, 0xd3, 0x34, 0x78, 0x6b, 0xc0, 0x39, - 0x12, 0x10, 0x4b, 0x6e, 0xa2, 0x57, 0x87, 0xff, 0xe9, 0xe9, 0x7a, 0x4c, 0xab, 0xc6, 0x2c, 0xf5, - 0x92, 0xa4, 0x67, 0x2b, 0x94, 0xca, 0xb6, 0x0e, 0xb7, 0x6b, 0xf0, 0x25, 0x91, 0x28, 0xad, 0x67, - 0x9a, 0xe3, 0x45, 0x46, 0xcd, 0x0a, 0x65, 0x5a, 0xb0, 0xae, 0x2d, 0xf1, 0x61, 0x8f, 0x2c, 0x99, - 0xf9, 0xf1, 0x79, 0xf6, 0xe4, 0x18, 0x97, 0xf9, 0xf3, 0xc7, 0xe1, 0xf5, 0xdf, 0x42, 0x9d, 0x9b, - 0x58, 0x98, 0x0e, 0xbc, 0x09, 0x44, 0xc2, 0x37, 0x3b, 0x10, 0x64, 0x51, 0xef, 0x49, 0x9a, 0xcd, - 0x9b, 0x6e, 0xfb, 0x12, 0xa3, 0x65, 0x4b, 0xee, 0xf7, 0xeb, 0x96, 0x43, 0x5d, 0xae, 0x32, 0x13, - 0x8b, 0x1a, 0x05, 0xbe, 0x24, 0x9a, 0x47, 0x16, 0x08, 0xf2, 0xa4, 0xde, 0x92, 0x74, 0x31, 0x6f, - 0xac, 0x24, 0x20, 0x74, 0x7f, 0xf6, 0x7a, 0x3c, 0xe8, 0x2f, 0x93, 0xfa, 0x64, 0xf8, 0xed, 0xeb, - 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x4b, 0x95, 0x94, 0xa1, 0x02, 0x00, 0x00, + // 282 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x91, 0x31, 0x4a, 0xc4, 0x40, + 0x14, 0x86, 0x89, 0x82, 0x45, 0x0a, 0x91, 0x41, 0x57, 0x09, 0x6b, 0xe3, 0x01, 0x66, 0x8c, 0x76, + 0x96, 0x36, 0x5b, 0x6d, 0x93, 0x1c, 0x60, 0x99, 0xcd, 0x3e, 0xe2, 0xe0, 0xe6, 0xbd, 0x71, 0xde, + 0xdb, 0x40, 0x10, 0x1b, 0x6f, 0x20, 0x56, 0x82, 0xb7, 0xf2, 0x00, 0x36, 0x1e, 0x44, 0x36, 0x99, + 0xc6, 0x80, 0x60, 0x23, 0x5b, 0x7f, 0xc3, 0xff, 0x7d, 0x33, 0x93, 0x9e, 0x35, 0x84, 0x4e, 0x28, + 0x2c, 0xda, 0x7c, 0xc1, 0x10, 0x5a, 0x57, 0x81, 0xf6, 0x81, 0x84, 0x94, 0x8a, 0x44, 0xb7, 0xb9, + 0x8e, 0x24, 0x5b, 0xd5, 0x4e, 0xee, 0x36, 0x4b, 0x5d, 0x51, 0x63, 0x6a, 0xa2, 0x7a, 0x0d, 0xe6, + 0x1e, 0x3a, 0x09, 0x16, 0xd9, 0xdb, 0x00, 0x58, 0x75, 0xa6, 0xa2, 0x00, 0xa6, 0x5f, 0x18, 0xa3, + 0xad, 0x42, 0x3a, 0x0f, 0xfc, 0x2b, 0x18, 0xcc, 0xd9, 0x34, 0x4e, 0x5b, 0xef, 0x8c, 0x45, 0x24, + 0xb1, 0xe2, 0x08, 0x23, 0xbd, 0xfa, 0xdc, 0x4f, 0x0f, 0xe7, 0x43, 0x5a, 0x39, 0x64, 0xa9, 0x97, + 0x24, 0x3d, 0x9a, 0x81, 0x94, 0xae, 0x46, 0x58, 0xcd, 0xad, 0x2f, 0x88, 0x44, 0x69, 0x3d, 0xd2, + 0x6c, 0x2f, 0x32, 0x68, 0x66, 0x20, 0x71, 0xc1, 0x61, 0x5d, 0xc0, 0xc3, 0x06, 0x58, 0x32, 0xf3, + 0xe7, 0xf3, 0xec, 0x09, 0x19, 0x2e, 0xa6, 0xcf, 0x1f, 0x5f, 0xaf, 0x7b, 0x13, 0x75, 0x6c, 0xda, + 0xdc, 0x34, 0xd6, 0x9b, 0x40, 0x24, 0x7c, 0xb3, 0xb6, 0x02, 0x2c, 0xea, 0x3d, 0x49, 0xb3, 0x71, + 0xd3, 0x6d, 0x57, 0x40, 0xeb, 0xd8, 0x11, 0xfe, 0x7f, 0xdd, 0x79, 0x5f, 0x77, 0xaa, 0x4e, 0x7e, + 0xd4, 0x99, 0x47, 0x16, 0x1b, 0xe4, 0x49, 0xbd, 0x25, 0xe9, 0x64, 0x9c, 0x57, 0x4a, 0x00, 0xdb, + 0xec, 0xec, 0xe1, 0xb8, 0xd7, 0x5f, 0x26, 0xcb, 0x83, 0xfe, 0xa3, 0xaf, 0xbf, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x0f, 0x72, 0x10, 0xb7, 0x9c, 0x02, 0x00, 0x00, } diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go index 1d345a4c8..3278543ef 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go @@ -217,7 +217,7 @@ func RegisterMonitorServiceHandler(ctx context.Context, mux *runtime.ServeMux, c var ( pattern_MonitorService_GetSignedMapRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "latest")) - pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1beta1", "map", "roots", "start"}, "")) + pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "map", "roots", "start"}, "")) pattern_MonitorService_GetSignedMapRootStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "stream")) ) diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.proto b/impl/proto/monitor_v1_service/monitor_v1_service.proto index db34dc4cd..9723cfed4 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.proto +++ b/impl/proto/monitor_v1_service/monitor_v1_service.proto @@ -32,21 +32,33 @@ import "google/api/annotations.proto"; // service MonitorService { // GetSignedMapRoot returns the latest valid signed map root the monitor - // observed. + // observed. Additionally, the response contains additional data necessary to + // reproduce errors on failure. // // Returns the signed map root for the latest epoch the monitor observed. If // the monitor could not reconstruct the map root given the set of mutations - // from the previous to the current epoch it won't sign the map root. + // from the previous to the current epoch it won't sign the map root and + // additional data will be provided to reproduce the failure. rpc GetSignedMapRoot(keytransparency.v1.types.GetMonitoringRequest) returns (keytransparency.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots:latest" }; } - // TODO(ismail): comments + + // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns + // the monitor's result for a specific map revision. + // + // Returns the signed map root for the specified epoch the monitor observed. + // If the monitor could not reconstruct the map root given the set of + // mutations from the previous to the current epoch it won't sign the map root + // and additional data will be provided to reproduce the failure. rpc GetSignedMapRootByRevision(keytransparency.v1.types.GetMonitoringRequest) returns(keytransparency.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots/{start}" }; } + // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. + // + // Returns a list of SMRs along with data to reproduce any errors. rpc GetSignedMapRootStream(keytransparency.v1.types.GetMonitoringRequest) returns (stream keytransparency.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots:stream" }; diff --git a/scripts/gen_monitor_keys.sh b/scripts/gen_monitor_keys.sh new file mode 100644 index 000000000..f79f6721e --- /dev/null +++ b/scripts/gen_monitor_keys.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# Copyright 2016 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Create output directory. +mkdir -p "${GOPATH}/src/github.com/google/keytransparency/genfiles" +cd "${GOPATH}/src/github.com/google/keytransparency/genfiles" + +INTERACTIVE=1 + +while getopts ":f" opt; do + case $opt in + f) + INTERACTIVE=0 + ;; + \?) + echo "Invalid option: -$OPTARG." + usage + exit 1 + ;; + esac +done + + +DEFAULT_PWD=towel + +# Generate monitor signing key-pair: +if ((INTERACTIVE == 1)); then + # Prompts for password: + openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -out p256-monitor_sign-key.pem +else + + openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -passout pass:$DEFAULT_PWD -out p256-monitor_sign-key.pem +fi +chmod 600 p256-monitor_sign-key.pem + From 77a14fbd838c08af3cfe2fad8ea99988cba6facd Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 31 Jul 2017 15:56:48 +0100 Subject: [PATCH 03/46] Add to kubernetes config and deploy script Minor changes verify signature on response resolves #672 Add log sig verification rebase wip WIP add TODO remove streaming API (simplifies moving to core) Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's work in progress revert local changes, add TODOs simplify monitor Dockerfile (non-opinionated) --- cmd/keytransparency-monitor/main.go | 17 +- core/keyserver/keyserver.go | 2 +- core/mutator/entry/entry.go | 6 +- core/mutator/mutator.go | 2 +- .../keytransparency_v1_types.pb.go | 256 ++++++++++++------ .../keytransparency_v1_types.proto | 20 +- .../keytransparency-deployment.yml.tmpl | 35 +++ docker-compose.yml | 8 +- impl/monitor/monitor.go | 143 +++++----- impl/monitor/monitor_test.go | 12 +- impl/monitor/verify.go | 86 ++++++ impl/monitor/verify_test.go | 18 ++ .../keytransparency_v1_service.pb.go | 86 ++---- .../monitor_v1_service.pb.go | 106 ++------ .../monitor_v1_service.pb.gw.go | 57 ---- .../monitor_v1_service.proto | 8 - scripts/deploy.sh | 2 +- 17 files changed, 440 insertions(+), 424 deletions(-) create mode 100644 impl/monitor/verify.go create mode 100644 impl/monitor/verify_test.go diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index bb9b626e1..f91fd8497 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -21,9 +21,6 @@ import ( "strings" "time" - mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" - mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" - "github.com/golang/glog" "github.com/google/keytransparency/impl/monitor" "github.com/google/trillian/crypto" @@ -34,12 +31,15 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" + + mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" ) var ( addr = flag.String("addr", ":8099", "The ip:port combination to listen on") - keyFile = flag.String("key", "genfiles/server.key", "TLS private key file") - certFile = flag.String("cert", "genfiles/server.pem", "TLS cert file") + keyFile = flag.String("tls-key", "genfiles/server.key", "TLS private key file") + certFile = flag.String("tls-cert", "genfiles/server.pem", "TLS cert file") signingKey = flag.String("sign-key", "genfiles/p256-key.pem", "Path to private key PEM for SMH signing") signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") @@ -47,8 +47,9 @@ var ( pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") - // TODO(ismail): remove mapID - mapID = flag.Int64("map-id", 0, "Trillian map ID") + + mapKey = flag.String("map-key", "genfiles/map-rpc-server.pubkey.pem", "Path to public key PEM used to verify the SMH signature") + logKey = flag.String("log-key", "genfiles/log-rpc-server.pubkey.pem", "Path to public key PEM used to verify the STH signature") // TODO(ismail): expose prometheus metrics: a variable that tracks valid/invalid MHs metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") @@ -111,7 +112,7 @@ func main() { glog.Fatalf("Could not create signer from %v: %v", *signingKey, err) } - srv := monitor.New(mcc, *crypto.NewSHA256Signer(key), *mapID, *pollPeriod) + srv := monitor.New(mcc, *crypto.NewSHA256Signer(key), *mapKey, *logKey, *pollPeriod) mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index be967c347..4945d733c 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -285,7 +285,7 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* } // Catch errors early. Perform mutation verification. - // Read at the current value. Assert the following: + // Read at the current value. Assert the following: // - Correct signatures from previous epoch. // - Correct signatures internal to the update. // - Hash of current data matches the expectation in the mutation. diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index e13864814..241bfeb40 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -81,20 +81,20 @@ func (*Entry) Mutate(oldValue, mutation []byte) ([]byte, error) { return nil, mutator.ErrMissingKey } - if err := verifyKeys(oldValue, kv, update, entry); err != nil { + if err := VerifyKeys(oldValue, kv, update, entry); err != nil { return nil, err } return update.GetKeyValue().GetValue(), nil } -// verifyKeys verifies both old and new authorized keys based on the following +// VerifyKeys verifies both old and new authorized keys based on the following // criteria: // 1. At least one signature with a key in the previous entry should exist. // 2. The first mutation should contain at least one signature with a key in // in that mutation. // 3. Signatures with no matching keys are simply ignored. -func verifyKeys(oldValue []byte, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { +func VerifyKeys(oldValue []byte, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { prevEntry := new(tpb.Entry) var verifiers map[string]signatures.Verifier var err error diff --git a/core/mutator/mutator.go b/core/mutator/mutator.go index 68a1a869b..8d648f74d 100644 --- a/core/mutator/mutator.go +++ b/core/mutator/mutator.go @@ -47,7 +47,7 @@ var ( // Mutator verifies mutations and transforms values in the map. type Mutator interface { - // CheckMutation verifies that this is a valid mutation for this item and + // Mutate verifies that this is a valid mutation for this item and // applies mutation to value. Mutate(value, mutation []byte) ([]byte, error) } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go index 2b1537acf..15a434368 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go @@ -29,6 +29,8 @@ It has these top-level messages: UpdateEntryResponse GetMutationsRequest GetMutationsResponse + GetDomainInfoRequest + GetDomainInfoResponse GetMonitoringRequest InvalidMutation NotMatchingMapRootProof @@ -39,6 +41,7 @@ package keytransparency_v1_types import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import keyspb "github.com/google/trillian/crypto/keyspb" import sigpb "github.com/google/trillian/crypto/sigpb" import trillian "github.com/google/trillian" import trillian1 "github.com/google/trillian" @@ -760,6 +763,52 @@ func (m *GetMutationsResponse) GetNextPageToken() string { return "" } +// GetDomainInfoRequest contains an empty request to query the GetDomainInfo +// APIs. +type GetDomainInfoRequest struct { +} + +func (m *GetDomainInfoRequest) Reset() { *m = GetDomainInfoRequest{} } +func (m *GetDomainInfoRequest) String() string { return proto.CompactTextString(m) } +func (*GetDomainInfoRequest) ProtoMessage() {} +func (*GetDomainInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +// GetDomainInfoResponse contains the results of GetDomainInfo APIs. +type GetDomainInfoResponse struct { + // Log contains the Log-Tree's info. + Log *trillian.Tree `protobuf:"bytes,1,opt,name=log" json:"log,omitempty"` + // Map contains the Map-Tree's info. + Map *trillian.Tree `protobuf:"bytes,2,opt,name=map" json:"map,omitempty"` + // Vrf contains the VRF public key. + Vrf *keyspb.PublicKey `protobuf:"bytes,3,opt,name=vrf" json:"vrf,omitempty"` +} + +func (m *GetDomainInfoResponse) Reset() { *m = GetDomainInfoResponse{} } +func (m *GetDomainInfoResponse) String() string { return proto.CompactTextString(m) } +func (*GetDomainInfoResponse) ProtoMessage() {} +func (*GetDomainInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +func (m *GetDomainInfoResponse) GetLog() *trillian.Tree { + if m != nil { + return m.Log + } + return nil +} + +func (m *GetDomainInfoResponse) GetMap() *trillian.Tree { + if m != nil { + return m.Map + } + return nil +} + +func (m *GetDomainInfoResponse) GetVrf() *keyspb.PublicKey { + if m != nil { + return m.Vrf + } + return nil +} + // GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. type GetMonitoringRequest struct { // start specifies the start epoch number from which monitoring results will @@ -770,7 +819,7 @@ type GetMonitoringRequest struct { func (m *GetMonitoringRequest) Reset() { *m = GetMonitoringRequest{} } func (m *GetMonitoringRequest) String() string { return proto.CompactTextString(m) } func (*GetMonitoringRequest) ProtoMessage() {} -func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *GetMonitoringRequest) GetStart() int64 { if m != nil { @@ -791,7 +840,7 @@ type InvalidMutation struct { func (m *InvalidMutation) Reset() { *m = InvalidMutation{} } func (m *InvalidMutation) String() string { return proto.CompactTextString(m) } func (*InvalidMutation) ProtoMessage() {} -func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *InvalidMutation) GetOldLeaf() *trillian1.MapLeafInclusion { if m != nil { @@ -823,7 +872,7 @@ type NotMatchingMapRootProof struct { func (m *NotMatchingMapRootProof) Reset() { *m = NotMatchingMapRootProof{} } func (m *NotMatchingMapRootProof) String() string { return proto.CompactTextString(m) } func (*NotMatchingMapRootProof) ProtoMessage() {} -func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *NotMatchingMapRootProof) GetMapRoot() *trillian.SignedMapRoot { if m != nil { @@ -851,25 +900,33 @@ type GetMonitoringResponse struct { // monitor's key on success. If the checks were not successful the // smr will be empty. The epochs are encoded into the smr map_revision. Smr *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=smr" json:"smr,omitempty"` + // seen_timestamp_nanos contains the time in nanoseconds where this particular + // signed map root was retrieved and processed. The actual timestamp of the + // smr returned by the server is contained in above smr field. + SeenTimestampNanos int64 `protobuf:"varint,2,opt,name=seen_timestamp_nanos,json=seenTimestampNanos" json:"seen_timestamp_nanos,omitempty"` // isValid signals if all verification steps for the requested epoch passed // or not. - IsValid bool `protobuf:"varint,2,opt,name=isValid" json:"isValid,omitempty"` - // invalidRootSigProof contains the signed map root received by the + IsValid bool `protobuf:"varint,3,opt,name=isValid" json:"isValid,omitempty"` + // invalidMapSigProof contains the signed map root received by the // key-transparency server, if and only if the key-server's signature was // invalid. - InvalidRootSigProof *trillian.SignedMapRoot `protobuf:"bytes,3,opt,name=invalidRootSigProof" json:"invalidRootSigProof,omitempty"` + InvalidMapSigProof *trillian.SignedMapRoot `protobuf:"bytes,4,opt,name=invalidMapSigProof" json:"invalidMapSigProof,omitempty"` + // invalidLogSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + InvalidLogSigProof *trillian.SignedLogRoot `protobuf:"bytes,5,opt,name=invalidLogSigProof" json:"invalidLogSigProof,omitempty"` // invalidMutation contains data to reproduce that there was an invalid // mutation from epoch e to epoch e+1 - InvalidMutation *InvalidMutation `protobuf:"bytes,4,opt,name=invalidMutation" json:"invalidMutation,omitempty"` + InvalidMutation *InvalidMutation `protobuf:"bytes,6,opt,name=invalidMutation" json:"invalidMutation,omitempty"` // NotMatchingMapRoot contains all data to reproduce that the set of mutations // does not produce observed new map root. - NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,5,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` + NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,7,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` } func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } func (m *GetMonitoringResponse) String() string { return proto.CompactTextString(m) } func (*GetMonitoringResponse) ProtoMessage() {} -func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { if m != nil { @@ -878,6 +935,13 @@ func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { return nil } +func (m *GetMonitoringResponse) GetSeenTimestampNanos() int64 { + if m != nil { + return m.SeenTimestampNanos + } + return 0 +} + func (m *GetMonitoringResponse) GetIsValid() bool { if m != nil { return m.IsValid @@ -885,9 +949,16 @@ func (m *GetMonitoringResponse) GetIsValid() bool { return false } -func (m *GetMonitoringResponse) GetInvalidRootSigProof() *trillian.SignedMapRoot { +func (m *GetMonitoringResponse) GetInvalidMapSigProof() *trillian.SignedMapRoot { + if m != nil { + return m.InvalidMapSigProof + } + return nil +} + +func (m *GetMonitoringResponse) GetInvalidLogSigProof() *trillian.SignedLogRoot { if m != nil { - return m.InvalidRootSigProof + return m.InvalidLogSigProof } return nil } @@ -922,6 +993,8 @@ func init() { proto.RegisterType((*UpdateEntryResponse)(nil), "keytransparency.v1.types.UpdateEntryResponse") proto.RegisterType((*GetMutationsRequest)(nil), "keytransparency.v1.types.GetMutationsRequest") proto.RegisterType((*GetMutationsResponse)(nil), "keytransparency.v1.types.GetMutationsResponse") + proto.RegisterType((*GetDomainInfoRequest)(nil), "keytransparency.v1.types.GetDomainInfoRequest") + proto.RegisterType((*GetDomainInfoResponse)(nil), "keytransparency.v1.types.GetDomainInfoResponse") proto.RegisterType((*GetMonitoringRequest)(nil), "keytransparency.v1.types.GetMonitoringRequest") proto.RegisterType((*InvalidMutation)(nil), "keytransparency.v1.types.InvalidMutation") proto.RegisterType((*NotMatchingMapRootProof)(nil), "keytransparency.v1.types.NotMatchingMapRootProof") @@ -931,81 +1004,88 @@ func init() { func init() { proto.RegisterFile("keytransparency_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1204 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xdd, 0x6e, 0xdb, 0x36, - 0x14, 0xae, 0xec, 0x38, 0x96, 0x4f, 0xd2, 0xba, 0x60, 0xd3, 0x46, 0xcb, 0xd0, 0xa2, 0x50, 0xb1, - 0xad, 0x1d, 0x0a, 0xa7, 0x51, 0x91, 0x76, 0xed, 0x2e, 0xd6, 0xb5, 0x1b, 0x9a, 0x20, 0xc9, 0x10, - 0xd0, 0x6d, 0x76, 0x29, 0x30, 0x16, 0xad, 0x10, 0x91, 0x45, 0x4d, 0xa4, 0xdc, 0xaa, 0xc0, 0xb0, - 0x17, 0x18, 0x30, 0x60, 0xcf, 0xb0, 0x67, 0xd8, 0xed, 0x2e, 0xf6, 0x16, 0xbb, 0xd9, 0xab, 0x0c, - 0x24, 0x25, 0x5b, 0x76, 0xfd, 0x93, 0xf6, 0x62, 0x37, 0x01, 0x79, 0x74, 0x3e, 0x9e, 0x73, 0xbe, - 0xf3, 0x1d, 0xd2, 0x81, 0x5b, 0xe7, 0x34, 0x97, 0x29, 0x89, 0x45, 0x42, 0x52, 0x1a, 0xf7, 0x72, - 0x7f, 0xb8, 0xe3, 0xcb, 0x3c, 0xa1, 0xa2, 0x93, 0xa4, 0x5c, 0x72, 0xe4, 0x4c, 0x7d, 0xef, 0x0c, - 0x77, 0x3a, 0xfa, 0xfb, 0xd6, 0xc3, 0x90, 0xc9, 0xb3, 0xec, 0xb4, 0xd3, 0xe3, 0x83, 0xed, 0x90, - 0xf3, 0x30, 0xa2, 0xdb, 0x32, 0x65, 0x51, 0xc4, 0x48, 0xbc, 0xdd, 0x4b, 0xf3, 0x44, 0xf2, 0x6d, - 0xc1, 0xc2, 0xe4, 0xd4, 0xfc, 0x35, 0xc7, 0x6d, 0xdd, 0x5b, 0x00, 0x2a, 0x17, 0x85, 0xeb, 0xce, - 0x05, 0x5c, 0xfd, 0x01, 0x49, 0x7c, 0x92, 0x30, 0x03, 0x71, 0x77, 0xa0, 0xf5, 0x82, 0x0f, 0x06, - 0x4c, 0x4a, 0x1a, 0xa0, 0xab, 0x50, 0x3f, 0xa7, 0xb9, 0x63, 0xdd, 0xb6, 0xee, 0xae, 0x63, 0xb5, - 0x44, 0x08, 0x56, 0x02, 0x22, 0x89, 0x53, 0xd3, 0x26, 0xbd, 0x76, 0x7f, 0xb5, 0x60, 0xed, 0xfb, - 0x58, 0xa6, 0xf9, 0xeb, 0x24, 0x20, 0x92, 0xa2, 0xa7, 0xb0, 0x9a, 0xe9, 0x95, 0xf6, 0x5a, 0xf3, - 0xdc, 0xce, 0x3c, 0x02, 0x3a, 0x5d, 0x16, 0xc6, 0x34, 0x38, 0x38, 0xc1, 0x05, 0x02, 0x7d, 0x0b, - 0xad, 0x5e, 0x19, 0xde, 0xa9, 0x6b, 0xf8, 0x9d, 0xf9, 0xf0, 0x51, 0xa6, 0x78, 0x8c, 0x72, 0x33, - 0x68, 0xe8, 0x6c, 0xd0, 0x2d, 0x00, 0x63, 0x1d, 0xd0, 0x58, 0x16, 0x45, 0x54, 0x2c, 0xe8, 0x10, - 0xda, 0x24, 0x93, 0x67, 0x3c, 0x65, 0xef, 0x68, 0xe0, 0x9f, 0xd3, 0x5c, 0x38, 0xb5, 0xdb, 0xf5, - 0xc5, 0x11, 0x8f, 0xb3, 0xd3, 0x88, 0xf5, 0x0e, 0x68, 0x8e, 0xaf, 0x8c, 0xb1, 0x07, 0x34, 0x17, - 0xee, 0x1f, 0x16, 0xb4, 0x46, 0x5f, 0xd1, 0x16, 0x34, 0x69, 0xe0, 0xed, 0xee, 0xee, 0x3c, 0x31, - 0x81, 0xf7, 0x2e, 0xe1, 0xd2, 0x80, 0xbe, 0x86, 0x4f, 0x52, 0x41, 0xfc, 0x21, 0x4d, 0x59, 0x3f, - 0x67, 0x71, 0xe8, 0x8b, 0x33, 0xe2, 0xed, 0x3e, 0xf2, 0x1f, 0x3e, 0x78, 0xec, 0x19, 0x62, 0xf7, - 0x2e, 0xe1, 0x1b, 0xa9, 0x20, 0x27, 0xa5, 0x47, 0x57, 0x3b, 0xa8, 0xef, 0xc8, 0x83, 0x0d, 0xda, - 0x0b, 0x26, 0xe0, 0x89, 0xb7, 0xfb, 0x48, 0x73, 0xa5, 0x70, 0x48, 0x7f, 0x1d, 0x21, 0x8f, 0xbd, - 0xdd, 0x47, 0xcf, 0x01, 0xec, 0x73, 0x9a, 0x6b, 0x4d, 0xba, 0x1e, 0xd8, 0x07, 0x34, 0x3f, 0x21, - 0x51, 0x46, 0x67, 0xb4, 0x77, 0x03, 0x1a, 0x43, 0xf5, 0xa9, 0xe8, 0xaf, 0xd9, 0xb8, 0xbf, 0xd7, - 0xc0, 0x2e, 0x3b, 0x85, 0xbe, 0x81, 0x96, 0x3a, 0xcc, 0xb8, 0x59, 0xcb, 0x1a, 0x5c, 0xc6, 0xc2, - 0x2a, 0x03, 0x13, 0x15, 0x03, 0x08, 0x16, 0xc6, 0x44, 0x66, 0x29, 0x2d, 0x19, 0xf7, 0x96, 0x4b, - 0x44, 0x2f, 0x0c, 0x48, 0xb7, 0x17, 0x57, 0x4e, 0x41, 0x5b, 0x60, 0x27, 0x29, 0x1d, 0x32, 0x9e, - 0x09, 0xc3, 0x04, 0x1e, 0xed, 0xb7, 0x5e, 0x43, 0x7b, 0x0a, 0x5a, 0x2d, 0xbc, 0x65, 0x0a, 0xbf, - 0x5f, 0x2d, 0x7c, 0xcd, 0xbb, 0xd1, 0x31, 0x13, 0xf7, 0x1d, 0x0b, 0x99, 0x24, 0x51, 0x94, 0x9b, - 0x2c, 0x0a, 0x42, 0x9e, 0xd6, 0xbe, 0xb2, 0xdc, 0xb7, 0x60, 0x1f, 0x65, 0x92, 0x48, 0xc6, 0xe3, - 0x8a, 0xe2, 0xad, 0x0f, 0x56, 0xfc, 0x03, 0x68, 0x24, 0x29, 0xe7, 0xfd, 0x22, 0xf2, 0x56, 0x67, - 0x34, 0xc3, 0x47, 0x24, 0x39, 0xa4, 0xa4, 0xbf, 0x1f, 0xf7, 0xa2, 0x4c, 0x30, 0x1e, 0x63, 0xe3, - 0xe8, 0x32, 0x68, 0xbf, 0xa4, 0xd2, 0x90, 0x40, 0x7f, 0xca, 0xa8, 0x90, 0x68, 0x13, 0x9a, 0x99, - 0xa0, 0xa9, 0xcf, 0x82, 0xa2, 0xa8, 0x55, 0xb5, 0xdd, 0x0f, 0xd0, 0x75, 0x58, 0x25, 0x49, 0xa2, - 0xec, 0x35, 0x6d, 0x6f, 0x90, 0x24, 0xd9, 0x0f, 0xd0, 0xe7, 0xd0, 0xee, 0xb3, 0x54, 0x48, 0x5f, - 0xa6, 0x94, 0xfa, 0x82, 0xbd, 0xa3, 0x9a, 0xb6, 0x3a, 0xbe, 0xac, 0xcd, 0xaf, 0x52, 0x4a, 0xbb, - 0xec, 0x1d, 0x75, 0xff, 0xa9, 0xc1, 0xd5, 0x71, 0x2c, 0x91, 0xf0, 0x58, 0x50, 0xf4, 0x29, 0xb4, - 0x86, 0x69, 0xdf, 0x37, 0x59, 0x1b, 0xf1, 0xd8, 0xc3, 0xb4, 0x7f, 0xac, 0xf6, 0x93, 0x03, 0x5c, - 0xfb, 0x98, 0x01, 0x46, 0x4f, 0x00, 0x22, 0x4a, 0xca, 0x00, 0xf5, 0xa5, 0xb4, 0xb4, 0x94, 0xb7, - 0x89, 0x7e, 0x0f, 0xea, 0x62, 0x90, 0x3a, 0x2b, 0x1a, 0xb3, 0x39, 0xc6, 0x18, 0xd6, 0x8f, 0x48, - 0x82, 0x39, 0x97, 0x58, 0xf9, 0x20, 0x0f, 0xec, 0x88, 0x87, 0x7e, 0xca, 0xb9, 0x74, 0x1a, 0xb3, - 0xfd, 0x0f, 0x79, 0xa8, 0xfd, 0x9b, 0x91, 0x59, 0xa0, 0x2f, 0xa0, 0xad, 0x30, 0x3d, 0x1e, 0x0b, - 0x26, 0xa4, 0x2a, 0xc5, 0x59, 0xbd, 0x5d, 0xbf, 0xbb, 0x8e, 0xaf, 0x44, 0x3c, 0x7c, 0x31, 0xb6, - 0xa2, 0x3b, 0x70, 0x59, 0x39, 0xb2, 0x32, 0x47, 0xa7, 0xa9, 0xdd, 0xd6, 0x23, 0x1e, 0x8e, 0xf2, - 0x56, 0x37, 0xc6, 0xe6, 0x21, 0x13, 0x86, 0xdd, 0x3d, 0x26, 0x24, 0xbf, 0x40, 0x43, 0x37, 0xa0, - 0x21, 0x24, 0x49, 0xa5, 0xe6, 0xb6, 0x8e, 0xcd, 0x46, 0xb5, 0x24, 0x21, 0x61, 0xa5, 0x93, 0x0d, - 0x6c, 0x2b, 0x83, 0x6a, 0x62, 0x45, 0x03, 0x2b, 0x4b, 0x34, 0xd0, 0x98, 0xa5, 0x81, 0x9f, 0xc1, - 0x79, 0x3f, 0xcb, 0x42, 0x0a, 0xcf, 0x61, 0x55, 0x4f, 0x84, 0x70, 0x2c, 0x3d, 0xc7, 0x5f, 0xce, - 0x6f, 0xf5, 0xb4, 0x8c, 0x70, 0x81, 0x44, 0x37, 0x01, 0x62, 0xfa, 0x56, 0xfa, 0xd5, 0xb2, 0x5a, - 0xca, 0xd2, 0x55, 0x06, 0xf7, 0x4f, 0x0b, 0x90, 0x79, 0x58, 0xfe, 0x0f, 0xc5, 0xa3, 0x3d, 0x58, - 0xa7, 0x2a, 0x8e, 0x5f, 0x0c, 0xb4, 0x91, 0xd2, 0x67, 0xf3, 0xeb, 0xaa, 0xbc, 0x7c, 0x78, 0x8d, - 0x8e, 0x37, 0xee, 0x8f, 0x70, 0x6d, 0x22, 0xef, 0x82, 0xb2, 0x67, 0xe5, 0xbc, 0x9b, 0xab, 0xe2, - 0x43, 0x18, 0x2b, 0xe6, 0xff, 0x37, 0x0b, 0xae, 0xbd, 0xa4, 0xb2, 0xbc, 0x7d, 0x44, 0x49, 0xc9, - 0x06, 0x34, 0x68, 0xc2, 0x7b, 0x67, 0xfa, 0xe4, 0x3a, 0x36, 0x9b, 0x59, 0x85, 0xd7, 0x66, 0x15, - 0x7e, 0x13, 0x40, 0x4b, 0x48, 0xf2, 0x73, 0x1a, 0x6b, 0x6e, 0x5a, 0x58, 0x8b, 0xea, 0x95, 0x32, - 0x4c, 0x2a, 0x6c, 0x65, 0x52, 0x61, 0xee, 0xdf, 0x35, 0xd8, 0x98, 0xcc, 0xa8, 0x28, 0x76, 0x76, - 0x4a, 0xc5, 0x94, 0xd6, 0x3e, 0x70, 0x4a, 0xeb, 0x1f, 0x3f, 0xa5, 0x2b, 0x17, 0x9b, 0xd2, 0xc6, - 0xfb, 0x53, 0x8a, 0x9e, 0x41, 0x6b, 0x50, 0xd6, 0xa5, 0xa7, 0x7d, 0xe1, 0xf5, 0x5e, 0x52, 0x80, - 0xc7, 0x20, 0xd5, 0x01, 0x2d, 0xf0, 0x0a, 0xbd, 0x4d, 0x4d, 0xef, 0x65, 0x65, 0x3e, 0x2e, 0x29, - 0x76, 0xef, 0x1b, 0x12, 0x79, 0xcc, 0x24, 0x4f, 0x59, 0x1c, 0x56, 0xfa, 0x6a, 0x66, 0xc3, 0xaa, - 0x8c, 0xbc, 0xfb, 0x0b, 0xb4, 0xf7, 0xe3, 0x21, 0x89, 0x58, 0x30, 0x7a, 0x86, 0x76, 0xc1, 0xe6, - 0x51, 0xe0, 0xab, 0xeb, 0xb0, 0x50, 0xd7, 0xa2, 0x6b, 0xb3, 0xc9, 0xa3, 0x40, 0x59, 0x14, 0x2c, - 0xa6, 0x6f, 0x0c, 0x6c, 0xf9, 0x23, 0xd4, 0x8c, 0xe9, 0x1b, 0x65, 0x71, 0xff, 0xb2, 0x60, 0xf3, - 0x07, 0x2e, 0x8f, 0x88, 0xec, 0x9d, 0xb1, 0x38, 0x2c, 0xda, 0x66, 0xee, 0x61, 0x0f, 0x6c, 0xf5, - 0xb3, 0x52, 0xb7, 0xcd, 0x5a, 0xdc, 0xe6, 0xe6, 0xc0, 0x2c, 0xd0, 0x63, 0x68, 0x95, 0xd9, 0x97, - 0x3f, 0x0b, 0x16, 0xe5, 0x61, 0x17, 0xe9, 0x0b, 0x05, 0x2c, 0xf3, 0x57, 0xaf, 0xff, 0x52, 0x60, - 0x51, 0x80, 0x70, 0xff, 0xad, 0xc1, 0xf5, 0x29, 0xc6, 0x0b, 0xdd, 0x16, 0x0a, 0xb5, 0x2e, 0xa0, - 0x50, 0x07, 0x9a, 0x4c, 0x9c, 0xa8, 0x3e, 0x68, 0xf2, 0x6c, 0x5c, 0x6e, 0xd1, 0x3e, 0x5c, 0x63, - 0xa6, 0x43, 0xca, 0xbb, 0xcb, 0xc2, 0xe3, 0xca, 0x83, 0x36, 0xf7, 0xd0, 0x59, 0x18, 0xd4, 0x85, - 0x36, 0x9b, 0x6c, 0x76, 0x71, 0x31, 0xdd, 0x9b, 0x2f, 0xc5, 0x29, 0x75, 0xe0, 0xe9, 0x13, 0x10, - 0x01, 0x14, 0xbf, 0xd7, 0xbf, 0xe2, 0x2d, 0xdc, 0x99, 0x7f, 0xee, 0x9c, 0x9e, 0xe3, 0x19, 0x87, - 0x9d, 0xae, 0xea, 0x7f, 0x2a, 0x1e, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x8d, 0x71, 0xa8, - 0x23, 0x0d, 0x00, 0x00, + // 1317 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xdd, 0x6e, 0x13, 0x47, + 0x14, 0x66, 0xed, 0x38, 0xb6, 0x4f, 0x02, 0xa6, 0x43, 0x20, 0x6e, 0x2a, 0x50, 0xb4, 0xa8, 0x2d, + 0x54, 0xc8, 0x21, 0x46, 0x86, 0x42, 0x2f, 0x4a, 0x81, 0x8a, 0x44, 0x49, 0x50, 0x34, 0x81, 0xf4, + 0x72, 0x35, 0xb1, 0xc7, 0x9b, 0x51, 0x76, 0x67, 0xb6, 0x3b, 0x63, 0xc3, 0x22, 0x55, 0xed, 0x03, + 0x54, 0xaa, 0xd4, 0x67, 0xe8, 0x33, 0xf4, 0xb6, 0x17, 0x7d, 0x89, 0xaa, 0x4f, 0x53, 0xcd, 0xcf, + 0xda, 0xeb, 0xc4, 0x8e, 0x03, 0x17, 0xbd, 0x49, 0x66, 0xce, 0x9c, 0x6f, 0xe6, 0x9c, 0xef, 0x7c, + 0x67, 0x66, 0x0d, 0xb7, 0x4e, 0x68, 0xa6, 0x52, 0xc2, 0x65, 0x42, 0x52, 0xca, 0xbb, 0x59, 0x30, + 0xdc, 0x0c, 0x54, 0x96, 0x50, 0xd9, 0x4a, 0x52, 0xa1, 0x04, 0x6a, 0x9e, 0x5a, 0x6f, 0x0d, 0x37, + 0x5b, 0x66, 0x7d, 0xad, 0x13, 0x32, 0x75, 0x3c, 0x38, 0x6a, 0x75, 0x45, 0xbc, 0x11, 0x0a, 0x11, + 0x46, 0x74, 0x43, 0xa5, 0x2c, 0x8a, 0x18, 0xe1, 0x1b, 0xdd, 0x34, 0x4b, 0x94, 0xd8, 0x38, 0xa1, + 0x99, 0x4c, 0x8e, 0xdc, 0x3f, 0xbb, 0xe1, 0xda, 0x83, 0xf9, 0x30, 0xc9, 0xc2, 0xe4, 0xc8, 0xfe, + 0x75, 0xa0, 0xbb, 0xe7, 0x80, 0xf2, 0x81, 0x73, 0xdd, 0xbc, 0x80, 0x6b, 0x10, 0x93, 0x24, 0x20, + 0x09, 0xb3, 0x10, 0x7f, 0x13, 0xea, 0xcf, 0x45, 0x1c, 0x33, 0xa5, 0x68, 0x0f, 0x5d, 0x85, 0xf2, + 0x09, 0xcd, 0x9a, 0xde, 0xba, 0x77, 0x67, 0x19, 0xeb, 0x21, 0x42, 0xb0, 0xd0, 0x23, 0x8a, 0x34, + 0x4b, 0xc6, 0x64, 0xc6, 0xfe, 0xaf, 0x1e, 0x2c, 0x7d, 0xcf, 0x55, 0x9a, 0xbd, 0x49, 0x7a, 0x44, + 0x51, 0xf4, 0x04, 0x16, 0x07, 0x66, 0x64, 0xbc, 0x96, 0xda, 0x7e, 0x6b, 0x16, 0x6f, 0xad, 0x03, + 0x16, 0x72, 0xda, 0xdb, 0x39, 0xc4, 0x0e, 0x81, 0xbe, 0x83, 0x7a, 0x37, 0x3f, 0xbe, 0x59, 0x36, + 0xf0, 0xdb, 0xb3, 0xe1, 0xa3, 0x48, 0xf1, 0x18, 0xe5, 0x0f, 0xa0, 0x62, 0xa2, 0x41, 0xb7, 0x00, + 0xac, 0x35, 0xa6, 0x5c, 0xb9, 0x24, 0x0a, 0x16, 0xb4, 0x0b, 0x0d, 0x32, 0x50, 0xc7, 0x22, 0x65, + 0xef, 0x69, 0x2f, 0xd0, 0x85, 0x69, 0x96, 0xd6, 0xcb, 0xe7, 0x9f, 0xb8, 0x3f, 0x38, 0x8a, 0x58, + 0x77, 0x87, 0x66, 0xf8, 0xca, 0x18, 0xbb, 0x43, 0x33, 0xe9, 0xff, 0xe1, 0x41, 0x7d, 0xb4, 0x8a, + 0xd6, 0xa0, 0x4a, 0x7b, 0xed, 0x4e, 0x67, 0xf3, 0xb1, 0x3d, 0x78, 0xeb, 0x12, 0xce, 0x0d, 0xe8, + 0x1b, 0xf8, 0x34, 0x95, 0x24, 0x18, 0xd2, 0x94, 0xf5, 0x33, 0xc6, 0xc3, 0x40, 0x1e, 0x93, 0x76, + 0xe7, 0x61, 0xf0, 0xe0, 0xfe, 0xa3, 0xb6, 0x25, 0x76, 0xeb, 0x12, 0xbe, 0x91, 0x4a, 0x72, 0x98, + 0x7b, 0x1c, 0x18, 0x07, 0xbd, 0x8e, 0xda, 0xb0, 0x42, 0xbb, 0xbd, 0x09, 0x78, 0xd2, 0xee, 0x3c, + 0x34, 0x5c, 0x69, 0x1c, 0x32, 0xab, 0x23, 0xe4, 0x7e, 0xbb, 0xf3, 0xf0, 0x19, 0x40, 0xed, 0x84, + 0x66, 0x46, 0xca, 0x7e, 0x1b, 0x6a, 0x3b, 0x34, 0x3b, 0x24, 0xd1, 0x80, 0x4e, 0x29, 0xef, 0x0a, + 0x54, 0x86, 0x7a, 0xc9, 0xd5, 0xd7, 0x4e, 0xfc, 0xdf, 0x4b, 0x50, 0xcb, 0x2b, 0x85, 0xbe, 0x85, + 0xba, 0xde, 0xcc, 0xba, 0x79, 0xf3, 0x0a, 0x9c, 0x9f, 0x85, 0x75, 0x04, 0xf6, 0x54, 0x0c, 0x20, + 0x59, 0xc8, 0x89, 0x1a, 0xa4, 0x34, 0x67, 0xbc, 0x3d, 0x5f, 0x22, 0x66, 0x60, 0x41, 0xa6, 0xbc, + 0xb8, 0xb0, 0x0b, 0x5a, 0x83, 0x5a, 0x92, 0xd2, 0x21, 0x13, 0x03, 0x69, 0x99, 0xc0, 0xa3, 0xf9, + 0xda, 0x1b, 0x68, 0x9c, 0x82, 0x16, 0x13, 0xaf, 0xdb, 0xc4, 0xef, 0x15, 0x13, 0x5f, 0x6a, 0xdf, + 0x68, 0xd9, 0x8e, 0x7b, 0xc1, 0x42, 0xa6, 0x48, 0x14, 0x65, 0x36, 0x0a, 0x47, 0xc8, 0x93, 0xd2, + 0xd7, 0x9e, 0xff, 0x0e, 0x6a, 0x7b, 0x03, 0x45, 0x14, 0x13, 0xbc, 0xa0, 0x78, 0xef, 0x83, 0x15, + 0x7f, 0x1f, 0x2a, 0x49, 0x2a, 0x44, 0xdf, 0x9d, 0xbc, 0xd6, 0x1a, 0xf5, 0xf0, 0x1e, 0x49, 0x76, + 0x29, 0xe9, 0x6f, 0xf3, 0x6e, 0x34, 0x90, 0x4c, 0x70, 0x6c, 0x1d, 0x7d, 0x06, 0x8d, 0x97, 0x54, + 0x59, 0x12, 0xe8, 0x8f, 0x03, 0x2a, 0x15, 0x5a, 0x85, 0xea, 0x40, 0xd2, 0x34, 0x60, 0x3d, 0x97, + 0xd4, 0xa2, 0x9e, 0x6e, 0xf7, 0xd0, 0x75, 0x58, 0x24, 0x49, 0xa2, 0xed, 0x25, 0x63, 0xaf, 0x90, + 0x24, 0xd9, 0xee, 0xa1, 0x2f, 0xa0, 0xd1, 0x67, 0xa9, 0x54, 0x81, 0x4a, 0x29, 0x0d, 0x24, 0x7b, + 0x4f, 0x0d, 0x6d, 0x65, 0x7c, 0xd9, 0x98, 0x5f, 0xa7, 0x94, 0x1e, 0xb0, 0xf7, 0xd4, 0xff, 0xb7, + 0x04, 0x57, 0xc7, 0x67, 0xc9, 0x44, 0x70, 0x49, 0xd1, 0x67, 0x50, 0x1f, 0xa6, 0xfd, 0xc0, 0x46, + 0x6d, 0xc5, 0x53, 0x1b, 0xa6, 0xfd, 0x7d, 0x3d, 0x9f, 0x6c, 0xe0, 0xd2, 0xc7, 0x34, 0x30, 0x7a, + 0x0c, 0x10, 0x51, 0x92, 0x1f, 0x50, 0x9e, 0x4b, 0x4b, 0x5d, 0x7b, 0xdb, 0xd3, 0xef, 0x42, 0x59, + 0xc6, 0x69, 0x73, 0xc1, 0x60, 0x56, 0xc7, 0x18, 0xcb, 0xfa, 0x1e, 0x49, 0xb0, 0x10, 0x0a, 0x6b, + 0x1f, 0xd4, 0x86, 0x5a, 0x24, 0xc2, 0x20, 0x15, 0x42, 0x35, 0x2b, 0xd3, 0xfd, 0x77, 0x45, 0x68, + 0xfc, 0xab, 0x91, 0x1d, 0xa0, 0x2f, 0xa1, 0xa1, 0x31, 0x5d, 0xc1, 0x25, 0x93, 0x4a, 0xa7, 0xd2, + 0x5c, 0x5c, 0x2f, 0xdf, 0x59, 0xc6, 0x57, 0x22, 0x11, 0x3e, 0x1f, 0x5b, 0xd1, 0x6d, 0xb8, 0xac, + 0x1d, 0x59, 0x1e, 0x63, 0xb3, 0x6a, 0xdc, 0x96, 0x23, 0x11, 0x8e, 0xe2, 0xd6, 0x37, 0xc6, 0xea, + 0x2e, 0x93, 0x96, 0xdd, 0x2d, 0x26, 0x95, 0xb8, 0x40, 0x41, 0x57, 0xa0, 0x22, 0x15, 0x49, 0x95, + 0xe1, 0xb6, 0x8c, 0xed, 0x44, 0x97, 0x24, 0x21, 0x61, 0xa1, 0x92, 0x15, 0x5c, 0xd3, 0x06, 0x5d, + 0xc4, 0x82, 0x06, 0x16, 0xe6, 0x68, 0xa0, 0x32, 0x4d, 0x03, 0x3f, 0x41, 0xf3, 0x6c, 0x94, 0x4e, + 0x0a, 0xcf, 0x60, 0xd1, 0x74, 0x84, 0x6c, 0x7a, 0xa6, 0x8f, 0xbf, 0x9a, 0x5d, 0xea, 0xd3, 0x32, + 0xc2, 0x0e, 0x89, 0x6e, 0x02, 0x70, 0xfa, 0x4e, 0x05, 0xc5, 0xb4, 0xea, 0xda, 0x72, 0xa0, 0x0d, + 0xfe, 0x9f, 0x1e, 0x20, 0xfb, 0xb0, 0xfc, 0x1f, 0x8a, 0x47, 0x5b, 0xb0, 0x4c, 0xf5, 0x39, 0x81, + 0x6b, 0x68, 0x2b, 0xa5, 0xcf, 0x67, 0xe7, 0x55, 0x78, 0xf9, 0xf0, 0x12, 0x1d, 0x4f, 0xfc, 0x1f, + 0xe0, 0xda, 0x44, 0xdc, 0x8e, 0xb2, 0xa7, 0x79, 0xbf, 0xdb, 0xab, 0xe2, 0x43, 0x18, 0x73, 0xfd, + 0xff, 0x9b, 0x07, 0xd7, 0x5e, 0x52, 0x95, 0xdf, 0x3e, 0x32, 0xa7, 0x64, 0x05, 0x2a, 0x34, 0x11, + 0xdd, 0x63, 0xb3, 0x73, 0x19, 0xdb, 0xc9, 0xb4, 0xc4, 0x4b, 0xd3, 0x12, 0xbf, 0x09, 0x60, 0x24, + 0xa4, 0xc4, 0x09, 0xe5, 0x86, 0x9b, 0x3a, 0x36, 0xa2, 0x7a, 0xad, 0x0d, 0x93, 0x0a, 0x5b, 0x98, + 0x54, 0x98, 0xff, 0x77, 0x09, 0x56, 0x26, 0x23, 0x72, 0xc9, 0x4e, 0x0f, 0xc9, 0x75, 0x69, 0xe9, + 0x03, 0xbb, 0xb4, 0xfc, 0xf1, 0x5d, 0xba, 0x70, 0xb1, 0x2e, 0xad, 0x9c, 0xed, 0x52, 0xf4, 0x14, + 0xea, 0x71, 0x9e, 0x97, 0xe9, 0xf6, 0x73, 0xaf, 0xf7, 0x9c, 0x02, 0x3c, 0x06, 0xe9, 0x0a, 0x18, + 0x81, 0x17, 0xe8, 0xad, 0x1a, 0x7a, 0x2f, 0x6b, 0xf3, 0x7e, 0x4e, 0xb1, 0x7f, 0xc3, 0x90, 0xf8, + 0x42, 0xc4, 0x84, 0xf1, 0x6d, 0xde, 0x17, 0xae, 0xae, 0xfe, 0x2f, 0x1e, 0x5c, 0x3f, 0xb5, 0xe0, + 0xe8, 0x5d, 0x87, 0x72, 0x24, 0x42, 0xa7, 0xa4, 0x2b, 0x63, 0x62, 0x74, 0x51, 0xb1, 0x5e, 0xd2, + 0x1e, 0x31, 0x49, 0x1c, 0xd5, 0x67, 0x3c, 0x62, 0x92, 0xa0, 0xdb, 0x50, 0x1e, 0xa6, 0xf9, 0x35, + 0xfb, 0x49, 0xcb, 0x7d, 0x9f, 0x8e, 0xbf, 0x73, 0xf4, 0xaa, 0x7f, 0xcf, 0xd6, 0x57, 0x70, 0xa6, + 0x44, 0xca, 0x78, 0x58, 0x90, 0x9c, 0x6d, 0x5b, 0xaf, 0x70, 0x1b, 0xf9, 0x3f, 0x43, 0x63, 0x9b, + 0x0f, 0x49, 0xc4, 0x7a, 0xa3, 0x17, 0xb2, 0x03, 0x35, 0x11, 0xf5, 0x02, 0x7d, 0x53, 0xbb, 0x70, + 0xcf, 0xbb, 0xd1, 0xab, 0x22, 0xea, 0x69, 0x8b, 0x86, 0x71, 0xfa, 0xd6, 0xc2, 0xe6, 0xbf, 0x8f, + 0x55, 0x4e, 0xdf, 0x6a, 0x8b, 0xff, 0x97, 0x07, 0xab, 0xaf, 0x84, 0xda, 0x23, 0xaa, 0x7b, 0xcc, + 0x78, 0xe8, 0x14, 0x65, 0x9f, 0x88, 0x36, 0xd4, 0xf4, 0x17, 0xaf, 0x51, 0x94, 0x77, 0xbe, 0x02, + 0xab, 0xb1, 0x1d, 0xa0, 0x47, 0x50, 0xcf, 0xa3, 0xcf, 0xbf, 0x58, 0xce, 0x8b, 0xa3, 0xe6, 0xc2, + 0x97, 0x1a, 0x98, 0xc7, 0xaf, 0x3f, 0x4c, 0xe6, 0x02, 0x5d, 0x02, 0xd2, 0xff, 0xa7, 0x6c, 0x6a, + 0x5e, 0x64, 0xdc, 0xd5, 0xdc, 0x35, 0x8f, 0x77, 0x81, 0xe6, 0xb9, 0x0f, 0x2b, 0x92, 0x52, 0x1e, + 0x28, 0x16, 0x53, 0xa9, 0x48, 0x9c, 0x04, 0x9c, 0x70, 0x21, 0x5d, 0xff, 0x23, 0xbd, 0xf6, 0x3a, + 0x5f, 0x7a, 0xa5, 0x57, 0x50, 0x13, 0xaa, 0x4c, 0x1e, 0xea, 0xca, 0x19, 0x41, 0xd4, 0x70, 0x3e, + 0x45, 0x2f, 0x01, 0x31, 0x57, 0x53, 0x92, 0x1c, 0xb0, 0xd0, 0x90, 0x39, 0xef, 0xa1, 0x9d, 0x02, + 0x29, 0x6c, 0xb4, 0x2b, 0xc2, 0xd1, 0x46, 0x73, 0x5e, 0xe0, 0x29, 0x10, 0x74, 0x00, 0x0d, 0x36, + 0xa9, 0xb2, 0xe6, 0xa2, 0xd9, 0xe5, 0xee, 0xec, 0xf6, 0x3c, 0x25, 0x4b, 0x7c, 0x7a, 0x07, 0x44, + 0x00, 0xf1, 0x33, 0xc2, 0x31, 0xed, 0xba, 0xd4, 0xde, 0x9c, 0xbd, 0xef, 0x0c, 0xb1, 0xe1, 0x29, + 0x9b, 0x1d, 0x2d, 0x9a, 0x1f, 0x5a, 0x0f, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xb5, 0xfd, 0xe6, + 0xc1, 0x6e, 0x0e, 0x00, 0x00, } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto index 8520d7d12..8badf84fa 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto @@ -21,10 +21,10 @@ syntax = "proto3"; // associated with it. package keytransparency.v1.types; -import "crypto/keyspb/keyspb.proto"; -import "crypto/sigpb/sigpb.proto"; -import "trillian.proto"; -import "trillian_map_api.proto"; +import "github.com/google/trillian/crypto/keyspb/keyspb.proto"; +import "github.com/google/trillian/crypto/sigpb/sigpb.proto"; +import "github.com/google/trillian/trillian.proto"; +import "github.com/google/trillian/trillian_map_api.proto"; // // Data types. @@ -300,14 +300,18 @@ message GetMonitoringResponse { // isValid signals if all verification steps for the requested epoch passed // or not. bool isValid = 3; - // invalidRootSigProof contains the signed map root received by the + // invalidMapSigProof contains the signed map root received by the // key-transparency server, if and only if the key-server's signature was // invalid. - trillian.SignedMapRoot invalidRootSigProof = 4; + trillian.SignedMapRoot invalidMapSigProof = 4; + // invalidLogSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + trillian.SignedLogRoot invalidLogSigProof = 5; // invalidMutation contains data to reproduce that there was an invalid // mutation from epoch e to epoch e+1 - InvalidMutation invalidMutation = 5; + InvalidMutation invalidMutation = 6; // NotMatchingMapRoot contains all data to reproduce that the set of mutations // does not produce observed new map root. - NotMatchingMapRootProof notMatchingMapRoot = 6; + NotMatchingMapRootProof notMatchingMapRoot = 7; } \ No newline at end of file diff --git a/deploy/kubernetes/keytransparency-deployment.yml.tmpl b/deploy/kubernetes/keytransparency-deployment.yml.tmpl index a9437eb3f..748960368 100644 --- a/deploy/kubernetes/keytransparency-deployment.yml.tmpl +++ b/deploy/kubernetes/keytransparency-deployment.yml.tmpl @@ -136,6 +136,41 @@ spec: selector: run: kt-signer --- +------ + apiVersion: apps/v1beta1 + kind: Deployment + metadata: + name: kt-monitor + spec: + strategy: + type: Recreate + template: + metadata: + labels: + run: kt-monitor + spec: + containers: + - name: kt-monitor + image: us.gcr.io/key-transparency/keytransparency-monitor + ports: + - containerPort: 8099 + name: json-grpc + --- + apiVersion: v1 + kind: Service + metadata: + name: kt-monitor + labels: + run: kt-monitor + spec: + type: NodePort + ports: + - port: 8099 + targetPort: 8099 + name: http + selector: + run: kt-monitor + --- apiVersion: v1 kind: Service metadata: diff --git a/docker-compose.yml b/docker-compose.yml index ff5c6fac1..15fe7d836 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -160,11 +160,13 @@ services: - --addr=0.0.0.0:8099 - --kt-url=kt-server:8080 - --poll-period=5s - - --key=genfiles/server.key - - --cert=genfiles/server.crt + - --tls-key=genfiles/server.key + - --tls-cert=genfiles/server.crt - --sign-key=/kt/p256-monitor_sign-key.pem - --password=towel - - --map-id=$MAP_ID + # TODO(ismail): this needs to be the public-key returned by the createTree operation: + - --map-key=trillian/testdata/map-rpc-server.pubkey.pem + - --log-key=trillian/testdata/log-rpc-server.pubkey.pem - --alsologtostderr - --v=3 image: us.gcr.io/key-transparency/keytransparency-monitor diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 84b795ce3..cb8f079aa 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -20,6 +20,7 @@ package monitor import ( "bytes" + "crypto" "errors" "fmt" "time" @@ -30,15 +31,12 @@ import ( "google.golang.org/grpc/codes" "github.com/google/trillian" - "github.com/google/trillian/crypto" + + tcrypto "github.com/google/trillian/crypto" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - tv "github.com/google/keytransparency/core/tree/sparse/verifier" - mspb "github.com/google/keytransparency/impl/proto/monitor_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" - - "github.com/google/keytransparency/core/tree/sparse" ) // Each page contains pageSize profiles. Each profile contains multiple @@ -47,15 +45,6 @@ import ( const pageSize = 16 var ( - // ErrInvalidMutation occurs when verification failed because of an invalid - // mutation. - ErrInvalidMutation = errors.New("Invalid mutation") - // ErrNotMatchingRoot occurs when the reconstructed root differs from the one - // we received from the server. - ErrNotMatchingRoot = errors.New("Recreated root does not match") - // ErrInvalidSignature occurs when the signature on the observed map root is - // invalid. - ErrInvalidSignature = errors.New("Recreated root does not match") // ErrNothingProcessed occurs when the monitor did not process any mutations / // smrs yet. ErrNothingProcessed = errors.New("did not process any mutations yet") @@ -66,18 +55,23 @@ type Server struct { client mupb.MutationServiceClient pollPeriod time.Duration - tree *tv.Verifier - signer crypto.Signer + mapPubKey crypto.PublicKey + logPubKey crypto.PublicKey + + signer tcrypto.Signer proccessedSMRs []*ktpb.GetMonitoringResponse } // New creates a new instance of the monitor server. -func New(cli mupb.MutationServiceClient, signer crypto.Signer, mapID int64, poll time.Duration) *Server { +func New(cli mupb.MutationServiceClient, + signer tcrypto.Signer, + logPubKey, mapPubKey crypto.PublicKey, + poll time.Duration) *Server { return &Server{ client: cli, pollPeriod: poll, - // TODO TestMapHasher (maphasher.Default) does not implement sparse.TreeHasher: - tree: tv.New(mapID, sparse.CONIKSHasher), + logPubKey: logPubKey, + mapPubKey: mapPubKey, signer: signer, proccessedSMRs: make([]*ktpb.GetMonitoringResponse, 256), } @@ -111,12 +105,6 @@ func (s *Server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringReq return nil, ErrNothingProcessed } -// GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. -func (s *Server) GetSignedMapRootStream(in *ktpb.GetMonitoringRequest, stream mspb.MonitorService_GetSignedMapRootStreamServer) error { - // TODO(ismail): implement stream API - return grpc.Errorf(codes.Unimplemented, "GetSignedMapRootStream is unimplemented") -} - // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns // the monitor's result for a specific map revision. // @@ -130,8 +118,12 @@ func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *ktpb.GetMon } func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { - req := &ktpb.GetMutationsRequest{PageSize: pageSize, Epoch: s.nextRevToQuery()} - resp, err := s.client.GetMutations(ctx, req, opts...) + // TODO(ismail): move everything that does not rely on impl packages (e.g., + // the client here) into core: + resp, err := s.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ + PageSize: pageSize, + Epoch: s.nextRevToQuery(), + }, opts...) if err != nil { return nil, err } @@ -145,90 +137,77 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] return nil, nil } - mutations := make([]*ktpb.Mutation, pageSize*2) - mutations = append(mutations, resp.GetMutations()...) - if err := s.pageMutations(ctx, resp, mutations, opts...); err != nil { + mutations, err := s.pageMutations(ctx, resp, opts...) + if err != nil { glog.Errorf("s.pageMutations(_): %v", err) return nil, err } - - // update seen SMRs: - // TODO: this should be - - rh := resp.GetSmr().GetRootHash() - switch err := s.verifyMutations(mutations, rh); err { + respSmr := resp.GetSmr() + var monitorResp *ktpb.GetMonitoringResponse + switch err := s.verifyResponse(resp, mutations); err { // TODO(ismail): return proper data for failure cases: case ErrInvalidMutation: glog.Errorf("TODO: handle this ErrInvalidMutation properly") - case ErrInvalidSignature: - glog.Errorf("TODO: handle this ErrInvalidSignature properly (return SMR)") + case ErrInvalidMapSignature: + glog.Infof("Signature on map did not verify: %v", err) + monitorResp = &ktpb.GetMonitoringResponse{ + IsValid: false, + SeenTimestampNanos: seen, + InvalidMapSigProof: respSmr, + } + case ErrInvalidLogSignature: + glog.Infof("Signature on log did not verify: %v", err) + monitorResp = &ktpb.GetMonitoringResponse{ + IsValid: false, + SeenTimestampNanos: seen, + InvalidLogSigProof: resp.GetLogRoot(), + } case ErrNotMatchingRoot: glog.Errorf("TODO: handle this ErrNotMatchingRoot properly") case nil: - glog.Info("TODO: Successfully verified.") + // Sign map root with monitor key: + sig, err := s.signer.SignObject(resp.GetSmr().GetRootHash()) + if err != nil { + return nil, fmt.Errorf("s.signer.SignObject(_): %v", err) + } + // update signature on smr: + respSmr.Signature = sig + monitorResp = &ktpb.GetMonitoringResponse{ + Smr: respSmr, + IsValid: true, + SeenTimestampNanos: seen, + } default: glog.Errorf("Unexpected error: %v", err) + // TODO(ismail): Clarify: Would we still want to create a monitor response + // in this case? + return nil, err } - // TODO(ismail): Sign reconstructed Hash instead of response hash: - sig, err := s.signer.SignObject(resp.GetSmr().GetRootHash()) - if err != nil { - return nil, fmt.Errorf("s.signer.SignObject(_): %v", err) - } // Update seen/processed signed map roots: - s.proccessedSMRs = append(s.proccessedSMRs, - &ktpb.GetMonitoringResponse{ - Smr: &trillian.SignedMapRoot{ - Signature: sig, - TimestampNanos: resp.GetSmr().GetTimestampNanos(), - RootHash: resp.GetSmr().GetRootHash(), - Metadata: resp.GetSmr().GetMetadata(), - MapId: resp.GetSmr().GetMapId(), - MapRevision: resp.GetSmr().GetMapRevision(), - }, - IsValid: true, - SeenTimestampNanos: seen, - }) + s.proccessedSMRs = append(s.proccessedSMRs, monitorResp) return mutations, nil } -func (s *Server) verifyMutations(ms []*ktpb.Mutation, expectedRoot []byte) error { - // TODO(ismail): - // For each received mutation in epoch e: - // Verify that the provided leaf’s inclusion proof goes to epoch e -1. - // Verify the mutation’s validity against the previous leaf. - // Compute the new leaf and store the intermediate hashes locally. - // Compute the new root using local intermediate hashes from epoch e. - for _, m := range ms { - idx := m.GetProof().GetLeaf().GetIndex() - nbrs := m.GetProof().GetInclusion() - if err := s.tree.VerifyProof(nbrs, idx, m.GetProof().GetLeaf().GetLeafValue(), - sparse.FromBytes(expectedRoot)); err != nil { - glog.Errorf("VerifyProof(): %v", err) - // TODO return nil, err - } - } - - return nil -} - // pageMutations iterates/pages through all mutations in the case there were // more then maximum pageSize mutations in between epochs. -// It will modify the passed GetMutationsResponse resp and the passed list of -// mutations ms. +// It will modify the passed GetMutationsResponse resp. func (s *Server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsResponse, - ms []*ktpb.Mutation, opts ...grpc.CallOption) error { + opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { + ms := make([]*ktpb.Mutation, pageSize*2) + ms = append(ms, resp.GetMutations()...) + // Query all mutations in the current epoch for resp.GetNextPageToken() != "" { req := &ktpb.GetMutationsRequest{PageSize: pageSize} resp, err := s.client.GetMutations(ctx, req, opts...) if err != nil { - return err + return nil, err } ms = append(ms, resp.GetMutations()...) } - return nil + return ms, nil } func (s *Server) lastSeenSMR() *trillian.SignedMapRoot { diff --git a/impl/monitor/monitor_test.go b/impl/monitor/monitor_test.go index 5c183e74b..b3ea4ced4 100644 --- a/impl/monitor/monitor_test.go +++ b/impl/monitor/monitor_test.go @@ -20,8 +20,6 @@ package monitor import ( "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" "testing" ) @@ -31,12 +29,4 @@ func TestGetSignedMapRoot(t *testing.T) { if got, want := err, ErrNothingProcessed; got != want { t.Errorf("GetSignedMapRoot(_, _): %v, want %v", got, want) } -} - -func TestGetSignedMapRootStream(t *testing.T) { - srv := Server{} - err := srv.GetSignedMapRootStream(nil, nil) - if got, want := grpc.Code(err), codes.Unimplemented; got != want { - t.Errorf("GetSignedMapRootStream(_, _): %v, want %v", got, want) - } -} +} \ No newline at end of file diff --git a/impl/monitor/verify.go b/impl/monitor/verify.go new file mode 100644 index 000000000..23f12541f --- /dev/null +++ b/impl/monitor/verify.go @@ -0,0 +1,86 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package monitor implements the monitor service. A monitor repeatedly polls a +// key-transparency server's Mutations API and signs Map Roots if it could +// reconstruct +// clients can query. +package monitor + +import ( + "errors" + + "github.com/golang/glog" + + // "github.com/google/trillian" + // "github.com/google/trillian/merkle" + + tcrypto "github.com/google/trillian/crypto" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" +) + +var ( + // ErrInvalidMutation occurs when verification failed because of an invalid + // mutation. + ErrInvalidMutation = errors.New("invalid mutation") + // ErrNotMatchingRoot occurs when the reconstructed root differs from the one + // we received from the server. + ErrNotMatchingRoot = errors.New("recreated root does not match") + // ErrInvalidMapSignature occurs when the signature on the observed map root + // is invalid. + ErrInvalidMapSignature = errors.New("invalid signature on map in GetMutationsResponse") + // ErrInvalidMapSignature occurs when the signature on the observed map root + // is invalid. + ErrInvalidLogSignature = errors.New("invalid signature on log in GetMutationsResponse") +) + +// verifyResponse verifies a response received by the GetMutations API. +// Additionally to the response it takes a complete list of mutations. The list +// of received mutations may differ from those included in the initial response +// because of the max. page size. +func (s *Server) verifyResponse(resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { + // verify signature on map root: + if err := tcrypto.VerifyObject(s.mapPubKey, resp.GetSmr(), resp.GetSmr().GetSignature()); err != nil { + glog.Errorf("couldn't verify signature on map root: %v", err) + return ErrInvalidMapSignature + } + // verify signature on log root: + if err := tcrypto.VerifyObject(s.logPubKey, resp.GetSmr(), resp.GetLogRoot().GetSignature()); err != nil { + glog.Errorf("couldn't verify signature on log root: %v", err) + return ErrInvalidLogSignature + } + // TODO verify log-root: + // VerifyRoot(trusted, newRoot *trillian.SignedLogRoot, consistency [][]byte) error + // mapID := resp.GetSmr().GetMapId() + + // TODO: export applyMutations in CreateEpoch / signer.go? + // + // verify that the provided leaf’s inclusion proof goes to epoch e-1. + // + // for each mutation: + //if err := merkle.VerifyMapInclusionProof(mapID, index, + // leafHash, rootHash, proof, hasher); err != nil { + // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) + // return ErrInvalidMutation + //} + + // verify the mutation’s validity against the previous leaf. + + // compute the new leaf and store the intermediate hashes locally. + // compute the new root using local intermediate hashes from epoch e. + // verify rootHash + + return errors.New("TODO: implement verification logic") +} diff --git a/impl/monitor/verify_test.go b/impl/monitor/verify_test.go new file mode 100644 index 000000000..c1d88be8d --- /dev/null +++ b/impl/monitor/verify_test.go @@ -0,0 +1,18 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package monitor + +// TODO(ismail): write extensive tests for verification steps (if not existing +// in trillian) diff --git a/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go b/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go index 8023aec19..671988f09 100644 --- a/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go +++ b/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go @@ -64,12 +64,6 @@ type KeyTransparencyServiceClient interface { // Returns the current user profile. // Clients must retry until this function returns a proof containing the desired value. UpdateEntry(ctx context.Context, in *keytransparency_v1_types.UpdateEntryRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.UpdateEntryResponse, error) - // GetDomainInfo returns all info tied to the specified domain. - // - // This API to get all necessary data needed to verify a particular - // key-server. Data contains for instance the tree-info, like for instance the - // log-/map-id and the corresponding public-keys. - GetDomainInfo(ctx context.Context, in *keytransparency_v1_types.GetDomainInfoRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetDomainInfoResponse, error) } type keyTransparencyServiceClient struct { @@ -107,15 +101,6 @@ func (c *keyTransparencyServiceClient) UpdateEntry(ctx context.Context, in *keyt return out, nil } -func (c *keyTransparencyServiceClient) GetDomainInfo(ctx context.Context, in *keytransparency_v1_types.GetDomainInfoRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetDomainInfoResponse, error) { - out := new(keytransparency_v1_types.GetDomainInfoResponse) - err := grpc.Invoke(ctx, "/keytransparency.v1.service.KeyTransparencyService/GetDomainInfo", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // Server API for KeyTransparencyService service type KeyTransparencyServiceServer interface { @@ -133,12 +118,6 @@ type KeyTransparencyServiceServer interface { // Returns the current user profile. // Clients must retry until this function returns a proof containing the desired value. UpdateEntry(context.Context, *keytransparency_v1_types.UpdateEntryRequest) (*keytransparency_v1_types.UpdateEntryResponse, error) - // GetDomainInfo returns all info tied to the specified domain. - // - // This API to get all necessary data needed to verify a particular - // key-server. Data contains for instance the tree-info, like for instance the - // log-/map-id and the corresponding public-keys. - GetDomainInfo(context.Context, *keytransparency_v1_types.GetDomainInfoRequest) (*keytransparency_v1_types.GetDomainInfoResponse, error) } func RegisterKeyTransparencyServiceServer(s *grpc.Server, srv KeyTransparencyServiceServer) { @@ -199,24 +178,6 @@ func _KeyTransparencyService_UpdateEntry_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } -func _KeyTransparencyService_GetDomainInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(keytransparency_v1_types.GetDomainInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(KeyTransparencyServiceServer).GetDomainInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/keytransparency.v1.service.KeyTransparencyService/GetDomainInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(KeyTransparencyServiceServer).GetDomainInfo(ctx, req.(*keytransparency_v1_types.GetDomainInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ ServiceName: "keytransparency.v1.service.KeyTransparencyService", HandlerType: (*KeyTransparencyServiceServer)(nil), @@ -233,10 +194,6 @@ var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ MethodName: "UpdateEntry", Handler: _KeyTransparencyService_UpdateEntry_Handler, }, - { - MethodName: "GetDomainInfo", - Handler: _KeyTransparencyService_GetDomainInfo_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "keytransparency_v1_service.proto", @@ -245,27 +202,24 @@ var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("keytransparency_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 343 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x4f, 0x4b, 0x33, 0x31, - 0x10, 0x87, 0xe9, 0xcb, 0x8b, 0xc8, 0xaa, 0xa8, 0x11, 0x15, 0xb6, 0x0a, 0x62, 0x4f, 0x15, 0xdd, - 0xb0, 0xf5, 0xe6, 0x59, 0xa9, 0xa2, 0x27, 0xff, 0x9c, 0x97, 0x74, 0x77, 0xda, 0x06, 0x6d, 0x66, - 0x4d, 0xb2, 0x0b, 0x41, 0xf4, 0xe0, 0xcd, 0xb3, 0x78, 0xf5, 0x4b, 0x79, 0xf6, 0xe6, 0x07, 0x91, - 0x66, 0xb3, 0x58, 0xca, 0x56, 0xd6, 0x53, 0x0e, 0xf3, 0xcc, 0x6f, 0x9e, 0x4c, 0xe2, 0xed, 0xdc, - 0x82, 0xd1, 0x92, 0x09, 0x95, 0x32, 0x09, 0x22, 0x36, 0x51, 0x1e, 0x46, 0x0a, 0x64, 0xce, 0x63, - 0x08, 0x52, 0x89, 0x1a, 0x89, 0x3f, 0x45, 0x04, 0x79, 0x18, 0x38, 0xc2, 0x4f, 0x06, 0x5c, 0x0f, - 0xb3, 0x5e, 0x10, 0xe3, 0x88, 0x0e, 0x10, 0x07, 0x77, 0x40, 0xa7, 0x68, 0x1a, 0xa3, 0x04, 0x6a, - 0x93, 0x68, 0xc5, 0x28, 0x6d, 0x52, 0x50, 0x33, 0x0b, 0x85, 0x81, 0xbf, 0xe5, 0xa2, 0x59, 0xca, - 0x29, 0x13, 0x02, 0x35, 0xd3, 0x1c, 0x85, 0xab, 0x76, 0x3e, 0xff, 0x7b, 0x1b, 0xe7, 0x60, 0xae, - 0x27, 0x02, 0xae, 0x0a, 0x3d, 0xf2, 0xe4, 0xcd, 0x77, 0x41, 0x9f, 0x08, 0x2d, 0x0d, 0x69, 0x07, - 0x15, 0xf7, 0x28, 0xa6, 0x94, 0xcc, 0x25, 0xdc, 0x67, 0xa0, 0xb4, 0xbf, 0x57, 0x07, 0x55, 0x29, - 0x0a, 0x05, 0xbb, 0xcd, 0xe7, 0x8f, 0xaf, 0xd7, 0x7f, 0xeb, 0x64, 0x8d, 0xe6, 0x21, 0xcd, 0x14, - 0x48, 0x45, 0x1f, 0xc6, 0x47, 0xc4, 0x93, 0x47, 0xf2, 0xde, 0xf0, 0x56, 0x2e, 0xb8, 0x2a, 0x5a, - 0x4e, 0xb9, 0xd2, 0x28, 0x0d, 0x09, 0x67, 0xa7, 0x4f, 0xb3, 0xa5, 0x50, 0xe7, 0x2f, 0x2d, 0x4e, - 0xac, 0x65, 0xc5, 0xb6, 0x49, 0xb3, 0x42, 0x8c, 0x0e, 0x9d, 0xcb, 0x5b, 0xc3, 0x5b, 0xb8, 0x49, - 0x13, 0xa6, 0xa1, 0x58, 0xd2, 0xfe, 0xec, 0x41, 0x13, 0x58, 0xa9, 0x75, 0x50, 0x93, 0x76, 0x46, - 0x6d, 0x6b, 0xd4, 0xf2, 0xab, 0x56, 0x75, 0xb4, 0x08, 0x63, 0x36, 0xca, 0x6c, 0x1f, 0x79, 0x69, - 0x78, 0x4b, 0x5d, 0xd0, 0xc7, 0x38, 0x62, 0x5c, 0x9c, 0x89, 0x3e, 0x92, 0xe0, 0xd7, 0x37, 0xf9, - 0x01, 0x4b, 0x37, 0x5a, 0x9b, 0x77, 0x76, 0x9b, 0xd6, 0x6e, 0x95, 0x2c, 0x8f, 0xed, 0x12, 0x5b, - 0xa7, 0x5c, 0xf4, 0xb1, 0x37, 0x67, 0xbf, 0xd9, 0xe1, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa0, - 0xc2, 0x1d, 0xdb, 0x2a, 0x03, 0x00, 0x00, + // 300 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xbf, 0x4a, 0xc4, 0x40, + 0x10, 0xc6, 0x39, 0x05, 0x91, 0x68, 0x21, 0x2b, 0x5a, 0xe4, 0x14, 0xc4, 0xab, 0x4e, 0x34, 0x4b, + 0xce, 0xce, 0x5e, 0x14, 0xb4, 0xf2, 0x4f, 0x1d, 0xf6, 0x92, 0x21, 0xb7, 0xa8, 0xbb, 0xeb, 0xce, + 0x24, 0xb0, 0x88, 0x16, 0xbe, 0x82, 0xd8, 0xfa, 0x4e, 0xe2, 0x2b, 0xf8, 0x20, 0x72, 0xc9, 0x06, + 0x8e, 0x90, 0xc0, 0x59, 0xa5, 0x98, 0xdf, 0x7c, 0xdf, 0x2f, 0xb3, 0xc1, 0xc1, 0x03, 0x38, 0xb2, + 0x42, 0xa1, 0x11, 0x16, 0x54, 0xea, 0x92, 0x32, 0x4e, 0x10, 0x6c, 0x29, 0x53, 0x88, 0x8c, 0xd5, + 0xa4, 0x59, 0xd8, 0x22, 0xa2, 0x32, 0x8e, 0x3c, 0x11, 0x66, 0xb9, 0xa4, 0x59, 0x31, 0x8d, 0x52, + 0xfd, 0xc4, 0x73, 0xad, 0xf3, 0x47, 0xe0, 0x2d, 0x9a, 0xa7, 0xda, 0x02, 0xaf, 0x92, 0x78, 0x47, + 0x15, 0x39, 0x03, 0xd8, 0x3b, 0xa8, 0x0d, 0xc2, 0x3d, 0x1f, 0x2d, 0x8c, 0xe4, 0x42, 0x29, 0x4d, + 0x82, 0xa4, 0x56, 0x7e, 0x3a, 0xf9, 0x5e, 0x0d, 0x76, 0xaf, 0xc0, 0xdd, 0x2d, 0x04, 0xdc, 0xd6, + 0x7a, 0xec, 0x2d, 0x58, 0xbf, 0x00, 0x3a, 0x57, 0x64, 0x1d, 0x1b, 0x47, 0x1d, 0xff, 0x51, 0xb7, + 0x34, 0xcc, 0x0d, 0x3c, 0x17, 0x80, 0x14, 0x1e, 0x2d, 0x83, 0xa2, 0xd1, 0x0a, 0xe1, 0x70, 0xf8, + 0xfe, 0xf3, 0xfb, 0xb1, 0xb2, 0xc3, 0xb6, 0x79, 0x19, 0xf3, 0x02, 0xc1, 0x22, 0x7f, 0x99, 0x7f, + 0x12, 0x99, 0xbd, 0xb2, 0xaf, 0x41, 0xb0, 0x75, 0x2d, 0xb1, 0x5e, 0xb9, 0x94, 0x48, 0xda, 0x3a, + 0x16, 0xf7, 0xa7, 0xb7, 0xd9, 0x46, 0x68, 0xf2, 0x9f, 0x15, 0x2f, 0x36, 0xaa, 0xc4, 0xf6, 0xd9, + 0xb0, 0x43, 0x8c, 0xcf, 0xbc, 0xcb, 0xe7, 0x20, 0xd8, 0xb8, 0x37, 0x99, 0x20, 0xa8, 0x8f, 0x74, + 0xdc, 0x5f, 0xb4, 0x80, 0x35, 0x5a, 0x27, 0x4b, 0xd2, 0xde, 0x68, 0x5c, 0x19, 0x8d, 0xc2, 0xae, + 0x53, 0x9d, 0x6d, 0xc2, 0x9c, 0x4d, 0x8a, 0x6a, 0x6f, 0xba, 0x56, 0x3d, 0xed, 0xe9, 0x5f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x47, 0xf4, 0xa4, 0xe3, 0x9e, 0x02, 0x00, 0x00, } diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go index 5550c914a..86455b453 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go @@ -66,10 +66,6 @@ type MonitorServiceClient interface { // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) - // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. - // - // Returns a list of SMRs along with data to reproduce any errors. - GetSignedMapRootStream(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (MonitorService_GetSignedMapRootStreamClient, error) } type monitorServiceClient struct { @@ -98,38 +94,6 @@ func (c *monitorServiceClient) GetSignedMapRootByRevision(ctx context.Context, i return out, nil } -func (c *monitorServiceClient) GetSignedMapRootStream(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (MonitorService_GetSignedMapRootStreamClient, error) { - stream, err := grpc.NewClientStream(ctx, &_MonitorService_serviceDesc.Streams[0], c.cc, "/monitor.v1.service.MonitorService/GetSignedMapRootStream", opts...) - if err != nil { - return nil, err - } - x := &monitorServiceGetSignedMapRootStreamClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type MonitorService_GetSignedMapRootStreamClient interface { - Recv() (*keytransparency_v1_types.GetMonitoringResponse, error) - grpc.ClientStream -} - -type monitorServiceGetSignedMapRootStreamClient struct { - grpc.ClientStream -} - -func (x *monitorServiceGetSignedMapRootStreamClient) Recv() (*keytransparency_v1_types.GetMonitoringResponse, error) { - m := new(keytransparency_v1_types.GetMonitoringResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - // Server API for MonitorService service type MonitorServiceServer interface { @@ -150,10 +114,6 @@ type MonitorServiceServer interface { // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. GetSignedMapRootByRevision(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) - // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. - // - // Returns a list of SMRs along with data to reproduce any errors. - GetSignedMapRootStream(*keytransparency_v1_types.GetMonitoringRequest, MonitorService_GetSignedMapRootStreamServer) error } func RegisterMonitorServiceServer(s *grpc.Server, srv MonitorServiceServer) { @@ -196,27 +156,6 @@ func _MonitorService_GetSignedMapRootByRevision_Handler(srv interface{}, ctx con return interceptor(ctx, in, info, handler) } -func _MonitorService_GetSignedMapRootStream_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(keytransparency_v1_types.GetMonitoringRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(MonitorServiceServer).GetSignedMapRootStream(m, &monitorServiceGetSignedMapRootStreamServer{stream}) -} - -type MonitorService_GetSignedMapRootStreamServer interface { - Send(*keytransparency_v1_types.GetMonitoringResponse) error - grpc.ServerStream -} - -type monitorServiceGetSignedMapRootStreamServer struct { - grpc.ServerStream -} - -func (x *monitorServiceGetSignedMapRootStreamServer) Send(m *keytransparency_v1_types.GetMonitoringResponse) error { - return x.ServerStream.SendMsg(m) -} - var _MonitorService_serviceDesc = grpc.ServiceDesc{ ServiceName: "monitor.v1.service.MonitorService", HandlerType: (*MonitorServiceServer)(nil), @@ -230,36 +169,29 @@ var _MonitorService_serviceDesc = grpc.ServiceDesc{ Handler: _MonitorService_GetSignedMapRootByRevision_Handler, }, }, - Streams: []grpc.StreamDesc{ - { - StreamName: "GetSignedMapRootStream", - Handler: _MonitorService_GetSignedMapRootStream_Handler, - ServerStreams: true, - }, - }, + Streams: []grpc.StreamDesc{}, Metadata: "monitor_v1_service.proto", } func init() { proto.RegisterFile("monitor_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 282 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x91, 0x31, 0x4a, 0xc4, 0x40, - 0x14, 0x86, 0x89, 0x82, 0x45, 0x0a, 0x91, 0x41, 0x57, 0x09, 0x6b, 0xe3, 0x01, 0x66, 0x8c, 0x76, - 0x96, 0x36, 0x5b, 0x6d, 0x93, 0x1c, 0x60, 0x99, 0xcd, 0x3e, 0xe2, 0xe0, 0xe6, 0xbd, 0x71, 0xde, - 0xdb, 0x40, 0x10, 0x1b, 0x6f, 0x20, 0x56, 0x82, 0xb7, 0xf2, 0x00, 0x36, 0x1e, 0x44, 0x36, 0x99, - 0xc6, 0x80, 0x60, 0x23, 0x5b, 0x7f, 0xc3, 0xff, 0x7d, 0x33, 0x93, 0x9e, 0x35, 0x84, 0x4e, 0x28, - 0x2c, 0xda, 0x7c, 0xc1, 0x10, 0x5a, 0x57, 0x81, 0xf6, 0x81, 0x84, 0x94, 0x8a, 0x44, 0xb7, 0xb9, - 0x8e, 0x24, 0x5b, 0xd5, 0x4e, 0xee, 0x36, 0x4b, 0x5d, 0x51, 0x63, 0x6a, 0xa2, 0x7a, 0x0d, 0xe6, - 0x1e, 0x3a, 0x09, 0x16, 0xd9, 0xdb, 0x00, 0x58, 0x75, 0xa6, 0xa2, 0x00, 0xa6, 0x5f, 0x18, 0xa3, - 0xad, 0x42, 0x3a, 0x0f, 0xfc, 0x2b, 0x18, 0xcc, 0xd9, 0x34, 0x4e, 0x5b, 0xef, 0x8c, 0x45, 0x24, - 0xb1, 0xe2, 0x08, 0x23, 0xbd, 0xfa, 0xdc, 0x4f, 0x0f, 0xe7, 0x43, 0x5a, 0x39, 0x64, 0xa9, 0x97, - 0x24, 0x3d, 0x9a, 0x81, 0x94, 0xae, 0x46, 0x58, 0xcd, 0xad, 0x2f, 0x88, 0x44, 0x69, 0x3d, 0xd2, - 0x6c, 0x2f, 0x32, 0x68, 0x66, 0x20, 0x71, 0xc1, 0x61, 0x5d, 0xc0, 0xc3, 0x06, 0x58, 0x32, 0xf3, - 0xe7, 0xf3, 0xec, 0x09, 0x19, 0x2e, 0xa6, 0xcf, 0x1f, 0x5f, 0xaf, 0x7b, 0x13, 0x75, 0x6c, 0xda, - 0xdc, 0x34, 0xd6, 0x9b, 0x40, 0x24, 0x7c, 0xb3, 0xb6, 0x02, 0x2c, 0xea, 0x3d, 0x49, 0xb3, 0x71, - 0xd3, 0x6d, 0x57, 0x40, 0xeb, 0xd8, 0x11, 0xfe, 0x7f, 0xdd, 0x79, 0x5f, 0x77, 0xaa, 0x4e, 0x7e, - 0xd4, 0x99, 0x47, 0x16, 0x1b, 0xe4, 0x49, 0xbd, 0x25, 0xe9, 0x64, 0x9c, 0x57, 0x4a, 0x00, 0xdb, - 0xec, 0xec, 0xe1, 0xb8, 0xd7, 0x5f, 0x26, 0xcb, 0x83, 0xfe, 0xa3, 0xaf, 0xbf, 0x03, 0x00, 0x00, - 0xff, 0xff, 0x0f, 0x72, 0x10, 0xb7, 0x9c, 0x02, 0x00, 0x00, + // 264 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x90, 0x3d, 0x4e, 0xc3, 0x40, + 0x10, 0x46, 0x95, 0x14, 0x14, 0x2e, 0x10, 0x5a, 0xf1, 0x27, 0x2b, 0x34, 0x1c, 0x60, 0x47, 0x86, + 0x8e, 0x92, 0x26, 0x55, 0x1a, 0xe7, 0x00, 0xd1, 0xc6, 0x19, 0x99, 0x15, 0xf1, 0xcc, 0xb2, 0x33, + 0xb1, 0x64, 0x21, 0x1a, 0x6e, 0x80, 0x68, 0xb9, 0x0d, 0x47, 0xe0, 0x0a, 0x1c, 0x04, 0xc5, 0xde, + 0x06, 0x4b, 0x48, 0x34, 0xa9, 0xdf, 0xea, 0x7b, 0x6f, 0x27, 0xbb, 0x6c, 0x98, 0xbc, 0x72, 0x5c, + 0xb5, 0xc5, 0x4a, 0x30, 0xb6, 0xbe, 0x42, 0x1b, 0x22, 0x2b, 0x1b, 0x93, 0x88, 0x6d, 0x0b, 0x9b, + 0x48, 0xbe, 0xa9, 0xbd, 0x3e, 0xec, 0xd6, 0xb6, 0xe2, 0x06, 0x6a, 0xe6, 0x7a, 0x8b, 0xf0, 0x88, + 0x9d, 0x46, 0x47, 0x12, 0x5c, 0x44, 0xaa, 0x3a, 0xa8, 0x38, 0x22, 0xf4, 0x0b, 0x63, 0xb4, 0x57, + 0x68, 0x17, 0x50, 0xfe, 0x04, 0x83, 0x39, 0x9f, 0xa5, 0x69, 0x17, 0x3c, 0x38, 0x22, 0x56, 0xa7, + 0x9e, 0x29, 0xd1, 0x9b, 0xcf, 0x69, 0x76, 0xbc, 0x18, 0xd2, 0x96, 0x43, 0x96, 0x79, 0x9b, 0x64, + 0x27, 0x73, 0xd4, 0xa5, 0xaf, 0x09, 0x37, 0x0b, 0x17, 0x4a, 0x66, 0x35, 0xd6, 0x8e, 0x34, 0xfb, + 0x8f, 0x0c, 0x9a, 0x39, 0x6a, 0x5a, 0xf0, 0x54, 0x97, 0xf8, 0xb4, 0x43, 0xd1, 0x1c, 0xfe, 0xfd, + 0x5e, 0x02, 0x93, 0xe0, 0xf5, 0xec, 0xf5, 0xeb, 0xfb, 0x7d, 0x7a, 0x6e, 0x4e, 0xa1, 0x2d, 0xa0, + 0x71, 0x01, 0x22, 0xb3, 0xca, 0xdd, 0xd6, 0x29, 0x8a, 0x9a, 0x8f, 0x49, 0x96, 0x8f, 0x9b, 0xee, + 0xbb, 0x12, 0x5b, 0x2f, 0x9e, 0xe9, 0xf0, 0x75, 0x57, 0x7d, 0xdd, 0x85, 0x39, 0xfb, 0x55, 0x07, + 0xcf, 0xa2, 0x2e, 0xea, 0xcb, 0xfa, 0xa8, 0x3f, 0xe6, 0xed, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xf1, 0x14, 0x6f, 0x52, 0x00, 0x02, 0x00, 0x00, } diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go index 3278543ef..050d81507 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go @@ -72,31 +72,6 @@ func request_MonitorService_GetSignedMapRootByRevision_0(ctx context.Context, ma } -var ( - filter_MonitorService_GetSignedMapRootStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_MonitorService_GetSignedMapRootStream_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (MonitorService_GetSignedMapRootStreamClient, runtime.ServerMetadata, error) { - var protoReq keytransparency_v1_types.GetMonitoringRequest - var metadata runtime.ServerMetadata - - if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_MonitorService_GetSignedMapRootStream_0); err != nil { - return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err) - } - - stream, err := client.GetSignedMapRootStream(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - // RegisterMonitorServiceHandlerFromEndpoint is same as RegisterMonitorServiceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterMonitorServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { @@ -183,34 +158,6 @@ func RegisterMonitorServiceHandler(ctx context.Context, mux *runtime.ServeMux, c }) - mux.Handle("GET", pattern_MonitorService_GetSignedMapRootStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(ctx) - defer cancel() - if cn, ok := w.(http.CloseNotifier); ok { - go func(done <-chan struct{}, closed <-chan bool) { - select { - case <-done: - case <-closed: - cancel() - } - }(ctx.Done(), cn.CloseNotify()) - } - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, req) - if err != nil { - runtime.HTTPError(ctx, outboundMarshaler, w, req, err) - } - resp, md, err := request_MonitorService_GetSignedMapRootStream_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, outboundMarshaler, w, req, err) - return - } - - forward_MonitorService_GetSignedMapRootStream_0(ctx, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - return nil } @@ -218,14 +165,10 @@ var ( pattern_MonitorService_GetSignedMapRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "latest")) pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "map", "roots", "start"}, "")) - - pattern_MonitorService_GetSignedMapRootStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "stream")) ) var ( forward_MonitorService_GetSignedMapRoot_0 = runtime.ForwardResponseMessage forward_MonitorService_GetSignedMapRootByRevision_0 = runtime.ForwardResponseMessage - - forward_MonitorService_GetSignedMapRootStream_0 = runtime.ForwardResponseStream ) diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.proto b/impl/proto/monitor_v1_service/monitor_v1_service.proto index 9723cfed4..741faefed 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.proto +++ b/impl/proto/monitor_v1_service/monitor_v1_service.proto @@ -55,14 +55,6 @@ service MonitorService { returns(keytransparency.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots/{start}" }; } - - // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. - // - // Returns a list of SMRs along with data to reproduce any errors. - rpc GetSignedMapRootStream(keytransparency.v1.types.GetMonitoringRequest) - returns (stream keytransparency.v1.types.GetMonitoringResponse) { - option (google.api.http) = { get: "/v1/map/roots:stream" }; - } } diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 60cf378a3..e63ef6bc9 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -72,7 +72,7 @@ function pushTrillianImgs() function pushKTImgs() { - images=("keytransparency-server" "prometheus") + images=("keytransparency-server" "keytransparency-monitor" "prometheus") for DOCKER_IMAGE_NAME in "${images[@]}" do # Push the images as we refer to them in the kubernetes config files: From bb41010e656d24f0cbb0d4b53efbb506bf4df92d Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 31 Jul 2017 15:56:48 +0100 Subject: [PATCH 04/46] Add to kubernetes config and deploy script Minor changes verify signature on response resolves #672 Add log sig verification rebase wip WIP add TODO remove streaming API (simplifies moving to core) Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's Monitor service and types: regenerate protos and downgrade grpc-gateway to match trillian's work in progress revert local changes, add TODOs simplify monitor Dockerfile (non-opinionated) regenerate proto with correct dependency versions Add to kubernetes config and deploy script resolves #672 rebase rebase =gofmt WIP --- .../grpcc/grpc_client.go | 8 +- core/keyserver/keyserver.go | 9 +- core/mutator/entry/entry.go | 7 +- core/mutator/mutator.go | 2 +- core/signer/signer.go | 8 +- impl/monitor/monitor.go | 10 +- impl/monitor/monitor_test.go | 2 +- impl/monitor/verify.go | 96 +++++++++++++++---- impl/monitor/verify_test.go | 19 ++++ impl/proto/keytransparency_v1_service/gen.go | 4 +- .../keytransparency_v1_service.pb.go | 86 +++++++++++++---- 11 files changed, 178 insertions(+), 73 deletions(-) diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 129c5dc2d..2eb3f26af 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -32,7 +32,6 @@ import ( "github.com/google/keytransparency/core/mutator" "github.com/google/keytransparency/core/mutator/entry" - "github.com/golang/protobuf/proto" "github.com/google/trillian/client" "github.com/google/trillian/merkle/hashers" "golang.org/x/net/context" @@ -202,12 +201,7 @@ func (c *Client) Update(ctx context.Context, userID, appID string, profileData [ return nil, fmt.Errorf("CreateUpdateEntryRequest: %v", err) } - // Check the mutation before submitting it. - m, err := proto.Marshal(req.GetEntryUpdate().GetUpdate()) - if err != nil { - return nil, fmt.Errorf("proto.Marshal(): %v", err) - } - if _, err := c.mutator.Mutate(getResp.GetLeafProof().GetLeaf().GetLeafValue(), m); err != nil { + if _, err := c.mutator.Mutate(getResp.GetLeafProof().GetLeaf().GetLeafValue(), req.GetEntryUpdate().GetUpdate()); err != nil { return nil, fmt.Errorf("Mutate: %v", err) } diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index 4945d733c..a5ec233c4 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -290,14 +290,9 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* // - Correct signatures internal to the update. // - Hash of current data matches the expectation in the mutation. - m, err := proto.Marshal(in.GetEntryUpdate().GetUpdate()) - if err != nil { - glog.Warningf("Marshal error of Update: %v", err) - return nil, grpc.Errorf(codes.InvalidArgument, "Marshaling error") - } - // The very first mutation will have resp.LeafProof.LeafData=nil. - if _, err := s.mutator.Mutate(resp.LeafProof.Leaf.LeafValue, m); err == mutator.ErrReplay { + if _, err := s.mutator.Mutate(resp.LeafProof.Leaf.LeafValue, + in.GetEntryUpdate().GetUpdate()); err == mutator.ErrReplay { glog.Warningf("Discarding request due to replay") // Return the response. The client should handle the replay case // by comparing the returned response with the request. Check diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index 241bfeb40..613d56da6 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -41,12 +41,7 @@ func New() *Entry { // Mutate verifies that this is a valid mutation for this item and applies // mutation to value. -func (*Entry) Mutate(oldValue, mutation []byte) ([]byte, error) { - update := new(tpb.SignedKV) - if err := proto.Unmarshal(mutation, update); err != nil { - return nil, err - } - +func (*Entry) Mutate(oldValue []byte, update *tpb.SignedKV) ([]byte, error) { // Ensure that the mutation size is within bounds. if proto.Size(update) > mutator.MaxMutationSize { glog.Warningf("mutation (%v bytes) is larger than the maximum accepted size (%v bytes).", proto.Size(update), mutator.MaxMutationSize) diff --git a/core/mutator/mutator.go b/core/mutator/mutator.go index 8d648f74d..4bfbb9896 100644 --- a/core/mutator/mutator.go +++ b/core/mutator/mutator.go @@ -49,7 +49,7 @@ var ( type Mutator interface { // Mutate verifies that this is a valid mutation for this item and // applies mutation to value. - Mutate(value, mutation []byte) ([]byte, error) + Mutate(value []byte, mutation *tpb.SignedKV) ([]byte, error) } // Mutation reads and writes mutations to the database. diff --git a/core/signer/signer.go b/core/signer/signer.go index e59fc2140..20575a051 100644 --- a/core/signer/signer.go +++ b/core/signer/signer.go @@ -19,7 +19,6 @@ import ( "math" "time" - "github.com/gogo/protobuf/proto" "github.com/google/keytransparency/core/appender" "github.com/google/keytransparency/core/mutator" "github.com/google/keytransparency/core/transaction" @@ -207,12 +206,7 @@ func (s *Signer) applyMutations(mutations []*tpb.SignedKV, leaves []*trillian.Ma oldValue = leaf.LeafValue } - // TODO: change mutator interface to accept objects directly. - mData, err := proto.Marshal(m) - if err != nil { - return nil, err - } - newValue, err := s.mutator.Mutate(oldValue, mData) + newValue, err := s.mutator.Mutate(oldValue, m) if err != nil { glog.Warningf("Mutate(): %v", err) continue // A bad mutation should not make the whole batch fail. diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index cb8f079aa..6f9ab4f46 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -68,10 +68,10 @@ func New(cli mupb.MutationServiceClient, logPubKey, mapPubKey crypto.PublicKey, poll time.Duration) *Server { return &Server{ - client: cli, - pollPeriod: poll, - logPubKey: logPubKey, - mapPubKey: mapPubKey, + client: cli, + pollPeriod: poll, + logPubKey: logPubKey, + mapPubKey: mapPubKey, signer: signer, proccessedSMRs: make([]*ktpb.GetMonitoringResponse, 256), } @@ -144,7 +144,7 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] } respSmr := resp.GetSmr() var monitorResp *ktpb.GetMonitoringResponse - switch err := s.verifyResponse(resp, mutations); err { + switch err := verifyResponse(s.logPubKey, s.mapPubKey, resp, mutations); err { // TODO(ismail): return proper data for failure cases: case ErrInvalidMutation: glog.Errorf("TODO: handle this ErrInvalidMutation properly") diff --git a/impl/monitor/monitor_test.go b/impl/monitor/monitor_test.go index b3ea4ced4..6464d5386 100644 --- a/impl/monitor/monitor_test.go +++ b/impl/monitor/monitor_test.go @@ -29,4 +29,4 @@ func TestGetSignedMapRoot(t *testing.T) { if got, want := err, ErrNothingProcessed; got != want { t.Errorf("GetSignedMapRoot(_, _): %v, want %v", got, want) } -} \ No newline at end of file +} diff --git a/impl/monitor/verify.go b/impl/monitor/verify.go index 23f12541f..ff8a97cdf 100644 --- a/impl/monitor/verify.go +++ b/impl/monitor/verify.go @@ -19,16 +19,20 @@ package monitor import ( + "fmt" + "crypto" "errors" "github.com/golang/glog" // "github.com/google/trillian" // "github.com/google/trillian/merkle" + "github.com/google/keytransparency/core/mutator/entry" tcrypto "github.com/google/trillian/crypto" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/google/trillian" ) var ( @@ -41,7 +45,7 @@ var ( // ErrInvalidMapSignature occurs when the signature on the observed map root // is invalid. ErrInvalidMapSignature = errors.New("invalid signature on map in GetMutationsResponse") - // ErrInvalidMapSignature occurs when the signature on the observed map root + // ErrInvalidLogSignature occurs when the signature on the observed map root // is invalid. ErrInvalidLogSignature = errors.New("invalid signature on log in GetMutationsResponse") ) @@ -50,37 +54,95 @@ var ( // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. -func (s *Server) verifyResponse(resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { +func verifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { // verify signature on map root: - if err := tcrypto.VerifyObject(s.mapPubKey, resp.GetSmr(), resp.GetSmr().GetSignature()); err != nil { + if err := tcrypto.VerifyObject(mapPubKey, resp.GetSmr(), resp.GetSmr().GetSignature()); err != nil { glog.Errorf("couldn't verify signature on map root: %v", err) return ErrInvalidMapSignature } - // verify signature on log root: - if err := tcrypto.VerifyObject(s.logPubKey, resp.GetSmr(), resp.GetLogRoot().GetSignature()); err != nil { - glog.Errorf("couldn't verify signature on log root: %v", err) + + // verify signature on log-root: + hash := tcrypto.HashLogRoot(*resp.GetLogRoot()) + if err := tcrypto.Verify(logPubKey, hash, resp.GetLogRoot().GetSignature()); err != nil { return ErrInvalidLogSignature } - // TODO verify log-root: - // VerifyRoot(trusted, newRoot *trillian.SignedLogRoot, consistency [][]byte) error + //hasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) + //if err != nil { + // return nil, fmt.Errorf("Failed retrieving LogHasher from registry: %v", err) + //} + // logVerifier := merkle.NewLogVerifier(hasher) + // logVerifier.VerifyConsistencyProof() + // logVerifier.VerifyInclusionProof() + // mapID := resp.GetSmr().GetMapId() + if err := verifyMutations(allMuts, resp.GetSmr().GetRootHash()); err != nil { + return err + } + return errors.New("TODO: implement verification logic") +} + + +func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { // TODO: export applyMutations in CreateEpoch / signer.go? // - // verify that the provided leaf’s inclusion proof goes to epoch e-1. - // - // for each mutation: - //if err := merkle.VerifyMapInclusionProof(mapID, index, - // leafHash, rootHash, proof, hasher); err != nil { - // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) - // return ErrInvalidMutation - //} // verify the mutation’s validity against the previous leaf. + // + // entry.VerifyKeys() + // or + // entry.Mutate() // does all checks and returns the new leaf as well + inclusionMap := make(map[[32]byte]*trillian.MapLeafInclusion) + updatedLeafMap := make(map[[32]byte]*trillian.MapLeaf) + mutator := entry.New() + for _, m := range muts { + // verify that the provided leaf’s inclusion proof goes to epoch e-1: + // + //if err := merkle.VerifyMapInclusionProof(mapID, index, + // leafHash, rootHash, proof, hasher); err != nil { + // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) + // return ErrInvalidMutation + //} + + newLeaf, err := mutator.Mutate(m.GetProof().GetLeaf().GetLeafValue(), m.GetUpdate()) + if err != nil { + // TODO(ismail): do not return; collect other errors if any + return ErrInvalidMutation + } + // update and store intermediate hashes for this new leaf + // (using old inclusion proof and already updated intermediate leafs) + fmt.Println(newLeaf) + // the index shouldn't change: + var index [32]byte + copy(index[:], m.GetProof().GetLeaf().GetIndex()[:32]) + // TODO(ismail): do we actually need these copies? + inclusionMap[index] = m.GetProof() + + updatedLeafMap[index] = &trillian.MapLeaf{ + Index: index[:], + // LeafHash: hasher.HashLeaf(mapID, l.Index, l.LeafValue), + LeafValue: newLeaf, + } + + //for level, proof := range m.GetProof().GetInclusion() { + // pElement := proof + // if len(pElement) == 0 { + // pElement = hasher.HashEmpty(treeID, sib.Path, level) + // } + // if proofIsRightHandElement { + // runningHash = hasher.HashChildren(runningHash, pElement) + // } else { + // runningHash = hasher.HashChildren(pElement, runningHash) + // } + //} + // + + } + + // compute the new leaf and store the intermediate hashes locally. // compute the new root using local intermediate hashes from epoch e. // verify rootHash - return errors.New("TODO: implement verification logic") } diff --git a/impl/monitor/verify_test.go b/impl/monitor/verify_test.go index c1d88be8d..11fe19a64 100644 --- a/impl/monitor/verify_test.go +++ b/impl/monitor/verify_test.go @@ -14,5 +14,24 @@ package monitor +import ( + "testing" + "github.com/google/trillian/merkle" + "fmt" +) + + // TODO(ismail): write extensive tests for verification steps (if not existing // in trillian) +const ( + emptyMapRootB64 = "xmifEIEqCYCXbZUz2Dh1KCFmFZVn7DUVVxbBQTr1PWo=" + mapID = int64(0) +) + +func TestServerVerifyMutations(t *testing.T) { + // verifyInclusionProof for empty leaf + if err := merkle.VerifyMapInclusionProof(mapID, index, + leafHash, rootHash, proof, hasher); err != nil { + return fmt.Errorf("VerifyMapInclusionProof(%x): %v", index, err) + } +} \ No newline at end of file diff --git a/impl/proto/keytransparency_v1_service/gen.go b/impl/proto/keytransparency_v1_service/gen.go index 3aa740059..e0bf325dd 100644 --- a/impl/proto/keytransparency_v1_service/gen.go +++ b/impl/proto/keytransparency_v1_service/gen.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --go_out=,plugins=grpc:. keytransparency_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --go_out=,plugins=grpc:. keytransparency_v1_service.proto -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --grpc-gateway_out=logtostderr=true:. keytransparency_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --grpc-gateway_out=logtostderr=true:. keytransparency_v1_service.proto package keytransparency_v1_service diff --git a/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go b/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go index 671988f09..8023aec19 100644 --- a/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go +++ b/impl/proto/keytransparency_v1_service/keytransparency_v1_service.pb.go @@ -64,6 +64,12 @@ type KeyTransparencyServiceClient interface { // Returns the current user profile. // Clients must retry until this function returns a proof containing the desired value. UpdateEntry(ctx context.Context, in *keytransparency_v1_types.UpdateEntryRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.UpdateEntryResponse, error) + // GetDomainInfo returns all info tied to the specified domain. + // + // This API to get all necessary data needed to verify a particular + // key-server. Data contains for instance the tree-info, like for instance the + // log-/map-id and the corresponding public-keys. + GetDomainInfo(ctx context.Context, in *keytransparency_v1_types.GetDomainInfoRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetDomainInfoResponse, error) } type keyTransparencyServiceClient struct { @@ -101,6 +107,15 @@ func (c *keyTransparencyServiceClient) UpdateEntry(ctx context.Context, in *keyt return out, nil } +func (c *keyTransparencyServiceClient) GetDomainInfo(ctx context.Context, in *keytransparency_v1_types.GetDomainInfoRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetDomainInfoResponse, error) { + out := new(keytransparency_v1_types.GetDomainInfoResponse) + err := grpc.Invoke(ctx, "/keytransparency.v1.service.KeyTransparencyService/GetDomainInfo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for KeyTransparencyService service type KeyTransparencyServiceServer interface { @@ -118,6 +133,12 @@ type KeyTransparencyServiceServer interface { // Returns the current user profile. // Clients must retry until this function returns a proof containing the desired value. UpdateEntry(context.Context, *keytransparency_v1_types.UpdateEntryRequest) (*keytransparency_v1_types.UpdateEntryResponse, error) + // GetDomainInfo returns all info tied to the specified domain. + // + // This API to get all necessary data needed to verify a particular + // key-server. Data contains for instance the tree-info, like for instance the + // log-/map-id and the corresponding public-keys. + GetDomainInfo(context.Context, *keytransparency_v1_types.GetDomainInfoRequest) (*keytransparency_v1_types.GetDomainInfoResponse, error) } func RegisterKeyTransparencyServiceServer(s *grpc.Server, srv KeyTransparencyServiceServer) { @@ -178,6 +199,24 @@ func _KeyTransparencyService_UpdateEntry_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _KeyTransparencyService_GetDomainInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(keytransparency_v1_types.GetDomainInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyTransparencyServiceServer).GetDomainInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/keytransparency.v1.service.KeyTransparencyService/GetDomainInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyTransparencyServiceServer).GetDomainInfo(ctx, req.(*keytransparency_v1_types.GetDomainInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ ServiceName: "keytransparency.v1.service.KeyTransparencyService", HandlerType: (*KeyTransparencyServiceServer)(nil), @@ -194,6 +233,10 @@ var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ MethodName: "UpdateEntry", Handler: _KeyTransparencyService_UpdateEntry_Handler, }, + { + MethodName: "GetDomainInfo", + Handler: _KeyTransparencyService_GetDomainInfo_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "keytransparency_v1_service.proto", @@ -202,24 +245,27 @@ var _KeyTransparencyService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("keytransparency_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 300 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xbf, 0x4a, 0xc4, 0x40, - 0x10, 0xc6, 0x39, 0x05, 0x91, 0x68, 0x21, 0x2b, 0x5a, 0xe4, 0x14, 0xc4, 0xab, 0x4e, 0x34, 0x4b, - 0xce, 0xce, 0x5e, 0x14, 0xb4, 0xf2, 0x4f, 0x1d, 0xf6, 0x92, 0x21, 0xb7, 0xa8, 0xbb, 0xeb, 0xce, - 0x24, 0xb0, 0x88, 0x16, 0xbe, 0x82, 0xd8, 0xfa, 0x4e, 0xe2, 0x2b, 0xf8, 0x20, 0x72, 0xc9, 0x06, - 0x8e, 0x90, 0xc0, 0x59, 0xa5, 0x98, 0xdf, 0x7c, 0xdf, 0x2f, 0xb3, 0xc1, 0xc1, 0x03, 0x38, 0xb2, - 0x42, 0xa1, 0x11, 0x16, 0x54, 0xea, 0x92, 0x32, 0x4e, 0x10, 0x6c, 0x29, 0x53, 0x88, 0x8c, 0xd5, - 0xa4, 0x59, 0xd8, 0x22, 0xa2, 0x32, 0x8e, 0x3c, 0x11, 0x66, 0xb9, 0xa4, 0x59, 0x31, 0x8d, 0x52, - 0xfd, 0xc4, 0x73, 0xad, 0xf3, 0x47, 0xe0, 0x2d, 0x9a, 0xa7, 0xda, 0x02, 0xaf, 0x92, 0x78, 0x47, - 0x15, 0x39, 0x03, 0xd8, 0x3b, 0xa8, 0x0d, 0xc2, 0x3d, 0x1f, 0x2d, 0x8c, 0xe4, 0x42, 0x29, 0x4d, - 0x82, 0xa4, 0x56, 0x7e, 0x3a, 0xf9, 0x5e, 0x0d, 0x76, 0xaf, 0xc0, 0xdd, 0x2d, 0x04, 0xdc, 0xd6, - 0x7a, 0xec, 0x2d, 0x58, 0xbf, 0x00, 0x3a, 0x57, 0x64, 0x1d, 0x1b, 0x47, 0x1d, 0xff, 0x51, 0xb7, - 0x34, 0xcc, 0x0d, 0x3c, 0x17, 0x80, 0x14, 0x1e, 0x2d, 0x83, 0xa2, 0xd1, 0x0a, 0xe1, 0x70, 0xf8, - 0xfe, 0xf3, 0xfb, 0xb1, 0xb2, 0xc3, 0xb6, 0x79, 0x19, 0xf3, 0x02, 0xc1, 0x22, 0x7f, 0x99, 0x7f, - 0x12, 0x99, 0xbd, 0xb2, 0xaf, 0x41, 0xb0, 0x75, 0x2d, 0xb1, 0x5e, 0xb9, 0x94, 0x48, 0xda, 0x3a, - 0x16, 0xf7, 0xa7, 0xb7, 0xd9, 0x46, 0x68, 0xf2, 0x9f, 0x15, 0x2f, 0x36, 0xaa, 0xc4, 0xf6, 0xd9, - 0xb0, 0x43, 0x8c, 0xcf, 0xbc, 0xcb, 0xe7, 0x20, 0xd8, 0xb8, 0x37, 0x99, 0x20, 0xa8, 0x8f, 0x74, - 0xdc, 0x5f, 0xb4, 0x80, 0x35, 0x5a, 0x27, 0x4b, 0xd2, 0xde, 0x68, 0x5c, 0x19, 0x8d, 0xc2, 0xae, - 0x53, 0x9d, 0x6d, 0xc2, 0x9c, 0x4d, 0x8a, 0x6a, 0x6f, 0xba, 0x56, 0x3d, 0xed, 0xe9, 0x5f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x47, 0xf4, 0xa4, 0xe3, 0x9e, 0x02, 0x00, 0x00, + // 343 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x4f, 0x4b, 0x33, 0x31, + 0x10, 0x87, 0xe9, 0xcb, 0x8b, 0xc8, 0xaa, 0xa8, 0x11, 0x15, 0xb6, 0x0a, 0x62, 0x4f, 0x15, 0xdd, + 0xb0, 0xf5, 0xe6, 0x59, 0xa9, 0xa2, 0x27, 0xff, 0x9c, 0x97, 0x74, 0x77, 0xda, 0x06, 0x6d, 0x66, + 0x4d, 0xb2, 0x0b, 0x41, 0xf4, 0xe0, 0xcd, 0xb3, 0x78, 0xf5, 0x4b, 0x79, 0xf6, 0xe6, 0x07, 0x91, + 0x66, 0xb3, 0x58, 0xca, 0x56, 0xd6, 0x53, 0x0e, 0xf3, 0xcc, 0x6f, 0x9e, 0x4c, 0xe2, 0xed, 0xdc, + 0x82, 0xd1, 0x92, 0x09, 0x95, 0x32, 0x09, 0x22, 0x36, 0x51, 0x1e, 0x46, 0x0a, 0x64, 0xce, 0x63, + 0x08, 0x52, 0x89, 0x1a, 0x89, 0x3f, 0x45, 0x04, 0x79, 0x18, 0x38, 0xc2, 0x4f, 0x06, 0x5c, 0x0f, + 0xb3, 0x5e, 0x10, 0xe3, 0x88, 0x0e, 0x10, 0x07, 0x77, 0x40, 0xa7, 0x68, 0x1a, 0xa3, 0x04, 0x6a, + 0x93, 0x68, 0xc5, 0x28, 0x6d, 0x52, 0x50, 0x33, 0x0b, 0x85, 0x81, 0xbf, 0xe5, 0xa2, 0x59, 0xca, + 0x29, 0x13, 0x02, 0x35, 0xd3, 0x1c, 0x85, 0xab, 0x76, 0x3e, 0xff, 0x7b, 0x1b, 0xe7, 0x60, 0xae, + 0x27, 0x02, 0xae, 0x0a, 0x3d, 0xf2, 0xe4, 0xcd, 0x77, 0x41, 0x9f, 0x08, 0x2d, 0x0d, 0x69, 0x07, + 0x15, 0xf7, 0x28, 0xa6, 0x94, 0xcc, 0x25, 0xdc, 0x67, 0xa0, 0xb4, 0xbf, 0x57, 0x07, 0x55, 0x29, + 0x0a, 0x05, 0xbb, 0xcd, 0xe7, 0x8f, 0xaf, 0xd7, 0x7f, 0xeb, 0x64, 0x8d, 0xe6, 0x21, 0xcd, 0x14, + 0x48, 0x45, 0x1f, 0xc6, 0x47, 0xc4, 0x93, 0x47, 0xf2, 0xde, 0xf0, 0x56, 0x2e, 0xb8, 0x2a, 0x5a, + 0x4e, 0xb9, 0xd2, 0x28, 0x0d, 0x09, 0x67, 0xa7, 0x4f, 0xb3, 0xa5, 0x50, 0xe7, 0x2f, 0x2d, 0x4e, + 0xac, 0x65, 0xc5, 0xb6, 0x49, 0xb3, 0x42, 0x8c, 0x0e, 0x9d, 0xcb, 0x5b, 0xc3, 0x5b, 0xb8, 0x49, + 0x13, 0xa6, 0xa1, 0x58, 0xd2, 0xfe, 0xec, 0x41, 0x13, 0x58, 0xa9, 0x75, 0x50, 0x93, 0x76, 0x46, + 0x6d, 0x6b, 0xd4, 0xf2, 0xab, 0x56, 0x75, 0xb4, 0x08, 0x63, 0x36, 0xca, 0x6c, 0x1f, 0x79, 0x69, + 0x78, 0x4b, 0x5d, 0xd0, 0xc7, 0x38, 0x62, 0x5c, 0x9c, 0x89, 0x3e, 0x92, 0xe0, 0xd7, 0x37, 0xf9, + 0x01, 0x4b, 0x37, 0x5a, 0x9b, 0x77, 0x76, 0x9b, 0xd6, 0x6e, 0x95, 0x2c, 0x8f, 0xed, 0x12, 0x5b, + 0xa7, 0x5c, 0xf4, 0xb1, 0x37, 0x67, 0xbf, 0xd9, 0xe1, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa0, + 0xc2, 0x1d, 0xdb, 0x2a, 0x03, 0x00, 0x00, } From ad4af544bc4dc88f9a28a555b4cc00e43ede5707 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Thu, 10 Aug 2017 15:03:35 +0100 Subject: [PATCH 05/46] Review comments: * move monitor service types into separate file * move verification (wip) into sperate file * generate and use separate priv. key for signing * pass pointer of priv key * unexport verifKeys --- cmd/keytransparency-monitor/main.go | 4 +- {impl => core}/monitor/verify.go | 2 +- {impl => core}/monitor/verify_test.go | 0 core/mutator/entry/entry.go | 6 +- .../keytransparency_v1_types.pb.go | 329 ++++-------------- .../keytransparency_v1_types.proto | 64 ---- core/proto/monitor_v1_types/gen.go | 17 + .../monitor_v1_types/monitor_v1_types.pb.go | 245 +++++++++++++ .../monitor_v1_types/monitor_v1_types.proto | 86 +++++ docker-compose.yml | 2 +- impl/monitor/monitor.go | 33 +- .../monitor_v1_service.pb.go | 62 ++-- .../monitor_v1_service.pb.gw.go | 6 +- .../monitor_v1_service.proto | 13 +- scripts/gen_monitor_keys.sh | 6 +- scripts/prepare_server.sh | 5 + 16 files changed, 491 insertions(+), 389 deletions(-) rename {impl => core}/monitor/verify.go (98%) rename {impl => core}/monitor/verify_test.go (100%) create mode 100644 core/proto/monitor_v1_types/gen.go create mode 100644 core/proto/monitor_v1_types/monitor_v1_types.pb.go create mode 100644 core/proto/monitor_v1_types/monitor_v1_types.proto diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index f91fd8497..7d74aa907 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -41,7 +41,7 @@ var ( keyFile = flag.String("tls-key", "genfiles/server.key", "TLS private key file") certFile = flag.String("tls-cert", "genfiles/server.pem", "TLS cert file") - signingKey = flag.String("sign-key", "genfiles/p256-key.pem", "Path to private key PEM for SMH signing") + signingKey = flag.String("sign-key", "genfiles/monitor_sign-key.pem", "Path to private key PEM for SMH signing") signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") @@ -112,7 +112,7 @@ func main() { glog.Fatalf("Could not create signer from %v: %v", *signingKey, err) } - srv := monitor.New(mcc, *crypto.NewSHA256Signer(key), *mapKey, *logKey, *pollPeriod) + srv := monitor.New(mcc, crypto.NewSHA256Signer(key), *mapKey, *logKey, *pollPeriod) mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) diff --git a/impl/monitor/verify.go b/core/monitor/verify.go similarity index 98% rename from impl/monitor/verify.go rename to core/monitor/verify.go index ff8a97cdf..ded5ec99f 100644 --- a/impl/monitor/verify.go +++ b/core/monitor/verify.go @@ -54,7 +54,7 @@ var ( // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. -func verifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { +func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { // verify signature on map root: if err := tcrypto.VerifyObject(mapPubKey, resp.GetSmr(), resp.GetSmr().GetSignature()); err != nil { glog.Errorf("couldn't verify signature on map root: %v", err) diff --git a/impl/monitor/verify_test.go b/core/monitor/verify_test.go similarity index 100% rename from impl/monitor/verify_test.go rename to core/monitor/verify_test.go diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index 613d56da6..6a1222f8d 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -76,20 +76,20 @@ func (*Entry) Mutate(oldValue []byte, update *tpb.SignedKV) ([]byte, error) { return nil, mutator.ErrMissingKey } - if err := VerifyKeys(oldValue, kv, update, entry); err != nil { + if err := verifyKeys(oldValue, kv, update, entry); err != nil { return nil, err } return update.GetKeyValue().GetValue(), nil } -// VerifyKeys verifies both old and new authorized keys based on the following +// verifyKeys verifies both old and new authorized keys based on the following // criteria: // 1. At least one signature with a key in the previous entry should exist. // 2. The first mutation should contain at least one signature with a key in // in that mutation. // 3. Signatures with no matching keys are simply ignored. -func VerifyKeys(oldValue []byte, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { +func verifyKeys(oldValue []byte, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { prevEntry := new(tpb.Entry) var verifiers map[string]signatures.Verifier var err error diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go index 15a434368..1044a313e 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go @@ -31,10 +31,6 @@ It has these top-level messages: GetMutationsResponse GetDomainInfoRequest GetDomainInfoResponse - GetMonitoringRequest - InvalidMutation - NotMatchingMapRootProof - GetMonitoringResponse */ package keytransparency_v1_types @@ -809,174 +805,6 @@ func (m *GetDomainInfoResponse) GetVrf() *keyspb.PublicKey { return nil } -// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. -type GetMonitoringRequest struct { - // start specifies the start epoch number from which monitoring results will - // be returned (ranging from [start, latestObserved] and starting at 1). - Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` -} - -func (m *GetMonitoringRequest) Reset() { *m = GetMonitoringRequest{} } -func (m *GetMonitoringRequest) String() string { return proto.CompactTextString(m) } -func (*GetMonitoringRequest) ProtoMessage() {} -func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } - -func (m *GetMonitoringRequest) GetStart() int64 { - if m != nil { - return m.Start - } - return 0 -} - -// InvalidMutation includes all information to reproduce that there was an -// invalid mutation from epoch e to e+1. -type InvalidMutation struct { - // old_leaf is the inclusion proof to the leaf at epoch e. - OldLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,1,opt,name=old_leaf,json=oldLeaf" json:"old_leaf,omitempty"` - // new_leaf is the inclusion proof to the leaf at epoch e+1. - NewLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,2,opt,name=new_leaf,json=newLeaf" json:"new_leaf,omitempty"` -} - -func (m *InvalidMutation) Reset() { *m = InvalidMutation{} } -func (m *InvalidMutation) String() string { return proto.CompactTextString(m) } -func (*InvalidMutation) ProtoMessage() {} -func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } - -func (m *InvalidMutation) GetOldLeaf() *trillian1.MapLeafInclusion { - if m != nil { - return m.OldLeaf - } - return nil -} - -func (m *InvalidMutation) GetNewLeaf() *trillian1.MapLeafInclusion { - if m != nil { - return m.NewLeaf - } - return nil -} - -// NotMatchingMapRootProof contains all data necessary to reproduce that set of -// mutations does not produce new expected map root. -type NotMatchingMapRootProof struct { - // map_root contains the map root hash the monitor observed. - MapRoot *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=map_root,json=mapRoot" json:"map_root,omitempty"` - // old_leafs is a list of inclusion proofs for the leafs in epoch e. - OldLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,2,rep,name=old_leafs,json=oldLeafs" json:"old_leafs,omitempty"` - // new_leafs is a list of inclusion proofs for changed leafs (from epoch e - // to epoch e+1). Hashing these produces a different hash than root hash in - // above's map_root. - NewLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,3,rep,name=new_leafs,json=newLeafs" json:"new_leafs,omitempty"` -} - -func (m *NotMatchingMapRootProof) Reset() { *m = NotMatchingMapRootProof{} } -func (m *NotMatchingMapRootProof) String() string { return proto.CompactTextString(m) } -func (*NotMatchingMapRootProof) ProtoMessage() {} -func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } - -func (m *NotMatchingMapRootProof) GetMapRoot() *trillian.SignedMapRoot { - if m != nil { - return m.MapRoot - } - return nil -} - -func (m *NotMatchingMapRootProof) GetOldLeafs() []*trillian1.MapLeafInclusion { - if m != nil { - return m.OldLeafs - } - return nil -} - -func (m *NotMatchingMapRootProof) GetNewLeafs() []*trillian1.MapLeafInclusion { - if m != nil { - return m.NewLeafs - } - return nil -} - -type GetMonitoringResponse struct { - // smr contains the map root for the sparse Merkle Tree signed with the - // monitor's key on success. If the checks were not successful the - // smr will be empty. The epochs are encoded into the smr map_revision. - Smr *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=smr" json:"smr,omitempty"` - // seen_timestamp_nanos contains the time in nanoseconds where this particular - // signed map root was retrieved and processed. The actual timestamp of the - // smr returned by the server is contained in above smr field. - SeenTimestampNanos int64 `protobuf:"varint,2,opt,name=seen_timestamp_nanos,json=seenTimestampNanos" json:"seen_timestamp_nanos,omitempty"` - // isValid signals if all verification steps for the requested epoch passed - // or not. - IsValid bool `protobuf:"varint,3,opt,name=isValid" json:"isValid,omitempty"` - // invalidMapSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - InvalidMapSigProof *trillian.SignedMapRoot `protobuf:"bytes,4,opt,name=invalidMapSigProof" json:"invalidMapSigProof,omitempty"` - // invalidLogSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - InvalidLogSigProof *trillian.SignedLogRoot `protobuf:"bytes,5,opt,name=invalidLogSigProof" json:"invalidLogSigProof,omitempty"` - // invalidMutation contains data to reproduce that there was an invalid - // mutation from epoch e to epoch e+1 - InvalidMutation *InvalidMutation `protobuf:"bytes,6,opt,name=invalidMutation" json:"invalidMutation,omitempty"` - // NotMatchingMapRoot contains all data to reproduce that the set of mutations - // does not produce observed new map root. - NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,7,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` -} - -func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } -func (m *GetMonitoringResponse) String() string { return proto.CompactTextString(m) } -func (*GetMonitoringResponse) ProtoMessage() {} -func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } - -func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { - if m != nil { - return m.Smr - } - return nil -} - -func (m *GetMonitoringResponse) GetSeenTimestampNanos() int64 { - if m != nil { - return m.SeenTimestampNanos - } - return 0 -} - -func (m *GetMonitoringResponse) GetIsValid() bool { - if m != nil { - return m.IsValid - } - return false -} - -func (m *GetMonitoringResponse) GetInvalidMapSigProof() *trillian.SignedMapRoot { - if m != nil { - return m.InvalidMapSigProof - } - return nil -} - -func (m *GetMonitoringResponse) GetInvalidLogSigProof() *trillian.SignedLogRoot { - if m != nil { - return m.InvalidLogSigProof - } - return nil -} - -func (m *GetMonitoringResponse) GetInvalidMutation() *InvalidMutation { - if m != nil { - return m.InvalidMutation - } - return nil -} - -func (m *GetMonitoringResponse) GetNotMatchingMapRoot() *NotMatchingMapRootProof { - if m != nil { - return m.NotMatchingMapRoot - } - return nil -} - func init() { proto.RegisterType((*Committed)(nil), "keytransparency.v1.types.Committed") proto.RegisterType((*EntryUpdate)(nil), "keytransparency.v1.types.EntryUpdate") @@ -995,97 +823,78 @@ func init() { proto.RegisterType((*GetMutationsResponse)(nil), "keytransparency.v1.types.GetMutationsResponse") proto.RegisterType((*GetDomainInfoRequest)(nil), "keytransparency.v1.types.GetDomainInfoRequest") proto.RegisterType((*GetDomainInfoResponse)(nil), "keytransparency.v1.types.GetDomainInfoResponse") - proto.RegisterType((*GetMonitoringRequest)(nil), "keytransparency.v1.types.GetMonitoringRequest") - proto.RegisterType((*InvalidMutation)(nil), "keytransparency.v1.types.InvalidMutation") - proto.RegisterType((*NotMatchingMapRootProof)(nil), "keytransparency.v1.types.NotMatchingMapRootProof") - proto.RegisterType((*GetMonitoringResponse)(nil), "keytransparency.v1.types.GetMonitoringResponse") } func init() { proto.RegisterFile("keytransparency_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1317 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xdd, 0x6e, 0x13, 0x47, - 0x14, 0x66, 0xed, 0x38, 0xb6, 0x4f, 0x02, 0xa6, 0x43, 0x20, 0x6e, 0x2a, 0x50, 0xb4, 0xa8, 0x2d, - 0x54, 0xc8, 0x21, 0x46, 0x86, 0x42, 0x2f, 0x4a, 0x81, 0x8a, 0x44, 0x49, 0x50, 0x34, 0x81, 0xf4, - 0x72, 0x35, 0xb1, 0xc7, 0x9b, 0x51, 0x76, 0x67, 0xb6, 0x3b, 0x63, 0xc3, 0x22, 0x55, 0xed, 0x03, - 0x54, 0xaa, 0xd4, 0x67, 0xe8, 0x33, 0xf4, 0xb6, 0x17, 0x7d, 0x89, 0xaa, 0x4f, 0x53, 0xcd, 0xcf, - 0xda, 0xeb, 0xc4, 0x8e, 0x03, 0x17, 0xbd, 0x49, 0x66, 0xce, 0x9c, 0x6f, 0xe6, 0x9c, 0xef, 0x7c, - 0x67, 0x66, 0x0d, 0xb7, 0x4e, 0x68, 0xa6, 0x52, 0xc2, 0x65, 0x42, 0x52, 0xca, 0xbb, 0x59, 0x30, - 0xdc, 0x0c, 0x54, 0x96, 0x50, 0xd9, 0x4a, 0x52, 0xa1, 0x04, 0x6a, 0x9e, 0x5a, 0x6f, 0x0d, 0x37, - 0x5b, 0x66, 0x7d, 0xad, 0x13, 0x32, 0x75, 0x3c, 0x38, 0x6a, 0x75, 0x45, 0xbc, 0x11, 0x0a, 0x11, - 0x46, 0x74, 0x43, 0xa5, 0x2c, 0x8a, 0x18, 0xe1, 0x1b, 0xdd, 0x34, 0x4b, 0x94, 0xd8, 0x38, 0xa1, - 0x99, 0x4c, 0x8e, 0xdc, 0x3f, 0xbb, 0xe1, 0xda, 0x83, 0xf9, 0x30, 0xc9, 0xc2, 0xe4, 0xc8, 0xfe, - 0x75, 0xa0, 0xbb, 0xe7, 0x80, 0xf2, 0x81, 0x73, 0xdd, 0xbc, 0x80, 0x6b, 0x10, 0x93, 0x24, 0x20, - 0x09, 0xb3, 0x10, 0x7f, 0x13, 0xea, 0xcf, 0x45, 0x1c, 0x33, 0xa5, 0x68, 0x0f, 0x5d, 0x85, 0xf2, - 0x09, 0xcd, 0x9a, 0xde, 0xba, 0x77, 0x67, 0x19, 0xeb, 0x21, 0x42, 0xb0, 0xd0, 0x23, 0x8a, 0x34, - 0x4b, 0xc6, 0x64, 0xc6, 0xfe, 0xaf, 0x1e, 0x2c, 0x7d, 0xcf, 0x55, 0x9a, 0xbd, 0x49, 0x7a, 0x44, - 0x51, 0xf4, 0x04, 0x16, 0x07, 0x66, 0x64, 0xbc, 0x96, 0xda, 0x7e, 0x6b, 0x16, 0x6f, 0xad, 0x03, - 0x16, 0x72, 0xda, 0xdb, 0x39, 0xc4, 0x0e, 0x81, 0xbe, 0x83, 0x7a, 0x37, 0x3f, 0xbe, 0x59, 0x36, - 0xf0, 0xdb, 0xb3, 0xe1, 0xa3, 0x48, 0xf1, 0x18, 0xe5, 0x0f, 0xa0, 0x62, 0xa2, 0x41, 0xb7, 0x00, - 0xac, 0x35, 0xa6, 0x5c, 0xb9, 0x24, 0x0a, 0x16, 0xb4, 0x0b, 0x0d, 0x32, 0x50, 0xc7, 0x22, 0x65, - 0xef, 0x69, 0x2f, 0xd0, 0x85, 0x69, 0x96, 0xd6, 0xcb, 0xe7, 0x9f, 0xb8, 0x3f, 0x38, 0x8a, 0x58, - 0x77, 0x87, 0x66, 0xf8, 0xca, 0x18, 0xbb, 0x43, 0x33, 0xe9, 0xff, 0xe1, 0x41, 0x7d, 0xb4, 0x8a, - 0xd6, 0xa0, 0x4a, 0x7b, 0xed, 0x4e, 0x67, 0xf3, 0xb1, 0x3d, 0x78, 0xeb, 0x12, 0xce, 0x0d, 0xe8, - 0x1b, 0xf8, 0x34, 0x95, 0x24, 0x18, 0xd2, 0x94, 0xf5, 0x33, 0xc6, 0xc3, 0x40, 0x1e, 0x93, 0x76, - 0xe7, 0x61, 0xf0, 0xe0, 0xfe, 0xa3, 0xb6, 0x25, 0x76, 0xeb, 0x12, 0xbe, 0x91, 0x4a, 0x72, 0x98, - 0x7b, 0x1c, 0x18, 0x07, 0xbd, 0x8e, 0xda, 0xb0, 0x42, 0xbb, 0xbd, 0x09, 0x78, 0xd2, 0xee, 0x3c, - 0x34, 0x5c, 0x69, 0x1c, 0x32, 0xab, 0x23, 0xe4, 0x7e, 0xbb, 0xf3, 0xf0, 0x19, 0x40, 0xed, 0x84, - 0x66, 0x46, 0xca, 0x7e, 0x1b, 0x6a, 0x3b, 0x34, 0x3b, 0x24, 0xd1, 0x80, 0x4e, 0x29, 0xef, 0x0a, - 0x54, 0x86, 0x7a, 0xc9, 0xd5, 0xd7, 0x4e, 0xfc, 0xdf, 0x4b, 0x50, 0xcb, 0x2b, 0x85, 0xbe, 0x85, - 0xba, 0xde, 0xcc, 0xba, 0x79, 0xf3, 0x0a, 0x9c, 0x9f, 0x85, 0x75, 0x04, 0xf6, 0x54, 0x0c, 0x20, - 0x59, 0xc8, 0x89, 0x1a, 0xa4, 0x34, 0x67, 0xbc, 0x3d, 0x5f, 0x22, 0x66, 0x60, 0x41, 0xa6, 0xbc, - 0xb8, 0xb0, 0x0b, 0x5a, 0x83, 0x5a, 0x92, 0xd2, 0x21, 0x13, 0x03, 0x69, 0x99, 0xc0, 0xa3, 0xf9, - 0xda, 0x1b, 0x68, 0x9c, 0x82, 0x16, 0x13, 0xaf, 0xdb, 0xc4, 0xef, 0x15, 0x13, 0x5f, 0x6a, 0xdf, - 0x68, 0xd9, 0x8e, 0x7b, 0xc1, 0x42, 0xa6, 0x48, 0x14, 0x65, 0x36, 0x0a, 0x47, 0xc8, 0x93, 0xd2, - 0xd7, 0x9e, 0xff, 0x0e, 0x6a, 0x7b, 0x03, 0x45, 0x14, 0x13, 0xbc, 0xa0, 0x78, 0xef, 0x83, 0x15, - 0x7f, 0x1f, 0x2a, 0x49, 0x2a, 0x44, 0xdf, 0x9d, 0xbc, 0xd6, 0x1a, 0xf5, 0xf0, 0x1e, 0x49, 0x76, - 0x29, 0xe9, 0x6f, 0xf3, 0x6e, 0x34, 0x90, 0x4c, 0x70, 0x6c, 0x1d, 0x7d, 0x06, 0x8d, 0x97, 0x54, - 0x59, 0x12, 0xe8, 0x8f, 0x03, 0x2a, 0x15, 0x5a, 0x85, 0xea, 0x40, 0xd2, 0x34, 0x60, 0x3d, 0x97, - 0xd4, 0xa2, 0x9e, 0x6e, 0xf7, 0xd0, 0x75, 0x58, 0x24, 0x49, 0xa2, 0xed, 0x25, 0x63, 0xaf, 0x90, - 0x24, 0xd9, 0xee, 0xa1, 0x2f, 0xa0, 0xd1, 0x67, 0xa9, 0x54, 0x81, 0x4a, 0x29, 0x0d, 0x24, 0x7b, - 0x4f, 0x0d, 0x6d, 0x65, 0x7c, 0xd9, 0x98, 0x5f, 0xa7, 0x94, 0x1e, 0xb0, 0xf7, 0xd4, 0xff, 0xb7, - 0x04, 0x57, 0xc7, 0x67, 0xc9, 0x44, 0x70, 0x49, 0xd1, 0x67, 0x50, 0x1f, 0xa6, 0xfd, 0xc0, 0x46, - 0x6d, 0xc5, 0x53, 0x1b, 0xa6, 0xfd, 0x7d, 0x3d, 0x9f, 0x6c, 0xe0, 0xd2, 0xc7, 0x34, 0x30, 0x7a, - 0x0c, 0x10, 0x51, 0x92, 0x1f, 0x50, 0x9e, 0x4b, 0x4b, 0x5d, 0x7b, 0xdb, 0xd3, 0xef, 0x42, 0x59, - 0xc6, 0x69, 0x73, 0xc1, 0x60, 0x56, 0xc7, 0x18, 0xcb, 0xfa, 0x1e, 0x49, 0xb0, 0x10, 0x0a, 0x6b, - 0x1f, 0xd4, 0x86, 0x5a, 0x24, 0xc2, 0x20, 0x15, 0x42, 0x35, 0x2b, 0xd3, 0xfd, 0x77, 0x45, 0x68, - 0xfc, 0xab, 0x91, 0x1d, 0xa0, 0x2f, 0xa1, 0xa1, 0x31, 0x5d, 0xc1, 0x25, 0x93, 0x4a, 0xa7, 0xd2, - 0x5c, 0x5c, 0x2f, 0xdf, 0x59, 0xc6, 0x57, 0x22, 0x11, 0x3e, 0x1f, 0x5b, 0xd1, 0x6d, 0xb8, 0xac, - 0x1d, 0x59, 0x1e, 0x63, 0xb3, 0x6a, 0xdc, 0x96, 0x23, 0x11, 0x8e, 0xe2, 0xd6, 0x37, 0xc6, 0xea, - 0x2e, 0x93, 0x96, 0xdd, 0x2d, 0x26, 0x95, 0xb8, 0x40, 0x41, 0x57, 0xa0, 0x22, 0x15, 0x49, 0x95, - 0xe1, 0xb6, 0x8c, 0xed, 0x44, 0x97, 0x24, 0x21, 0x61, 0xa1, 0x92, 0x15, 0x5c, 0xd3, 0x06, 0x5d, - 0xc4, 0x82, 0x06, 0x16, 0xe6, 0x68, 0xa0, 0x32, 0x4d, 0x03, 0x3f, 0x41, 0xf3, 0x6c, 0x94, 0x4e, - 0x0a, 0xcf, 0x60, 0xd1, 0x74, 0x84, 0x6c, 0x7a, 0xa6, 0x8f, 0xbf, 0x9a, 0x5d, 0xea, 0xd3, 0x32, - 0xc2, 0x0e, 0x89, 0x6e, 0x02, 0x70, 0xfa, 0x4e, 0x05, 0xc5, 0xb4, 0xea, 0xda, 0x72, 0xa0, 0x0d, - 0xfe, 0x9f, 0x1e, 0x20, 0xfb, 0xb0, 0xfc, 0x1f, 0x8a, 0x47, 0x5b, 0xb0, 0x4c, 0xf5, 0x39, 0x81, - 0x6b, 0x68, 0x2b, 0xa5, 0xcf, 0x67, 0xe7, 0x55, 0x78, 0xf9, 0xf0, 0x12, 0x1d, 0x4f, 0xfc, 0x1f, - 0xe0, 0xda, 0x44, 0xdc, 0x8e, 0xb2, 0xa7, 0x79, 0xbf, 0xdb, 0xab, 0xe2, 0x43, 0x18, 0x73, 0xfd, - 0xff, 0x9b, 0x07, 0xd7, 0x5e, 0x52, 0x95, 0xdf, 0x3e, 0x32, 0xa7, 0x64, 0x05, 0x2a, 0x34, 0x11, - 0xdd, 0x63, 0xb3, 0x73, 0x19, 0xdb, 0xc9, 0xb4, 0xc4, 0x4b, 0xd3, 0x12, 0xbf, 0x09, 0x60, 0x24, - 0xa4, 0xc4, 0x09, 0xe5, 0x86, 0x9b, 0x3a, 0x36, 0xa2, 0x7a, 0xad, 0x0d, 0x93, 0x0a, 0x5b, 0x98, - 0x54, 0x98, 0xff, 0x77, 0x09, 0x56, 0x26, 0x23, 0x72, 0xc9, 0x4e, 0x0f, 0xc9, 0x75, 0x69, 0xe9, - 0x03, 0xbb, 0xb4, 0xfc, 0xf1, 0x5d, 0xba, 0x70, 0xb1, 0x2e, 0xad, 0x9c, 0xed, 0x52, 0xf4, 0x14, - 0xea, 0x71, 0x9e, 0x97, 0xe9, 0xf6, 0x73, 0xaf, 0xf7, 0x9c, 0x02, 0x3c, 0x06, 0xe9, 0x0a, 0x18, - 0x81, 0x17, 0xe8, 0xad, 0x1a, 0x7a, 0x2f, 0x6b, 0xf3, 0x7e, 0x4e, 0xb1, 0x7f, 0xc3, 0x90, 0xf8, - 0x42, 0xc4, 0x84, 0xf1, 0x6d, 0xde, 0x17, 0xae, 0xae, 0xfe, 0x2f, 0x1e, 0x5c, 0x3f, 0xb5, 0xe0, - 0xe8, 0x5d, 0x87, 0x72, 0x24, 0x42, 0xa7, 0xa4, 0x2b, 0x63, 0x62, 0x74, 0x51, 0xb1, 0x5e, 0xd2, - 0x1e, 0x31, 0x49, 0x1c, 0xd5, 0x67, 0x3c, 0x62, 0x92, 0xa0, 0xdb, 0x50, 0x1e, 0xa6, 0xf9, 0x35, - 0xfb, 0x49, 0xcb, 0x7d, 0x9f, 0x8e, 0xbf, 0x73, 0xf4, 0xaa, 0x7f, 0xcf, 0xd6, 0x57, 0x70, 0xa6, - 0x44, 0xca, 0x78, 0x58, 0x90, 0x9c, 0x6d, 0x5b, 0xaf, 0x70, 0x1b, 0xf9, 0x3f, 0x43, 0x63, 0x9b, - 0x0f, 0x49, 0xc4, 0x7a, 0xa3, 0x17, 0xb2, 0x03, 0x35, 0x11, 0xf5, 0x02, 0x7d, 0x53, 0xbb, 0x70, - 0xcf, 0xbb, 0xd1, 0xab, 0x22, 0xea, 0x69, 0x8b, 0x86, 0x71, 0xfa, 0xd6, 0xc2, 0xe6, 0xbf, 0x8f, - 0x55, 0x4e, 0xdf, 0x6a, 0x8b, 0xff, 0x97, 0x07, 0xab, 0xaf, 0x84, 0xda, 0x23, 0xaa, 0x7b, 0xcc, - 0x78, 0xe8, 0x14, 0x65, 0x9f, 0x88, 0x36, 0xd4, 0xf4, 0x17, 0xaf, 0x51, 0x94, 0x77, 0xbe, 0x02, - 0xab, 0xb1, 0x1d, 0xa0, 0x47, 0x50, 0xcf, 0xa3, 0xcf, 0xbf, 0x58, 0xce, 0x8b, 0xa3, 0xe6, 0xc2, - 0x97, 0x1a, 0x98, 0xc7, 0xaf, 0x3f, 0x4c, 0xe6, 0x02, 0x5d, 0x02, 0xd2, 0xff, 0xa7, 0x6c, 0x6a, - 0x5e, 0x64, 0xdc, 0xd5, 0xdc, 0x35, 0x8f, 0x77, 0x81, 0xe6, 0xb9, 0x0f, 0x2b, 0x92, 0x52, 0x1e, - 0x28, 0x16, 0x53, 0xa9, 0x48, 0x9c, 0x04, 0x9c, 0x70, 0x21, 0x5d, 0xff, 0x23, 0xbd, 0xf6, 0x3a, - 0x5f, 0x7a, 0xa5, 0x57, 0x50, 0x13, 0xaa, 0x4c, 0x1e, 0xea, 0xca, 0x19, 0x41, 0xd4, 0x70, 0x3e, - 0x45, 0x2f, 0x01, 0x31, 0x57, 0x53, 0x92, 0x1c, 0xb0, 0xd0, 0x90, 0x39, 0xef, 0xa1, 0x9d, 0x02, - 0x29, 0x6c, 0xb4, 0x2b, 0xc2, 0xd1, 0x46, 0x73, 0x5e, 0xe0, 0x29, 0x10, 0x74, 0x00, 0x0d, 0x36, - 0xa9, 0xb2, 0xe6, 0xa2, 0xd9, 0xe5, 0xee, 0xec, 0xf6, 0x3c, 0x25, 0x4b, 0x7c, 0x7a, 0x07, 0x44, - 0x00, 0xf1, 0x33, 0xc2, 0x31, 0xed, 0xba, 0xd4, 0xde, 0x9c, 0xbd, 0xef, 0x0c, 0xb1, 0xe1, 0x29, - 0x9b, 0x1d, 0x2d, 0x9a, 0x1f, 0x5a, 0x0f, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xb5, 0xfd, 0xe6, - 0xc1, 0x6e, 0x0e, 0x00, 0x00, + // 1079 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5d, 0x6e, 0x1b, 0x37, + 0x10, 0x8e, 0xb4, 0x96, 0x2c, 0x8d, 0xff, 0x52, 0xc6, 0xb1, 0x55, 0x15, 0x09, 0x8c, 0x35, 0xda, + 0x26, 0x45, 0x21, 0xc7, 0x6b, 0xc8, 0x6d, 0xd2, 0x87, 0xa6, 0x49, 0x8a, 0xd8, 0xb0, 0x0d, 0x18, + 0x74, 0xe2, 0x3e, 0x2e, 0x68, 0x89, 0x5a, 0x13, 0x5e, 0x2d, 0x59, 0x92, 0x2b, 0x64, 0x0d, 0x14, + 0xe8, 0x01, 0x0a, 0x14, 0xe8, 0x19, 0x7a, 0x86, 0x5e, 0xa0, 0xb7, 0xe8, 0x69, 0x0a, 0x92, 0xbb, + 0xfa, 0xb1, 0xe5, 0xbf, 0x3c, 0xe4, 0xc5, 0x26, 0x67, 0xe6, 0xdb, 0x99, 0xf9, 0xe6, 0x9b, 0xd5, + 0xc2, 0xe3, 0x33, 0x9a, 0x69, 0x49, 0x12, 0x25, 0x88, 0xa4, 0x49, 0x27, 0x0b, 0x07, 0x9b, 0xa1, + 0xce, 0x04, 0x55, 0x2d, 0x21, 0xb9, 0xe6, 0xa8, 0x71, 0xc1, 0xdf, 0x1a, 0x6c, 0xb6, 0xac, 0xbf, + 0xd9, 0x8e, 0x98, 0x3e, 0x4d, 0x4f, 0x5a, 0x1d, 0xde, 0xdf, 0x88, 0x38, 0x8f, 0x62, 0xba, 0xa1, + 0x25, 0x8b, 0x63, 0x46, 0x92, 0x8d, 0x8e, 0xcc, 0x84, 0xe6, 0x1b, 0x67, 0x34, 0x53, 0xe2, 0x24, + 0xff, 0xe7, 0x1e, 0xd8, 0xdc, 0xba, 0x19, 0xa6, 0x58, 0x24, 0x4e, 0xdc, 0xdf, 0x1c, 0xf4, 0xf4, + 0x1a, 0x50, 0x71, 0xc8, 0x43, 0x37, 0x6f, 0x11, 0x1a, 0xf6, 0x89, 0x08, 0x89, 0x60, 0x0e, 0xe2, + 0x6f, 0x42, 0xfd, 0x35, 0xef, 0xf7, 0x99, 0xd6, 0xb4, 0x8b, 0xee, 0x83, 0x77, 0x46, 0xb3, 0x46, + 0x69, 0xad, 0xf4, 0x64, 0x1e, 0x9b, 0x23, 0x42, 0x30, 0xd3, 0x25, 0x9a, 0x34, 0xca, 0xd6, 0x64, + 0xcf, 0xfe, 0x1f, 0x25, 0x98, 0xfb, 0x39, 0xd1, 0x32, 0x7b, 0x2f, 0xba, 0x44, 0x53, 0xf4, 0x02, + 0xaa, 0xa9, 0x3d, 0xd9, 0xa8, 0xb9, 0xc0, 0x6f, 0x5d, 0xc5, 0x5b, 0xeb, 0x88, 0x45, 0x09, 0xed, + 0xee, 0x1d, 0xe3, 0x1c, 0x81, 0x7e, 0x82, 0x7a, 0xa7, 0x48, 0xdf, 0xf0, 0x2c, 0x7c, 0xfd, 0x6a, + 0xf8, 0xb0, 0x52, 0x3c, 0x42, 0xf9, 0x29, 0x54, 0x6c, 0x35, 0xe8, 0x31, 0x80, 0xb3, 0xf6, 0x69, + 0xa2, 0xf3, 0x26, 0xc6, 0x2c, 0x68, 0x1f, 0x96, 0x48, 0xaa, 0x4f, 0xb9, 0x64, 0xe7, 0xb4, 0x1b, + 0x9a, 0xc1, 0x34, 0xca, 0x6b, 0xde, 0xf5, 0x19, 0x0f, 0xd3, 0x93, 0x98, 0x75, 0xf6, 0x68, 0x86, + 0x17, 0x47, 0xd8, 0x3d, 0x9a, 0x29, 0xff, 0xef, 0x12, 0xd4, 0x87, 0x5e, 0xd4, 0x84, 0x59, 0xda, + 0x0d, 0xda, 0xed, 0xcd, 0xe7, 0x2e, 0xf1, 0xce, 0x3d, 0x5c, 0x18, 0xd0, 0x0f, 0xf0, 0xb9, 0x54, + 0x24, 0x1c, 0x50, 0xc9, 0x7a, 0x19, 0x4b, 0xa2, 0x50, 0x9d, 0x92, 0xa0, 0xbd, 0x1d, 0x6e, 0x3d, + 0xfb, 0x2e, 0x70, 0xc4, 0xee, 0xdc, 0xc3, 0x2b, 0x52, 0x91, 0xe3, 0x22, 0xe2, 0xc8, 0x06, 0x18, + 0x3f, 0x0a, 0x60, 0x99, 0x76, 0xba, 0x13, 0x70, 0x11, 0xb4, 0xb7, 0x2d, 0x57, 0x06, 0x87, 0xac, + 0x77, 0x88, 0x3c, 0x0c, 0xda, 0xdb, 0xaf, 0x00, 0x6a, 0x67, 0x34, 0xb3, 0x52, 0xf6, 0x03, 0xa8, + 0xed, 0xd1, 0xec, 0x98, 0xc4, 0x29, 0x9d, 0x32, 0xde, 0x65, 0xa8, 0x0c, 0x8c, 0x2b, 0x9f, 0xaf, + 0xbb, 0xf8, 0x7f, 0x95, 0xa1, 0x56, 0x4c, 0x0a, 0xfd, 0x08, 0x75, 0xf3, 0x30, 0x17, 0x56, 0xba, + 0x69, 0xc0, 0x45, 0x2e, 0x6c, 0x2a, 0x70, 0x59, 0x31, 0x80, 0x62, 0x51, 0x42, 0x74, 0x2a, 0x69, + 0xc1, 0x78, 0x70, 0xb3, 0x44, 0xec, 0xc1, 0x81, 0xec, 0x78, 0xf1, 0xd8, 0x53, 0x50, 0x13, 0x6a, + 0x42, 0xd2, 0x01, 0xe3, 0xa9, 0x72, 0x4c, 0xe0, 0xe1, 0xbd, 0xf9, 0x1e, 0x96, 0x2e, 0x40, 0xc7, + 0x1b, 0xaf, 0xbb, 0xc6, 0xbf, 0x1d, 0x6f, 0x7c, 0x2e, 0x58, 0x69, 0xb9, 0x8d, 0x7b, 0xc3, 0x22, + 0xa6, 0x49, 0x1c, 0x67, 0xae, 0x8a, 0x9c, 0x90, 0x17, 0xe5, 0xef, 0x4b, 0xfe, 0x07, 0xa8, 0x1d, + 0xa4, 0x9a, 0x68, 0xc6, 0x93, 0x31, 0xc5, 0x97, 0xee, 0xac, 0xf8, 0x67, 0x50, 0x11, 0x92, 0xf3, + 0x5e, 0x9e, 0xb9, 0xd9, 0x1a, 0xee, 0xf0, 0x01, 0x11, 0xfb, 0x94, 0xf4, 0x76, 0x93, 0x4e, 0x9c, + 0x2a, 0xc6, 0x13, 0xec, 0x02, 0x7d, 0x06, 0x4b, 0x6f, 0xa9, 0x76, 0x24, 0xd0, 0x5f, 0x53, 0xaa, + 0x34, 0x5a, 0x85, 0xd9, 0x54, 0x51, 0x19, 0xb2, 0x6e, 0xde, 0x54, 0xd5, 0x5c, 0x77, 0xbb, 0xe8, + 0x21, 0x54, 0x89, 0x10, 0xc6, 0x5e, 0xb6, 0xf6, 0x0a, 0x11, 0x62, 0xb7, 0x8b, 0xbe, 0x82, 0xa5, + 0x1e, 0x93, 0x4a, 0x87, 0x5a, 0x52, 0x1a, 0x2a, 0x76, 0x4e, 0x2d, 0x6d, 0x1e, 0x5e, 0xb0, 0xe6, + 0x77, 0x92, 0xd2, 0x23, 0x76, 0x4e, 0xfd, 0xff, 0xca, 0x70, 0x7f, 0x94, 0x4b, 0x09, 0x9e, 0x28, + 0x8a, 0xbe, 0x80, 0xfa, 0x40, 0xf6, 0x42, 0x57, 0xb5, 0x13, 0x4f, 0x6d, 0x20, 0x7b, 0x87, 0xe6, + 0x3e, 0xb9, 0xc0, 0xe5, 0x8f, 0x59, 0x60, 0xf4, 0x1c, 0x20, 0xa6, 0xa4, 0x48, 0xe0, 0xdd, 0x48, + 0x4b, 0xdd, 0x44, 0xbb, 0xec, 0x4f, 0xc1, 0x53, 0x7d, 0xd9, 0x98, 0xb1, 0x98, 0xd5, 0x11, 0xc6, + 0xb1, 0x7e, 0x40, 0x04, 0xe6, 0x5c, 0x63, 0x13, 0x83, 0x02, 0xa8, 0xc5, 0x3c, 0x0a, 0x25, 0xe7, + 0xba, 0x51, 0x99, 0x1e, 0xbf, 0xcf, 0x23, 0x1b, 0x3f, 0x1b, 0xbb, 0x03, 0xfa, 0x1a, 0x96, 0x0c, + 0xa6, 0xc3, 0x13, 0xc5, 0x94, 0x36, 0xad, 0x34, 0xaa, 0x6b, 0xde, 0x93, 0x79, 0xbc, 0x18, 0xf3, + 0xe8, 0xf5, 0xc8, 0x8a, 0xd6, 0x61, 0xc1, 0x04, 0xb2, 0xa2, 0xc6, 0xc6, 0xac, 0x0d, 0x9b, 0x8f, + 0x79, 0x34, 0xac, 0xdb, 0xbc, 0x31, 0x56, 0xf7, 0x99, 0x72, 0xec, 0xee, 0x30, 0xa5, 0xf9, 0x2d, + 0x06, 0xba, 0x0c, 0x15, 0xa5, 0x89, 0xd4, 0x96, 0x5b, 0x0f, 0xbb, 0x8b, 0x19, 0x89, 0x20, 0xd1, + 0xd8, 0x24, 0x2b, 0xb8, 0x66, 0x0c, 0x66, 0x88, 0x63, 0x1a, 0x98, 0xb9, 0x41, 0x03, 0x95, 0x69, + 0x1a, 0xf8, 0x0d, 0x1a, 0x97, 0xab, 0xcc, 0xa5, 0xf0, 0x0a, 0xaa, 0x76, 0x23, 0x54, 0xa3, 0x64, + 0xf7, 0xf8, 0x9b, 0xab, 0x47, 0x7d, 0x51, 0x46, 0x38, 0x47, 0xa2, 0x47, 0x00, 0x09, 0xfd, 0xa0, + 0xc3, 0xf1, 0xb6, 0xea, 0xc6, 0x72, 0x64, 0x0c, 0xfe, 0x3f, 0x25, 0x40, 0xee, 0x87, 0xe5, 0x53, + 0x28, 0x1e, 0xed, 0xc0, 0x3c, 0x35, 0x79, 0xc2, 0x7c, 0xa1, 0x9d, 0x94, 0xbe, 0xbc, 0xba, 0xaf, + 0xb1, 0x5f, 0x3e, 0x3c, 0x47, 0x47, 0x17, 0xff, 0x17, 0x78, 0x30, 0x51, 0x77, 0x4e, 0xd9, 0xcb, + 0x62, 0xdf, 0xdd, 0xab, 0xe2, 0x2e, 0x8c, 0xe5, 0xfb, 0xff, 0x67, 0x09, 0x1e, 0xbc, 0xa5, 0xba, + 0x78, 0xfb, 0xa8, 0x82, 0x92, 0x65, 0xa8, 0x50, 0xc1, 0x3b, 0xa7, 0xf6, 0xc9, 0x1e, 0x76, 0x97, + 0x69, 0x8d, 0x97, 0xa7, 0x35, 0xfe, 0x08, 0xc0, 0x4a, 0x48, 0xf3, 0x33, 0x9a, 0x58, 0x6e, 0xea, + 0xd8, 0x8a, 0xea, 0x9d, 0x31, 0x4c, 0x2a, 0x6c, 0x66, 0x52, 0x61, 0xfe, 0xbf, 0x65, 0x58, 0x9e, + 0xac, 0x28, 0x6f, 0x76, 0x7a, 0x49, 0xf9, 0x96, 0x96, 0xef, 0xb8, 0xa5, 0xde, 0xc7, 0x6f, 0xe9, + 0xcc, 0xed, 0xb6, 0xb4, 0x72, 0x79, 0x4b, 0xd1, 0x4b, 0xa8, 0xf7, 0x8b, 0xbe, 0xec, 0xb6, 0x5f, + 0xfb, 0x7a, 0x2f, 0x28, 0xc0, 0x23, 0x90, 0x99, 0x80, 0x15, 0xf8, 0x18, 0xbd, 0xb3, 0x96, 0xde, + 0x05, 0x63, 0x3e, 0x2c, 0x28, 0xf6, 0x57, 0x2c, 0x89, 0x6f, 0x78, 0x9f, 0xb0, 0x64, 0x37, 0xe9, + 0xf1, 0x7c, 0xae, 0xfe, 0xef, 0x25, 0x78, 0x78, 0xc1, 0x91, 0xd3, 0xbb, 0x06, 0x5e, 0xcc, 0xa3, + 0x5c, 0x49, 0x8b, 0x23, 0x62, 0xcc, 0x50, 0xb1, 0x71, 0x99, 0x88, 0x3e, 0x11, 0x39, 0xd5, 0x97, + 0x22, 0xfa, 0x44, 0xa0, 0x75, 0xf0, 0x06, 0xb2, 0x78, 0xcd, 0x7e, 0xd6, 0xca, 0xbf, 0x4f, 0x47, + 0xdf, 0x39, 0xc6, 0x7b, 0x52, 0xb5, 0x1f, 0x87, 0x5b, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xea, + 0x22, 0xfb, 0x26, 0x22, 0x0b, 0x00, 0x00, } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto index 8badf84fa..3b8a038ee 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto @@ -250,68 +250,4 @@ message GetDomainInfoResponse { trillian.Tree map = 2; // Vrf contains the VRF public key. keyspb.PublicKey vrf = 3; -} - -// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. -message GetMonitoringRequest { - // start specifies the start epoch number from which monitoring results will - // be returned (ranging from [start, latestObserved] and starting at 1). - int64 start = 1; -} - -// InvalidMutation includes all information to reproduce that there was an -// invalid mutation from epoch e to e+1. -message InvalidMutation { - // old_leaf is the inclusion proof to the leaf at epoch e. - trillian.MapLeafInclusion old_leaf = 1; - // new_leaf is the inclusion proof to the leaf at epoch e+1. - trillian.MapLeafInclusion new_leaf = 2; -} - -// NotMatchingMapRootProof contains all data necessary to reproduce that set of -// mutations does not produce new expected map root. -message NotMatchingMapRootProof { - // map_root contains the map root hash the monitor observed. - trillian.SignedMapRoot map_root = 1; - // old_leafs is a list of inclusion proofs for the leafs in epoch e. - repeated trillian.MapLeafInclusion old_leafs = 2; - // new_leafs is a list of inclusion proofs for changed leafs (from epoch e - // to epoch e+1). Hashing these produces a different hash than root hash in - // above's map_root. - repeated trillian.MapLeafInclusion new_leafs = 3; -} - -message GetMonitoringResponse { - // smr contains the map root for the sparse Merkle Tree signed with the - // monitor's key on success. If the checks were not successful the - // smr will be empty. The epochs are encoded into the smr map_revision. - trillian.SignedMapRoot smr = 1; - - // seen_timestamp_nanos contains the time in nanoseconds where this particular - // signed map root was retrieved and processed. The actual timestamp of the - // smr returned by the server is contained in above smr field. - int64 seen_timestamp_nanos = 2; - - // - // The following fields provide more information about each failure in this - // response, if any. - // - - // isValid signals if all verification steps for the requested epoch passed - // or not. - bool isValid = 3; - // invalidMapSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - trillian.SignedMapRoot invalidMapSigProof = 4; - // invalidLogSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - trillian.SignedLogRoot invalidLogSigProof = 5; - // invalidMutation contains data to reproduce that there was an invalid - // mutation from epoch e to epoch e+1 - InvalidMutation invalidMutation = 6; - // NotMatchingMapRoot contains all data to reproduce that the set of mutations - // does not produce observed new map root. - NotMatchingMapRootProof notMatchingMapRoot = 7; } \ No newline at end of file diff --git a/core/proto/monitor_v1_types/gen.go b/core/proto/monitor_v1_types/gen.go new file mode 100644 index 000000000..624949b57 --- /dev/null +++ b/core/proto/monitor_v1_types/gen.go @@ -0,0 +1,17 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis --go_out=:. monitor_v1_types.proto + +package monitor_v1_types diff --git a/core/proto/monitor_v1_types/monitor_v1_types.pb.go b/core/proto/monitor_v1_types/monitor_v1_types.pb.go new file mode 100644 index 000000000..6301d6f0a --- /dev/null +++ b/core/proto/monitor_v1_types/monitor_v1_types.pb.go @@ -0,0 +1,245 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: monitor_v1_types.proto + +/* +Package monitor_v1_types is a generated protocol buffer package. + +Key Transparency Monitor Service + + +It is generated from these files: + monitor_v1_types.proto + +It has these top-level messages: + GetMonitoringRequest + InvalidMutation + NotMatchingMapRootProof + GetMonitoringResponse +*/ +package monitor_v1_types + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import trillian "github.com/google/trillian" +import trillian1 "github.com/google/trillian" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. +type GetMonitoringRequest struct { + // start specifies the start epoch number from which monitoring results will + // be returned (ranging from [start, latestObserved] and starting at 1). + Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` +} + +func (m *GetMonitoringRequest) Reset() { *m = GetMonitoringRequest{} } +func (m *GetMonitoringRequest) String() string { return proto.CompactTextString(m) } +func (*GetMonitoringRequest) ProtoMessage() {} +func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *GetMonitoringRequest) GetStart() int64 { + if m != nil { + return m.Start + } + return 0 +} + +// InvalidMutation includes all information to reproduce that there was an +// invalid mutation from epoch e to e+1. +type InvalidMutation struct { + // old_leaf is the inclusion proof to the leaf at epoch e. + OldLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,1,opt,name=old_leaf,json=oldLeaf" json:"old_leaf,omitempty"` + // new_leaf is the inclusion proof to the leaf at epoch e+1. + NewLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,2,opt,name=new_leaf,json=newLeaf" json:"new_leaf,omitempty"` +} + +func (m *InvalidMutation) Reset() { *m = InvalidMutation{} } +func (m *InvalidMutation) String() string { return proto.CompactTextString(m) } +func (*InvalidMutation) ProtoMessage() {} +func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *InvalidMutation) GetOldLeaf() *trillian1.MapLeafInclusion { + if m != nil { + return m.OldLeaf + } + return nil +} + +func (m *InvalidMutation) GetNewLeaf() *trillian1.MapLeafInclusion { + if m != nil { + return m.NewLeaf + } + return nil +} + +// NotMatchingMapRootProof contains all data necessary to reproduce that set of +// mutations does not produce new expected map root. +type NotMatchingMapRootProof struct { + // map_root contains the map root hash the monitor observed. + MapRoot *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=map_root,json=mapRoot" json:"map_root,omitempty"` + // old_leafs is a list of inclusion proofs for the leafs in epoch e. + OldLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,2,rep,name=old_leafs,json=oldLeafs" json:"old_leafs,omitempty"` + // new_leafs is a list of inclusion proofs for changed leafs (from epoch e + // to epoch e+1). Hashing these produces a different hash than root hash in + // above's map_root. + NewLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,3,rep,name=new_leafs,json=newLeafs" json:"new_leafs,omitempty"` +} + +func (m *NotMatchingMapRootProof) Reset() { *m = NotMatchingMapRootProof{} } +func (m *NotMatchingMapRootProof) String() string { return proto.CompactTextString(m) } +func (*NotMatchingMapRootProof) ProtoMessage() {} +func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *NotMatchingMapRootProof) GetMapRoot() *trillian.SignedMapRoot { + if m != nil { + return m.MapRoot + } + return nil +} + +func (m *NotMatchingMapRootProof) GetOldLeafs() []*trillian1.MapLeafInclusion { + if m != nil { + return m.OldLeafs + } + return nil +} + +func (m *NotMatchingMapRootProof) GetNewLeafs() []*trillian1.MapLeafInclusion { + if m != nil { + return m.NewLeafs + } + return nil +} + +type GetMonitoringResponse struct { + // smr contains the map root for the sparse Merkle Tree signed with the + // monitor's key on success. If the checks were not successful the + // smr will be empty. The epochs are encoded into the smr map_revision. + Smr *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=smr" json:"smr,omitempty"` + // seen_timestamp_nanos contains the time in nanoseconds where this particular + // signed map root was retrieved and processed. The actual timestamp of the + // smr returned by the server is contained in above smr field. + SeenTimestampNanos int64 `protobuf:"varint,2,opt,name=seen_timestamp_nanos,json=seenTimestampNanos" json:"seen_timestamp_nanos,omitempty"` + // isValid signals if all verification steps for the requested epoch passed + // or not. + IsValid bool `protobuf:"varint,3,opt,name=isValid" json:"isValid,omitempty"` + // invalidMapSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + InvalidMapSigProof *trillian.SignedMapRoot `protobuf:"bytes,4,opt,name=invalidMapSigProof" json:"invalidMapSigProof,omitempty"` + // invalidLogSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + InvalidLogSigProof *trillian.SignedLogRoot `protobuf:"bytes,5,opt,name=invalidLogSigProof" json:"invalidLogSigProof,omitempty"` + // invalidMutation contains data to reproduce that there was an invalid + // mutation from epoch e to epoch e+1 + InvalidMutation *InvalidMutation `protobuf:"bytes,6,opt,name=invalidMutation" json:"invalidMutation,omitempty"` + // NotMatchingMapRoot contains all data to reproduce that the set of mutations + // does not produce observed new map root. + NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,7,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` +} + +func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } +func (m *GetMonitoringResponse) String() string { return proto.CompactTextString(m) } +func (*GetMonitoringResponse) ProtoMessage() {} +func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { + if m != nil { + return m.Smr + } + return nil +} + +func (m *GetMonitoringResponse) GetSeenTimestampNanos() int64 { + if m != nil { + return m.SeenTimestampNanos + } + return 0 +} + +func (m *GetMonitoringResponse) GetIsValid() bool { + if m != nil { + return m.IsValid + } + return false +} + +func (m *GetMonitoringResponse) GetInvalidMapSigProof() *trillian.SignedMapRoot { + if m != nil { + return m.InvalidMapSigProof + } + return nil +} + +func (m *GetMonitoringResponse) GetInvalidLogSigProof() *trillian.SignedLogRoot { + if m != nil { + return m.InvalidLogSigProof + } + return nil +} + +func (m *GetMonitoringResponse) GetInvalidMutation() *InvalidMutation { + if m != nil { + return m.InvalidMutation + } + return nil +} + +func (m *GetMonitoringResponse) GetNotMatchingMapRoot() *NotMatchingMapRootProof { + if m != nil { + return m.NotMatchingMapRoot + } + return nil +} + +func init() { + proto.RegisterType((*GetMonitoringRequest)(nil), "monitor.v1.types.GetMonitoringRequest") + proto.RegisterType((*InvalidMutation)(nil), "monitor.v1.types.InvalidMutation") + proto.RegisterType((*NotMatchingMapRootProof)(nil), "monitor.v1.types.NotMatchingMapRootProof") + proto.RegisterType((*GetMonitoringResponse)(nil), "monitor.v1.types.GetMonitoringResponse") +} + +func init() { proto.RegisterFile("monitor_v1_types.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 437 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xc1, 0x6e, 0x13, 0x31, + 0x10, 0x86, 0x95, 0x2e, 0x6d, 0x82, 0x39, 0x14, 0x59, 0x81, 0xae, 0x72, 0x0a, 0x39, 0x35, 0x12, + 0xda, 0x92, 0x22, 0xc4, 0x23, 0x54, 0x15, 0xd9, 0x0a, 0xb9, 0x08, 0x89, 0xd3, 0xca, 0x4d, 0x1c, + 0x77, 0x24, 0xef, 0x8c, 0x59, 0x4f, 0x52, 0x71, 0xe2, 0xd1, 0xb8, 0xf2, 0x58, 0xc8, 0xbb, 0x9b, + 0xd0, 0xa6, 0x81, 0xf4, 0x66, 0xcf, 0xcc, 0xf7, 0xfb, 0xf7, 0x78, 0x2c, 0x5e, 0x97, 0x84, 0xc0, + 0x54, 0x15, 0xab, 0x49, 0xc1, 0x3f, 0xbc, 0x09, 0x99, 0xaf, 0x88, 0x49, 0xbe, 0x6c, 0xe3, 0xd9, + 0x6a, 0x92, 0xd5, 0xf1, 0xc1, 0xd8, 0x02, 0xdf, 0x2e, 0x6f, 0xb2, 0x19, 0x95, 0x67, 0x96, 0xc8, + 0x3a, 0x73, 0xc6, 0x15, 0x38, 0x07, 0x1a, 0x37, 0x8b, 0x06, 0x1e, 0x4c, 0x9e, 0x50, 0x5a, 0x94, + 0xda, 0x17, 0xda, 0x43, 0x83, 0x8c, 0xde, 0x8a, 0xfe, 0x85, 0xe1, 0xbc, 0x39, 0x14, 0xd0, 0x2a, + 0xf3, 0x7d, 0x69, 0x02, 0xcb, 0xbe, 0x38, 0x0c, 0xac, 0x2b, 0x4e, 0x3b, 0xc3, 0xce, 0x69, 0xa2, + 0x9a, 0xcd, 0xe8, 0xa7, 0x38, 0xbe, 0xc4, 0x95, 0x76, 0x30, 0xcf, 0x97, 0xac, 0x19, 0x08, 0xe5, + 0x07, 0xd1, 0x23, 0x37, 0x2f, 0x9c, 0xd1, 0x8b, 0xba, 0xf6, 0xc5, 0xf9, 0x20, 0xdb, 0xd8, 0xca, + 0xb5, 0x9f, 0x1a, 0xbd, 0xb8, 0xc4, 0x99, 0x5b, 0x06, 0x20, 0x54, 0x5d, 0x72, 0xf3, 0x18, 0x89, + 0x18, 0x9a, 0xbb, 0x06, 0x3b, 0xd8, 0x8f, 0xa1, 0xb9, 0x8b, 0x91, 0xd1, 0xaf, 0x8e, 0x38, 0xb9, + 0x22, 0xce, 0x35, 0xcf, 0x6e, 0x01, 0x6d, 0xae, 0xbd, 0x22, 0xe2, 0xcf, 0x15, 0xd1, 0x42, 0x9e, + 0x8b, 0x5e, 0xbc, 0x5b, 0x45, 0xc4, 0xad, 0x93, 0x93, 0xbf, 0x92, 0xd7, 0x60, 0xd1, 0xcc, 0xdb, + 0x7a, 0xd5, 0x2d, 0x9b, 0x85, 0xfc, 0x28, 0x9e, 0xaf, 0xdd, 0x87, 0xf4, 0x60, 0x98, 0xec, 0xf1, + 0xd1, 0x6b, 0xed, 0x87, 0x08, 0xae, 0xfd, 0x87, 0x34, 0xd9, 0x0f, 0xb6, 0x17, 0x08, 0xa3, 0xdf, + 0x89, 0x78, 0xb5, 0xd5, 0xf1, 0xe0, 0x09, 0x83, 0x91, 0x63, 0x91, 0x84, 0xb2, 0xda, 0x67, 0x3d, + 0xd6, 0xc8, 0x77, 0xa2, 0x1f, 0x8c, 0xc1, 0x82, 0xa1, 0x34, 0x81, 0x75, 0xe9, 0x0b, 0xd4, 0x48, + 0xa1, 0xee, 0x64, 0xa2, 0x64, 0xcc, 0x7d, 0x59, 0xa7, 0xae, 0x62, 0x46, 0xa6, 0xa2, 0x0b, 0xe1, + 0x6b, 0x7c, 0xb9, 0x34, 0x19, 0x76, 0x4e, 0x7b, 0x6a, 0xbd, 0x95, 0x17, 0x42, 0x42, 0xfb, 0xa6, + 0xda, 0x5f, 0x83, 0xad, 0x9b, 0x99, 0x3e, 0xfb, 0xbf, 0x8b, 0x1d, 0xc8, 0x3d, 0xa1, 0x29, 0xd9, + 0x8d, 0xd0, 0xe1, 0x6e, 0xa1, 0x29, 0xd9, 0x07, 0x42, 0xf7, 0x10, 0xf9, 0x49, 0x1c, 0xc3, 0xc3, + 0x29, 0x4b, 0x8f, 0x6a, 0x95, 0x37, 0xd9, 0xf6, 0xef, 0xc8, 0xb6, 0xc6, 0x51, 0x6d, 0x93, 0xf2, + 0x9b, 0x90, 0xf8, 0x68, 0x60, 0xd2, 0x6e, 0xad, 0x37, 0x7e, 0xac, 0xf7, 0x8f, 0xe1, 0x52, 0x3b, + 0x44, 0x6e, 0x8e, 0xea, 0x2f, 0xf4, 0xfe, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xda, 0xc5, + 0xc2, 0xcc, 0x03, 0x00, 0x00, +} diff --git a/core/proto/monitor_v1_types/monitor_v1_types.proto b/core/proto/monitor_v1_types/monitor_v1_types.proto new file mode 100644 index 000000000..16e0e4bbe --- /dev/null +++ b/core/proto/monitor_v1_types/monitor_v1_types.proto @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// Key Transparency Monitor Service +// +package monitor.v1.types; + +import "github.com/google/trillian/trillian.proto"; +import "github.com/google/trillian/trillian_map_api.proto"; + +// GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. +message GetMonitoringRequest { + // start specifies the start epoch number from which monitoring results will + // be returned (ranging from [start, latestObserved] and starting at 1). + int64 start = 1; +} + +// InvalidMutation includes all information to reproduce that there was an +// invalid mutation from epoch e to e+1. +message InvalidMutation { + // old_leaf is the inclusion proof to the leaf at epoch e. + trillian.MapLeafInclusion old_leaf = 1; + // new_leaf is the inclusion proof to the leaf at epoch e+1. + trillian.MapLeafInclusion new_leaf = 2; +} + +// NotMatchingMapRootProof contains all data necessary to reproduce that set of +// mutations does not produce new expected map root. +message NotMatchingMapRootProof { + // map_root contains the map root hash the monitor observed. + trillian.SignedMapRoot map_root = 1; + // old_leafs is a list of inclusion proofs for the leafs in epoch e. + repeated trillian.MapLeafInclusion old_leafs = 2; + // new_leafs is a list of inclusion proofs for changed leafs (from epoch e + // to epoch e+1). Hashing these produces a different hash than root hash in + // above's map_root. + repeated trillian.MapLeafInclusion new_leafs = 3; +} + +message GetMonitoringResponse { + // smr contains the map root for the sparse Merkle Tree signed with the + // monitor's key on success. If the checks were not successful the + // smr will be empty. The epochs are encoded into the smr map_revision. + trillian.SignedMapRoot smr = 1; + + // seen_timestamp_nanos contains the time in nanoseconds where this particular + // signed map root was retrieved and processed. The actual timestamp of the + // smr returned by the server is contained in above smr field. + int64 seen_timestamp_nanos = 2; + + // + // The following fields provide more information about each failure in this + // response, if any. + // + + // isValid signals if all verification steps for the requested epoch passed + // or not. + bool isValid = 3; + // invalidMapSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + trillian.SignedMapRoot invalidMapSigProof = 4; + // invalidLogSigProof contains the signed map root received by the + // key-transparency server, if and only if the key-server's signature was + // invalid. + trillian.SignedLogRoot invalidLogSigProof = 5; + // invalidMutation contains data to reproduce that there was an invalid + // mutation from epoch e to epoch e+1 + InvalidMutation invalidMutation = 6; + // NotMatchingMapRoot contains all data to reproduce that the set of mutations + // does not produce observed new map root. + NotMatchingMapRootProof notMatchingMapRoot = 7; +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 15fe7d836..e4ef3308a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -162,7 +162,7 @@ services: - --poll-period=5s - --tls-key=genfiles/server.key - --tls-cert=genfiles/server.crt - - --sign-key=/kt/p256-monitor_sign-key.pem + - --sign-key=/kt/monitor_sign-key.pem - --password=towel # TODO(ismail): this needs to be the public-key returned by the createTree operation: - --map-key=trillian/testdata/map-rpc-server.pubkey.pem diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 6f9ab4f46..abd29816e 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -34,8 +34,11 @@ import ( tcrypto "github.com/google/trillian/crypto" + cmon "github.com/google/keytransparency/core/monitor" + mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" ) @@ -58,13 +61,13 @@ type Server struct { mapPubKey crypto.PublicKey logPubKey crypto.PublicKey - signer tcrypto.Signer - proccessedSMRs []*ktpb.GetMonitoringResponse + signer *tcrypto.Signer + proccessedSMRs []*mopb.GetMonitoringResponse } // New creates a new instance of the monitor server. func New(cli mupb.MutationServiceClient, - signer tcrypto.Signer, + signer *tcrypto.Signer, logPubKey, mapPubKey crypto.PublicKey, poll time.Duration) *Server { return &Server{ @@ -73,7 +76,7 @@ func New(cli mupb.MutationServiceClient, logPubKey: logPubKey, mapPubKey: mapPubKey, signer: signer, - proccessedSMRs: make([]*ktpb.GetMonitoringResponse, 256), + proccessedSMRs: make([]*mopb.GetMonitoringResponse, 256), } } @@ -98,7 +101,7 @@ func (s *Server) StartPolling() error { // the monitor could not reconstruct the map root given the set of mutations // from the previous to the current epoch it won't sign the map root and // additional data will be provided to reproduce the failure. -func (s *Server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { +func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { if len(s.proccessedSMRs) > 0 { return s.proccessedSMRs[len(s.proccessedSMRs)-1], nil } @@ -112,7 +115,7 @@ func (s *Server) GetSignedMapRoot(ctx context.Context, in *ktpb.GetMonitoringReq // If the monitor could not reconstruct the map root given the set of // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. -func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *ktpb.GetMonitoringRequest) (*ktpb.GetMonitoringResponse, error) { +func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { // TODO(ismail): implement by revision API return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") } @@ -143,26 +146,26 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] return nil, err } respSmr := resp.GetSmr() - var monitorResp *ktpb.GetMonitoringResponse - switch err := verifyResponse(s.logPubKey, s.mapPubKey, resp, mutations); err { + var monitorResp *mopb.GetMonitoringResponse + switch err := cmon.VerifyResponse(s.logPubKey, s.mapPubKey, resp, mutations); err { // TODO(ismail): return proper data for failure cases: - case ErrInvalidMutation: + case cmon.ErrInvalidMutation: glog.Errorf("TODO: handle this ErrInvalidMutation properly") - case ErrInvalidMapSignature: + case cmon.ErrInvalidMapSignature: glog.Infof("Signature on map did not verify: %v", err) - monitorResp = &ktpb.GetMonitoringResponse{ + monitorResp = &mopb.GetMonitoringResponse{ IsValid: false, SeenTimestampNanos: seen, InvalidMapSigProof: respSmr, } - case ErrInvalidLogSignature: + case cmon.ErrInvalidLogSignature: glog.Infof("Signature on log did not verify: %v", err) - monitorResp = &ktpb.GetMonitoringResponse{ + monitorResp = &mopb.GetMonitoringResponse{ IsValid: false, SeenTimestampNanos: seen, InvalidLogSigProof: resp.GetLogRoot(), } - case ErrNotMatchingRoot: + case cmon.ErrNotMatchingRoot: glog.Errorf("TODO: handle this ErrNotMatchingRoot properly") case nil: // Sign map root with monitor key: @@ -172,7 +175,7 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] } // update signature on smr: respSmr.Signature = sig - monitorResp = &ktpb.GetMonitoringResponse{ + monitorResp = &mopb.GetMonitoringResponse{ Smr: respSmr, IsValid: true, SeenTimestampNanos: seen, diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go index 86455b453..66c84e6aa 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go @@ -19,7 +19,7 @@ package monitor_v1_service import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" -import keytransparency_v1_types "github.com/google/keytransparency/core/proto/keytransparency_v1_types" +import monitor_v1_types "github.com/google/keytransparency/core/proto/monitor_v1_types" import _ "google.golang.org/genproto/googleapis/api/annotations" import ( @@ -57,7 +57,7 @@ type MonitorServiceClient interface { // the monitor could not reconstruct the map root given the set of mutations // from the previous to the current epoch it won't sign the map root and // additional data will be provided to reproduce the failure. - GetSignedMapRoot(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRoot(ctx context.Context, in *monitor_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*monitor_v1_types.GetMonitoringResponse, error) // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns // the monitor's result for a specific map revision. // @@ -65,7 +65,7 @@ type MonitorServiceClient interface { // If the monitor could not reconstruct the map root given the set of // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. - GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootByRevision(ctx context.Context, in *monitor_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*monitor_v1_types.GetMonitoringResponse, error) } type monitorServiceClient struct { @@ -76,8 +76,8 @@ func NewMonitorServiceClient(cc *grpc.ClientConn) MonitorServiceClient { return &monitorServiceClient{cc} } -func (c *monitorServiceClient) GetSignedMapRoot(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) { - out := new(keytransparency_v1_types.GetMonitoringResponse) +func (c *monitorServiceClient) GetSignedMapRoot(ctx context.Context, in *monitor_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*monitor_v1_types.GetMonitoringResponse, error) { + out := new(monitor_v1_types.GetMonitoringResponse) err := grpc.Invoke(ctx, "/monitor.v1.service.MonitorService/GetSignedMapRoot", in, out, c.cc, opts...) if err != nil { return nil, err @@ -85,8 +85,8 @@ func (c *monitorServiceClient) GetSignedMapRoot(ctx context.Context, in *keytran return out, nil } -func (c *monitorServiceClient) GetSignedMapRootByRevision(ctx context.Context, in *keytransparency_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*keytransparency_v1_types.GetMonitoringResponse, error) { - out := new(keytransparency_v1_types.GetMonitoringResponse) +func (c *monitorServiceClient) GetSignedMapRootByRevision(ctx context.Context, in *monitor_v1_types.GetMonitoringRequest, opts ...grpc.CallOption) (*monitor_v1_types.GetMonitoringResponse, error) { + out := new(monitor_v1_types.GetMonitoringResponse) err := grpc.Invoke(ctx, "/monitor.v1.service.MonitorService/GetSignedMapRootByRevision", in, out, c.cc, opts...) if err != nil { return nil, err @@ -105,7 +105,7 @@ type MonitorServiceServer interface { // the monitor could not reconstruct the map root given the set of mutations // from the previous to the current epoch it won't sign the map root and // additional data will be provided to reproduce the failure. - GetSignedMapRoot(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRoot(context.Context, *monitor_v1_types.GetMonitoringRequest) (*monitor_v1_types.GetMonitoringResponse, error) // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns // the monitor's result for a specific map revision. // @@ -113,7 +113,7 @@ type MonitorServiceServer interface { // If the monitor could not reconstruct the map root given the set of // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. - GetSignedMapRootByRevision(context.Context, *keytransparency_v1_types.GetMonitoringRequest) (*keytransparency_v1_types.GetMonitoringResponse, error) + GetSignedMapRootByRevision(context.Context, *monitor_v1_types.GetMonitoringRequest) (*monitor_v1_types.GetMonitoringResponse, error) } func RegisterMonitorServiceServer(s *grpc.Server, srv MonitorServiceServer) { @@ -121,7 +121,7 @@ func RegisterMonitorServiceServer(s *grpc.Server, srv MonitorServiceServer) { } func _MonitorService_GetSignedMapRoot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(keytransparency_v1_types.GetMonitoringRequest) + in := new(monitor_v1_types.GetMonitoringRequest) if err := dec(in); err != nil { return nil, err } @@ -133,13 +133,13 @@ func _MonitorService_GetSignedMapRoot_Handler(srv interface{}, ctx context.Conte FullMethod: "/monitor.v1.service.MonitorService/GetSignedMapRoot", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MonitorServiceServer).GetSignedMapRoot(ctx, req.(*keytransparency_v1_types.GetMonitoringRequest)) + return srv.(MonitorServiceServer).GetSignedMapRoot(ctx, req.(*monitor_v1_types.GetMonitoringRequest)) } return interceptor(ctx, in, info, handler) } func _MonitorService_GetSignedMapRootByRevision_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(keytransparency_v1_types.GetMonitoringRequest) + in := new(monitor_v1_types.GetMonitoringRequest) if err := dec(in); err != nil { return nil, err } @@ -151,7 +151,7 @@ func _MonitorService_GetSignedMapRootByRevision_Handler(srv interface{}, ctx con FullMethod: "/monitor.v1.service.MonitorService/GetSignedMapRootByRevision", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MonitorServiceServer).GetSignedMapRootByRevision(ctx, req.(*keytransparency_v1_types.GetMonitoringRequest)) + return srv.(MonitorServiceServer).GetSignedMapRootByRevision(ctx, req.(*monitor_v1_types.GetMonitoringRequest)) } return interceptor(ctx, in, info, handler) } @@ -176,22 +176,22 @@ var _MonitorService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("monitor_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 264 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x90, 0x3d, 0x4e, 0xc3, 0x40, - 0x10, 0x46, 0x95, 0x14, 0x14, 0x2e, 0x10, 0x5a, 0xf1, 0x27, 0x2b, 0x34, 0x1c, 0x60, 0x47, 0x86, - 0x8e, 0x92, 0x26, 0x55, 0x1a, 0xe7, 0x00, 0xd1, 0xc6, 0x19, 0x99, 0x15, 0xf1, 0xcc, 0xb2, 0x33, - 0xb1, 0x64, 0x21, 0x1a, 0x6e, 0x80, 0x68, 0xb9, 0x0d, 0x47, 0xe0, 0x0a, 0x1c, 0x04, 0xc5, 0xde, - 0x06, 0x4b, 0x48, 0x34, 0xa9, 0xdf, 0xea, 0x7b, 0x6f, 0x27, 0xbb, 0x6c, 0x98, 0xbc, 0x72, 0x5c, - 0xb5, 0xc5, 0x4a, 0x30, 0xb6, 0xbe, 0x42, 0x1b, 0x22, 0x2b, 0x1b, 0x93, 0x88, 0x6d, 0x0b, 0x9b, - 0x48, 0xbe, 0xa9, 0xbd, 0x3e, 0xec, 0xd6, 0xb6, 0xe2, 0x06, 0x6a, 0xe6, 0x7a, 0x8b, 0xf0, 0x88, - 0x9d, 0x46, 0x47, 0x12, 0x5c, 0x44, 0xaa, 0x3a, 0xa8, 0x38, 0x22, 0xf4, 0x0b, 0x63, 0xb4, 0x57, - 0x68, 0x17, 0x50, 0xfe, 0x04, 0x83, 0x39, 0x9f, 0xa5, 0x69, 0x17, 0x3c, 0x38, 0x22, 0x56, 0xa7, - 0x9e, 0x29, 0xd1, 0x9b, 0xcf, 0x69, 0x76, 0xbc, 0x18, 0xd2, 0x96, 0x43, 0x96, 0x79, 0x9b, 0x64, - 0x27, 0x73, 0xd4, 0xa5, 0xaf, 0x09, 0x37, 0x0b, 0x17, 0x4a, 0x66, 0x35, 0xd6, 0x8e, 0x34, 0xfb, - 0x8f, 0x0c, 0x9a, 0x39, 0x6a, 0x5a, 0xf0, 0x54, 0x97, 0xf8, 0xb4, 0x43, 0xd1, 0x1c, 0xfe, 0xfd, - 0x5e, 0x02, 0x93, 0xe0, 0xf5, 0xec, 0xf5, 0xeb, 0xfb, 0x7d, 0x7a, 0x6e, 0x4e, 0xa1, 0x2d, 0xa0, - 0x71, 0x01, 0x22, 0xb3, 0xca, 0xdd, 0xd6, 0x29, 0x8a, 0x9a, 0x8f, 0x49, 0x96, 0x8f, 0x9b, 0xee, - 0xbb, 0x12, 0x5b, 0x2f, 0x9e, 0xe9, 0xf0, 0x75, 0x57, 0x7d, 0xdd, 0x85, 0x39, 0xfb, 0x55, 0x07, - 0xcf, 0xa2, 0x2e, 0xea, 0xcb, 0xfa, 0xa8, 0x3f, 0xe6, 0xed, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xf1, 0x14, 0x6f, 0x52, 0x00, 0x02, 0x00, 0x00, + // 261 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x90, 0xaf, 0x4e, 0x03, 0x41, + 0x10, 0xc6, 0xd3, 0x0a, 0xc4, 0x09, 0x42, 0x36, 0xfc, 0xcb, 0xa5, 0x18, 0x04, 0xb8, 0x9b, 0x14, + 0x1c, 0x12, 0x53, 0x55, 0x73, 0xc5, 0x37, 0xdb, 0x63, 0xb2, 0x6c, 0xe8, 0xcd, 0x2c, 0x3b, 0xd3, + 0x4d, 0x2e, 0x04, 0x01, 0x1a, 0xc7, 0x23, 0xf0, 0x48, 0xbc, 0x02, 0x0f, 0x42, 0x72, 0xb7, 0xa2, + 0x80, 0xc0, 0x60, 0xe7, 0x9b, 0xef, 0x37, 0xbf, 0x4c, 0x71, 0xdc, 0x32, 0x79, 0xe5, 0xb8, 0x4c, + 0xd3, 0xa5, 0x60, 0x4c, 0xbe, 0xc1, 0x2a, 0x44, 0x56, 0x36, 0x26, 0x27, 0x55, 0x9a, 0x56, 0x39, + 0x29, 0x6f, 0x9c, 0xd7, 0xbb, 0xcd, 0xaa, 0x6a, 0xb8, 0x05, 0xc7, 0xec, 0xd6, 0x08, 0xf7, 0xd8, + 0x69, 0xb4, 0x24, 0xc1, 0x46, 0xa4, 0xa6, 0x83, 0x86, 0x23, 0x42, 0x4f, 0x80, 0x2d, 0xb4, 0x76, + 0x01, 0xe5, 0xd7, 0x60, 0xb8, 0x54, 0x4e, 0x32, 0xca, 0x06, 0x0f, 0x96, 0x88, 0xd5, 0xaa, 0x67, + 0xca, 0xe9, 0xc5, 0xfb, 0xb8, 0xd8, 0x9d, 0x0f, 0xc5, 0xc5, 0xa0, 0x61, 0x9e, 0x47, 0xc5, 0xde, + 0x0c, 0x75, 0xe1, 0x1d, 0xe1, 0xed, 0xdc, 0x86, 0x9a, 0x59, 0xcd, 0x59, 0xb5, 0x25, 0x3c, 0xe0, + 0x67, 0xa8, 0xb9, 0xe9, 0xc9, 0xd5, 0xf8, 0xb0, 0x41, 0xd1, 0xf2, 0xfc, 0xcf, 0x3d, 0x09, 0x4c, + 0x82, 0xa7, 0x93, 0x97, 0x8f, 0xcf, 0xb7, 0xf1, 0xa1, 0xd9, 0x87, 0x34, 0x85, 0xd6, 0x06, 0x88, + 0xcc, 0x2a, 0x57, 0x6b, 0xab, 0x28, 0x6a, 0x5e, 0x47, 0x45, 0xf9, 0xd3, 0xe1, 0xba, 0xab, 0x31, + 0x79, 0xf1, 0x4c, 0xff, 0x6f, 0x73, 0xd2, 0xdb, 0x1c, 0x99, 0x83, 0x6f, 0x36, 0xf0, 0x28, 0x6a, + 0xa3, 0x3e, 0xad, 0x76, 0xfa, 0x67, 0x5d, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x85, 0xab, + 0x1e, 0xd0, 0x01, 0x00, 0x00, } diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go index 050d81507..26786982a 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go @@ -14,7 +14,7 @@ import ( "net/http" "github.com/golang/protobuf/proto" - "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/google/keytransparency/core/proto/monitor_v1_types" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" "golang.org/x/net/context" @@ -33,7 +33,7 @@ var ( ) func request_MonitorService_GetSignedMapRoot_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq keytransparency_v1_types.GetMonitoringRequest + var protoReq monitor_v1_types.GetMonitoringRequest var metadata runtime.ServerMetadata if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_MonitorService_GetSignedMapRoot_0); err != nil { @@ -46,7 +46,7 @@ func request_MonitorService_GetSignedMapRoot_0(ctx context.Context, marshaler ru } func request_MonitorService_GetSignedMapRootByRevision_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq keytransparency_v1_types.GetMonitoringRequest + var protoReq monitor_v1_types.GetMonitoringRequest var metadata runtime.ServerMetadata var ( diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.proto b/impl/proto/monitor_v1_service/monitor_v1_service.proto index 741faefed..509afe90a 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.proto +++ b/impl/proto/monitor_v1_service/monitor_v1_service.proto @@ -20,7 +20,7 @@ syntax = "proto3"; // monitor results queried using the mutations API. package monitor.v1.service; -import "github.com/google/keytransparency/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto"; +import "github.com/google/keytransparency/core/proto/monitor_v1_types/monitor_v1_types.proto"; import "google/api/annotations.proto"; // The Monitor Service API allows clients to query the monitors observed and @@ -28,7 +28,8 @@ import "google/api/annotations.proto"; // // - Signed Map Roots can be collected using the GetSignedMapRoot APIs. // - Monitor resources are named: -// /v1/map/roots/* /v1/map/roots:latest and v1/map/roots:stream. +// - /v1/map/roots/* +// - /v1/map/roots:latest // service MonitorService { // GetSignedMapRoot returns the latest valid signed map root the monitor @@ -39,8 +40,8 @@ service MonitorService { // the monitor could not reconstruct the map root given the set of mutations // from the previous to the current epoch it won't sign the map root and // additional data will be provided to reproduce the failure. - rpc GetSignedMapRoot(keytransparency.v1.types.GetMonitoringRequest) - returns (keytransparency.v1.types.GetMonitoringResponse) { + rpc GetSignedMapRoot(monitor.v1.types.GetMonitoringRequest) + returns (monitor.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots:latest" }; } @@ -51,8 +52,8 @@ service MonitorService { // If the monitor could not reconstruct the map root given the set of // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. - rpc GetSignedMapRootByRevision(keytransparency.v1.types.GetMonitoringRequest) - returns(keytransparency.v1.types.GetMonitoringResponse) { + rpc GetSignedMapRootByRevision(monitor.v1.types.GetMonitoringRequest) + returns(monitor.v1.types.GetMonitoringResponse) { option (google.api.http) = { get: "/v1/map/roots/{start}" }; } } diff --git a/scripts/gen_monitor_keys.sh b/scripts/gen_monitor_keys.sh index f79f6721e..09a83ef66 100644 --- a/scripts/gen_monitor_keys.sh +++ b/scripts/gen_monitor_keys.sh @@ -39,10 +39,10 @@ DEFAULT_PWD=towel # Generate monitor signing key-pair: if ((INTERACTIVE == 1)); then # Prompts for password: - openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -out p256-monitor_sign-key.pem + openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -out monitor_sign-key.pem else - openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -passout pass:$DEFAULT_PWD -out p256-monitor_sign-key.pem + openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -passout pass:$DEFAULT_PWD -out monitor_sign-key.pem fi -chmod 600 p256-monitor_sign-key.pem +chmod 600 monitor_sign-key.pem diff --git a/scripts/prepare_server.sh b/scripts/prepare_server.sh index d7a2a745f..e1e4b2ace 100755 --- a/scripts/prepare_server.sh +++ b/scripts/prepare_server.sh @@ -23,6 +23,7 @@ INTERACTIVE=1 FRONTEND=1 FRONTENDNUM=0 BACKEND=1 +MONITOR=1 # 1 means SQLite, 2 means MySQL DSN="" IP1="127.0.0.1" @@ -131,6 +132,10 @@ if ((FRONTEND == 1)); then ./scripts/gen_server_keys.sh -d "${CERTDOMAIN}" -a "${CERTIP}" -s "${SAN_DNS}" fi +if ((MONITOR == 1)); then + ./scripts/gen_monitor_keys.sh +fi + # Generating .env file ENV="SIGN_PERIOD=5" From 1bcaa6777b1286f7ad7d91d21b1ef4a504ded334 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 14:54:29 +0100 Subject: [PATCH 06/46] * Change mutator interface to accept SignedKV objects directly * Remove replacer which isn't used anywhere --- core/mutator/replace/replace.go | 34 --------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 core/mutator/replace/replace.go diff --git a/core/mutator/replace/replace.go b/core/mutator/replace/replace.go deleted file mode 100644 index 75c9f1d71..000000000 --- a/core/mutator/replace/replace.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package replace implements a simple replacement strategy as a mapper. -package replace - -// Replace defines mutations to simply replace the current map value with the contents of the mutation. -type Replace struct{} - -// New creates a rew replacement mutator. -func New() *Replace { - return &Replace{} -} - -// CheckMutation verifies that this is a valid mutation for this item. -func (r *Replace) CheckMutation(value, mutation []byte) error { - return nil -} - -// Mutate applies mutation to value. -func (r *Replace) Mutate(value, mutation []byte) ([]byte, error) { - return mutation, nil -} From fa1eb0b0c723bd8ac49f69472289a36a2fe67e2f Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 16:55:28 +0100 Subject: [PATCH 07/46] Change mutator interface to accept proto.Message --- .../grpcc/grpc_client.go | 8 ++- core/keyserver/keyserver.go | 8 ++- core/mutator/entry/entry.go | 42 ++++++++++----- core/mutator/entry/entry_test.go | 53 +++++++++---------- core/mutator/mutator.go | 4 +- core/signer/signer.go | 10 ++-- 6 files changed, 77 insertions(+), 48 deletions(-) diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 2eb3f26af..1c3bd8131 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -37,6 +37,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" + "github.com/golang/protobuf/proto" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" "github.com/google/trillian" @@ -200,8 +201,11 @@ func (c *Client) Update(ctx context.Context, userID, appID string, profileData [ if err != nil { return nil, fmt.Errorf("CreateUpdateEntryRequest: %v", err) } - - if _, err := c.mutator.Mutate(getResp.GetLeafProof().GetLeaf().GetLeafValue(), req.GetEntryUpdate().GetUpdate()); err != nil { + var oldLeaf *tpb.Entry + if err := proto.Unmarshal(getResp.GetLeafProof().GetLeaf().GetLeafValue(), oldLeaf); err != nil { + return nil, fmt.Errorf("proto.Unmarshal: %v", err) + } + if _, err := c.mutator.Mutate(oldLeaf, req.GetEntryUpdate().GetUpdate()); err != nil { return nil, fmt.Errorf("Mutate: %v", err) } diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index a5ec233c4..983f807e7 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -291,8 +291,12 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* // - Hash of current data matches the expectation in the mutation. // The very first mutation will have resp.LeafProof.LeafData=nil. - if _, err := s.mutator.Mutate(resp.LeafProof.Leaf.LeafValue, - in.GetEntryUpdate().GetUpdate()); err == mutator.ErrReplay { + oldEntry := &tpb.Entry{} + if err := proto.Unmarshal(resp.GetLeafProof().GetLeaf().GetLeafValue(), oldEntry); err != nil { + glog.Errorf("proto.Unmarshal(%v, _): %v", resp.GetLeafProof().GetLeaf().GetLeafValue(), err) + return nil, grpc.Errorf(codes.InvalidArgument, "invalid previous leaf value") + } + if _, err := s.mutator.Mutate(oldEntry, in.GetEntryUpdate().GetUpdate()); err == mutator.ErrReplay { glog.Warningf("Discarding request due to replay") // Return the response. The client should handle the replay case // by comparing the returned response with the request. Check diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index 6a1222f8d..e064a5340 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -17,6 +17,7 @@ package entry import ( "bytes" + "fmt" "github.com/google/keytransparency/core/crypto/signatures" "github.com/google/keytransparency/core/crypto/signatures/factory" @@ -41,20 +42,39 @@ func New() *Entry { // Mutate verifies that this is a valid mutation for this item and applies // mutation to value. -func (*Entry) Mutate(oldValue []byte, update *tpb.SignedKV) ([]byte, error) { +func (*Entry) Mutate(oldValueM, updateM proto.Message) ([]byte, error) { // Ensure that the mutation size is within bounds. - if proto.Size(update) > mutator.MaxMutationSize { - glog.Warningf("mutation (%v bytes) is larger than the maximum accepted size (%v bytes).", proto.Size(update), mutator.MaxMutationSize) + if proto.Size(updateM) > mutator.MaxMutationSize { + glog.Warningf("mutation (%v bytes) is larger than the maximum accepted size (%v bytes).", proto.Size(updateM), mutator.MaxMutationSize) return nil, mutator.ErrSize } + update, ok := updateM.(*tpb.SignedKV) + if !ok { + glog.Warning("received proto.Message is not of type *tpb.SignedKV.") + return nil, fmt.Errorf("updateM.(*tpb.SignedKV): _, %v", ok) + } + + oldEntry, ok := oldValueM.(*tpb.Entry) + if !ok { + glog.Warning("received proto.Message is not of type *tpb.Entry.") + return nil, fmt.Errorf("oldValueM.(*tpb.Entry): _, %v", ok) + } + // Verify pointer to previous data. // The very first entry will have oldValue=nil, so its hash is the // ObjectHash value of nil. - prevEntryHash := objecthash.ObjectHash(oldValue) + prevEntryHash := objecthash.ObjectHash(oldEntry) if !bytes.Equal(prevEntryHash[:], update.Previous) { + var entryData []byte + if oldEntry != nil { + var err error + if entryData, err = proto.Marshal(oldEntry); err != nil { + return nil, fmt.Errorf("Marshal(%v)=%v", oldEntry, err) + } + } // Check if this mutation is a replay. - if bytes.Equal(oldValue, update.GetKeyValue().Value) { + if bytes.Equal(entryData, update.GetKeyValue().Value) { glog.Warningf("mutation is a replay of an old one") return nil, mutator.ErrReplay } @@ -76,7 +96,7 @@ func (*Entry) Mutate(oldValue []byte, update *tpb.SignedKV) ([]byte, error) { return nil, mutator.ErrMissingKey } - if err := verifyKeys(oldValue, kv, update, entry); err != nil { + if err := verifyKeys(oldEntry, kv, update, entry); err != nil { return nil, err } @@ -89,26 +109,22 @@ func (*Entry) Mutate(oldValue []byte, update *tpb.SignedKV) ([]byte, error) { // 2. The first mutation should contain at least one signature with a key in // in that mutation. // 3. Signatures with no matching keys are simply ignored. -func verifyKeys(oldValue []byte, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { - prevEntry := new(tpb.Entry) +func verifyKeys(prevEntry *tpb.Entry, data interface{}, update *tpb.SignedKV, entry *tpb.Entry) error { var verifiers map[string]signatures.Verifier var err error - if oldValue == nil { + if prevEntry == nil { verifiers, err = verifiersFromKeys(entry.GetAuthorizedKeys()) if err != nil { return err } } else { - if err = proto.Unmarshal(oldValue, prevEntry); err != nil { - return err - } verifiers, err = verifiersFromKeys(prevEntry.GetAuthorizedKeys()) if err != nil { return err } } - if err = verifyAuthorizedKeys(data, verifiers, update.Signatures); err != nil { + if err := verifyAuthorizedKeys(data, verifiers, update.GetSignatures()); err != nil { return err } return nil diff --git a/core/mutator/entry/entry_test.go b/core/mutator/entry/entry_test.go index 9fdb4c49a..190757839 100644 --- a/core/mutator/entry/entry_test.go +++ b/core/mutator/entry/entry_test.go @@ -57,7 +57,7 @@ LOA+tLe/MbwZ69SRdG6Rx92f9tbC6dz7UVsyI7vIjS+961sELA6FeR91lA== -----END PUBLIC KEY-----` ) -func createEntry(commitment []byte, pkeys []string) ([]byte, error) { +func createEntry(commitment []byte, pkeys []string) (*tpb.Entry, error) { authKeys := make([]*tpb.PublicKey, len(pkeys)) for i, key := range pkeys { p, _ := pem.Decode([]byte(key)) @@ -71,18 +71,21 @@ func createEntry(commitment []byte, pkeys []string) ([]byte, error) { } } - entry := &tpb.Entry{ + return &tpb.Entry{ Commitment: commitment, AuthorizedKeys: authKeys, - } - entryData, err := proto.Marshal(entry) - if err != nil { - return nil, fmt.Errorf("Marshal(%v)=%v", entry, err) - } - return entryData, nil + }, nil } -func prepareMutation(key []byte, entryData []byte, previous []byte, signers []signatures.Signer) ([]byte, error) { +func prepareMutation(key []byte, newEntry *tpb.Entry, previous []byte, signers []signatures.Signer) (*tpb.SignedKV, error) { + var entryData []byte + if newEntry != nil { + var err error + entryData, err = proto.Marshal(newEntry) + if err != nil { + return nil, fmt.Errorf("Marshal(%v)=%v", newEntry, err) + } + } kv := &tpb.KeyValue{ Key: key, Value: entryData, @@ -98,16 +101,11 @@ func prepareMutation(key []byte, entryData []byte, previous []byte, signers []si sigs[signer.KeyID()] = sig } - skv := &tpb.SignedKV{ + return &tpb.SignedKV{ KeyValue: kv, Signatures: sigs, Previous: previous, - } - mutation, err := proto.Marshal(skv) - if err != nil { - return nil, fmt.Errorf("Marshal(%v)=%v", skv, err) - } - return mutation, nil + }, nil } func signersFromPEMs(t *testing.T, keys [][]byte) []signatures.Signer { @@ -159,13 +157,13 @@ func TestCheckMutation(t *testing.T) { signers3 := signersFromPEMs(t, [][]byte{[]byte(testPrivKey1), []byte(testPrivKey2)}) _, _, _ = missingKeyEntryData2, hashMissingKeyEntry1, signers2 - for _, tc := range []struct { - key []byte - oldValue []byte - entryData []byte - previous []byte - signers []signatures.Signer - err error + for i, tc := range []struct { + key []byte + oldEntry *tpb.Entry + newEntry *tpb.Entry + previous []byte + signers []signatures.Signer + err error }{ {key, entryData2, entryData2, hashEntry1[:], nil, mutator.ErrReplay}, // Replayed mutation {largeKey, entryData1, entryData2, hashEntry1[:], nil, mutator.ErrSize}, // Large mutation @@ -183,13 +181,14 @@ func TestCheckMutation(t *testing.T) { {key, entryData1, entryData2, hashEntry1[:], signers1, nil}, // Second mutation, missing current signature, should work } { // Prepare mutations. - mutation, err := prepareMutation(tc.key, tc.entryData, tc.previous, tc.signers) + mutation, err := prepareMutation(tc.key, tc.newEntry, tc.previous, tc.signers) if err != nil { - t.Fatalf("prepareMutation(%v, %v, %v)=%v", tc.key, tc.entryData, tc.previous, err) + t.Fatalf("prepareMutation(%v, %v, %v)=%v", tc.key, tc.newEntry, tc.previous, err) } - if _, got := New().Mutate(tc.oldValue, mutation); got != tc.err { - t.Errorf("Mutate(%v, %v)=%v, want %v", tc.oldValue, mutation, got, tc.err) + if _, got := New().Mutate(tc.oldEntry, mutation); got != tc.err { + t.Errorf("In %d: Mutate(%v, %v)=%v, want %v", i, tc.oldEntry, mutation, got, tc.err) + } } } diff --git a/core/mutator/mutator.go b/core/mutator/mutator.go index 4bfbb9896..3611b1405 100644 --- a/core/mutator/mutator.go +++ b/core/mutator/mutator.go @@ -20,6 +20,8 @@ package mutator import ( "errors" + "github.com/golang/protobuf/proto" + "github.com/google/keytransparency/core/transaction" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" @@ -49,7 +51,7 @@ var ( type Mutator interface { // Mutate verifies that this is a valid mutation for this item and // applies mutation to value. - Mutate(value []byte, mutation *tpb.SignedKV) ([]byte, error) + Mutate(value, mutation proto.Message) ([]byte, error) } // Mutation reads and writes mutations to the database. diff --git a/core/signer/signer.go b/core/signer/signer.go index 20575a051..4cd6e37dc 100644 --- a/core/signer/signer.go +++ b/core/signer/signer.go @@ -28,6 +28,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "golang.org/x/net/context" + "github.com/gogo/protobuf/proto" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian/util" ) @@ -200,10 +201,13 @@ func (s *Signer) applyMutations(mutations []*tpb.SignedKV, leaves []*trillian.Ma retMap := make(map[[32]byte]*trillian.MapLeaf) for _, m := range mutations { - index := m.GetKeyValue().Key - var oldValue []byte // If no map leaf was found, oldValue will be nil. + index := m.GetKeyValue().GetKey() + var oldValue *tpb.Entry // If no map leaf was found, oldValue will be nil. if leaf, ok := leafMap[toArray(index)]; ok { - oldValue = leaf.LeafValue + if err := proto.Unmarshal(leaf.GetLeafValue(), oldValue); err != nil { + glog.Warningf("proto.Unmarshal(%v, _): %v", leaf.GetLeafValue(), err) + continue // A bad mutation should not make the whole batch fail. + } } newValue, err := s.mutator.Mutate(oldValue, m) From d6eddf00956cde4b27160ffec89d15f9ffed613c Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 17:55:50 +0100 Subject: [PATCH 08/46] Use nil in Update/Mutate instead &tpb.Entry{} --- cmd/keytransparency-client/grpcc/grpc_client.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 1c3bd8131..835021016 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -201,9 +201,13 @@ func (c *Client) Update(ctx context.Context, userID, appID string, profileData [ if err != nil { return nil, fmt.Errorf("CreateUpdateEntryRequest: %v", err) } - var oldLeaf *tpb.Entry - if err := proto.Unmarshal(getResp.GetLeafProof().GetLeaf().GetLeafValue(), oldLeaf); err != nil { - return nil, fmt.Errorf("proto.Unmarshal: %v", err) + oldLeafB := getResp.GetLeafProof().GetLeaf().GetLeafValue() + var oldLeaf *tpb.Entry // oldLeaf will be nil if getResp has empty Leaf + if len(oldLeafB) > 0 { + oldLeaf = &tpb.Entry{} + if err := proto.Unmarshal(oldLeafB, oldLeaf); err != nil { + return nil, fmt.Errorf("proto.Unmarshal: %v", err) + } } if _, err := c.mutator.Mutate(oldLeaf, req.GetEntryUpdate().GetUpdate()); err != nil { return nil, fmt.Errorf("Mutate: %v", err) From be831c50f46802f348b1eed3cdf08edc38547009 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 18:12:47 +0100 Subject: [PATCH 09/46] Use nil in Update/Mutate instead &tpb.Entry{} on keyserver as well --- core/keyserver/keyserver.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index 983f807e7..0107d061e 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -290,11 +290,15 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* // - Correct signatures internal to the update. // - Hash of current data matches the expectation in the mutation. - // The very first mutation will have resp.LeafProof.LeafData=nil. - oldEntry := &tpb.Entry{} - if err := proto.Unmarshal(resp.GetLeafProof().GetLeaf().GetLeafValue(), oldEntry); err != nil { - glog.Errorf("proto.Unmarshal(%v, _): %v", resp.GetLeafProof().GetLeaf().GetLeafValue(), err) - return nil, grpc.Errorf(codes.InvalidArgument, "invalid previous leaf value") + // The very first mutation will have resp.LeafProof.MapLeaf.LeafValue=nil. + var oldEntry *tpb.Entry + oldLeafB := resp.GetLeafProof().GetLeaf().GetLeafValue() + if len(oldLeafB) > 0 { + oldEntry = &tpb.Entry{} + if err := proto.Unmarshal(oldLeafB, oldEntry); err != nil { + glog.Errorf("proto.Unmarshal(%v, _): %v", resp.GetLeafProof().GetLeaf().GetLeafValue(), err) + return nil, grpc.Errorf(codes.InvalidArgument, "invalid previous leaf value") + } } if _, err := s.mutator.Mutate(oldEntry, in.GetEntryUpdate().GetUpdate()); err == mutator.ErrReplay { glog.Warningf("Discarding request due to replay") From 23c0a7d655a7e608522ad33bc076fbaa0f94d5f0 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 18:21:22 +0100 Subject: [PATCH 10/46] Use nil in Update/Mutate instead &tpb.Entry{} on signer as well --- core/signer/signer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/signer/signer.go b/core/signer/signer.go index 4cd6e37dc..f09d13c7f 100644 --- a/core/signer/signer.go +++ b/core/signer/signer.go @@ -202,7 +202,7 @@ func (s *Signer) applyMutations(mutations []*tpb.SignedKV, leaves []*trillian.Ma retMap := make(map[[32]byte]*trillian.MapLeaf) for _, m := range mutations { index := m.GetKeyValue().GetKey() - var oldValue *tpb.Entry // If no map leaf was found, oldValue will be nil. + oldValue := &tpb.Entry{} // If no map leaf was found, oldValue will be nil. if leaf, ok := leafMap[toArray(index)]; ok { if err := proto.Unmarshal(leaf.GetLeafValue(), oldValue); err != nil { glog.Warningf("proto.Unmarshal(%v, _): %v", leaf.GetLeafValue(), err) From cd4edd5bb4d8c35d70a89009e35983d3ae7faa9e Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 18:49:25 +0100 Subject: [PATCH 11/46] Add helper method to Entry to avoid code duplication --- cmd/keytransparency-client/grpcc/grpc_client.go | 10 +++------- core/keyserver/keyserver.go | 13 ++++++------- core/mutator/entry/entry.go | 16 ++++++++++++++++ core/mutator/entry/entry_test.go | 5 ++++- core/signer/signer.go | 14 ++++++++------ 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 835021016..5ca1cc1f3 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -37,7 +37,6 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" - "github.com/golang/protobuf/proto" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" "github.com/google/trillian" @@ -202,12 +201,9 @@ func (c *Client) Update(ctx context.Context, userID, appID string, profileData [ return nil, fmt.Errorf("CreateUpdateEntryRequest: %v", err) } oldLeafB := getResp.GetLeafProof().GetLeaf().GetLeafValue() - var oldLeaf *tpb.Entry // oldLeaf will be nil if getResp has empty Leaf - if len(oldLeafB) > 0 { - oldLeaf = &tpb.Entry{} - if err := proto.Unmarshal(oldLeafB, oldLeaf); err != nil { - return nil, fmt.Errorf("proto.Unmarshal: %v", err) - } + oldLeaf, err := entry.FromLeafValue(oldLeafB) + if err != nil { + return nil, fmt.Errorf("entry.FromLeafValue: %v", err) } if _, err := c.mutator.Mutate(oldLeaf, req.GetEntryUpdate().GetUpdate()); err != nil { return nil, fmt.Errorf("Mutate: %v", err) diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index 0107d061e..2289e7edf 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -21,6 +21,7 @@ import ( "github.com/google/keytransparency/core/crypto/commitments" "github.com/google/keytransparency/core/crypto/vrf" "github.com/google/keytransparency/core/mutator" + "github.com/google/keytransparency/core/mutator/entry" "github.com/google/keytransparency/core/transaction" "github.com/golang/glog" @@ -291,14 +292,12 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* // - Hash of current data matches the expectation in the mutation. // The very first mutation will have resp.LeafProof.MapLeaf.LeafValue=nil. - var oldEntry *tpb.Entry + oldLeafB := resp.GetLeafProof().GetLeaf().GetLeafValue() - if len(oldLeafB) > 0 { - oldEntry = &tpb.Entry{} - if err := proto.Unmarshal(oldLeafB, oldEntry); err != nil { - glog.Errorf("proto.Unmarshal(%v, _): %v", resp.GetLeafProof().GetLeaf().GetLeafValue(), err) - return nil, grpc.Errorf(codes.InvalidArgument, "invalid previous leaf value") - } + oldEntry, err := entry.FromLeafValue(oldLeafB) + if err != nil { + glog.Errorf("entry.FromLeafValue: %v", err) + return nil, grpc.Errorf(codes.InvalidArgument, "invalid previous leaf value") } if _, err := s.mutator.Mutate(oldEntry, in.GetEntryUpdate().GetUpdate()); err == mutator.ErrReplay { glog.Warningf("Discarding request due to replay") diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index e064a5340..9537bfa35 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -103,6 +103,22 @@ func (*Entry) Mutate(oldValueM, updateM proto.Message) ([]byte, error) { return update.GetKeyValue().GetValue(), nil } +// FromLeafValue takes a trillian.MapLeaf.LeafValue and returns and instantiated +// Entry or nil if the passes LeafValue was nil. +func FromLeafValue(value []byte) (*tpb.Entry, error) { + if len(value) > 0 { + entry := new(tpb.Entry) + if err := proto.Unmarshal(value, entry); err != nil { + glog.Warningf("proto.Unmarshal(%v, _): %v", value, err) + return nil, err + } + return entry, nil + } + // For the very first mutation we will have + // resp.LeafProof.MapLeaf.LeafValue=nil. + return nil, nil +} + // verifyKeys verifies both old and new authorized keys based on the following // criteria: // 1. At least one signature with a key in the previous entry should exist. diff --git a/core/mutator/entry/entry_test.go b/core/mutator/entry/entry_test.go index 190757839..b9db278bc 100644 --- a/core/mutator/entry/entry_test.go +++ b/core/mutator/entry/entry_test.go @@ -188,7 +188,10 @@ func TestCheckMutation(t *testing.T) { if _, got := New().Mutate(tc.oldEntry, mutation); got != tc.err { t.Errorf("In %d: Mutate(%v, %v)=%v, want %v", i, tc.oldEntry, mutation, got, tc.err) - } } } + +func TestFromLeafValue(t *testing.T) { + +} diff --git a/core/signer/signer.go b/core/signer/signer.go index f09d13c7f..4b3a4d215 100644 --- a/core/signer/signer.go +++ b/core/signer/signer.go @@ -22,15 +22,15 @@ import ( "github.com/google/keytransparency/core/appender" "github.com/google/keytransparency/core/mutator" "github.com/google/keytransparency/core/transaction" + "github.com/google/keytransparency/core/mutator/entry" "github.com/golang/glog" "github.com/google/trillian" + "github.com/google/trillian/util" "github.com/prometheus/client_golang/prometheus" "golang.org/x/net/context" - "github.com/gogo/protobuf/proto" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - "github.com/google/trillian/util" ) var ( @@ -202,11 +202,13 @@ func (s *Signer) applyMutations(mutations []*tpb.SignedKV, leaves []*trillian.Ma retMap := make(map[[32]byte]*trillian.MapLeaf) for _, m := range mutations { index := m.GetKeyValue().GetKey() - oldValue := &tpb.Entry{} // If no map leaf was found, oldValue will be nil. + var oldValue *tpb.Entry // If no map leaf was found, oldValue will be nil. if leaf, ok := leafMap[toArray(index)]; ok { - if err := proto.Unmarshal(leaf.GetLeafValue(), oldValue); err != nil { - glog.Warningf("proto.Unmarshal(%v, _): %v", leaf.GetLeafValue(), err) - continue // A bad mutation should not make the whole batch fail. + var err error + oldValue, err = entry.FromLeafValue(leaf.GetLeafValue()) + if err != nil { + glog.Warningf("entry.FromLeafValue(%v): %v", err) + continue } } From 0a2850da93a4956befacfe370bf30f6c2c777fb2 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 19:25:20 +0100 Subject: [PATCH 12/46] Add helper method to Entry to avoid code duplication (tests) --- core/mutator/entry/entry.go | 14 ++++++++------ core/mutator/entry/entry_test.go | 25 ++++++++++++++++++++++--- core/signer/signer.go | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/core/mutator/entry/entry.go b/core/mutator/entry/entry.go index 9537bfa35..502c46b0b 100644 --- a/core/mutator/entry/entry.go +++ b/core/mutator/entry/entry.go @@ -54,11 +54,13 @@ func (*Entry) Mutate(oldValueM, updateM proto.Message) ([]byte, error) { glog.Warning("received proto.Message is not of type *tpb.SignedKV.") return nil, fmt.Errorf("updateM.(*tpb.SignedKV): _, %v", ok) } - - oldEntry, ok := oldValueM.(*tpb.Entry) - if !ok { - glog.Warning("received proto.Message is not of type *tpb.Entry.") - return nil, fmt.Errorf("oldValueM.(*tpb.Entry): _, %v", ok) + var oldEntry *tpb.Entry + if oldValueM != nil { + oldEntry, ok = oldValueM.(*tpb.Entry) + if !ok { + glog.Warning("received proto.Message is not of type *tpb.Entry.") + return nil, fmt.Errorf("oldValueM.(*tpb.Entry): _, %v", ok) + } } // Verify pointer to previous data. @@ -110,7 +112,7 @@ func FromLeafValue(value []byte) (*tpb.Entry, error) { entry := new(tpb.Entry) if err := proto.Unmarshal(value, entry); err != nil { glog.Warningf("proto.Unmarshal(%v, _): %v", value, err) - return nil, err + return nil, err } return entry, nil } diff --git a/core/mutator/entry/entry_test.go b/core/mutator/entry/entry_test.go index b9db278bc..c0d252ab0 100644 --- a/core/mutator/entry/entry_test.go +++ b/core/mutator/entry/entry_test.go @@ -30,6 +30,7 @@ import ( tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian/crypto/sigpb" + "reflect" ) const ( @@ -157,7 +158,7 @@ func TestCheckMutation(t *testing.T) { signers3 := signersFromPEMs(t, [][]byte{[]byte(testPrivKey1), []byte(testPrivKey2)}) _, _, _ = missingKeyEntryData2, hashMissingKeyEntry1, signers2 - for i, tc := range []struct { + for _, tc := range []struct { key []byte oldEntry *tpb.Entry newEntry *tpb.Entry @@ -187,11 +188,29 @@ func TestCheckMutation(t *testing.T) { } if _, got := New().Mutate(tc.oldEntry, mutation); got != tc.err { - t.Errorf("In %d: Mutate(%v, %v)=%v, want %v", i, tc.oldEntry, mutation, got, tc.err) + t.Errorf("Mutate(%v, %v)=%v, want %v", tc.oldEntry, mutation, got, tc.err) } } } func TestFromLeafValue(t *testing.T) { - + entry := &tpb.Entry{Commitment: []byte{1, 2}} + entryB, _ := proto.Marshal(entry) + for i, tc := range []struct { + leafVal []byte + want *tpb.Entry + wantErr bool + }{ + {make([]byte, 0), nil, false}, // empty leaf -> nil, no error + {[]byte{2, 2, 2, 2, 2, 2, 2}, nil, true}, // no valid proto Message + {entryB, entry, false}, + } { + if got, _ := FromLeafValue(tc.leafVal); !reflect.DeepEqual(got, tc.want) { + t.Errorf("FromLeafValue(%v)=%v, _ , want %v", tc.leafVal, got, tc.want) + t.Error(i) + } + if _, gotErr := FromLeafValue(tc.leafVal); (gotErr != nil) != tc.wantErr { + t.Errorf("FromLeafValue(%v)=_, %v", tc.leafVal, gotErr) + } + } } diff --git a/core/signer/signer.go b/core/signer/signer.go index 4b3a4d215..e57e44bc8 100644 --- a/core/signer/signer.go +++ b/core/signer/signer.go @@ -21,8 +21,8 @@ import ( "github.com/google/keytransparency/core/appender" "github.com/google/keytransparency/core/mutator" - "github.com/google/keytransparency/core/transaction" "github.com/google/keytransparency/core/mutator/entry" + "github.com/google/keytransparency/core/transaction" "github.com/golang/glog" "github.com/google/trillian" From 4d3a88d4d3d3fe1ec5a20ad55528e8d7fc097b06 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 20:44:14 +0100 Subject: [PATCH 13/46] Use helper method to Entry to avoid code duplication --- core/client/kt/requests.go | 6 ++++-- core/mutator/entry/entry_test.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/client/kt/requests.go b/core/client/kt/requests.go index dda5abf0b..1a966a1d2 100644 --- a/core/client/kt/requests.go +++ b/core/client/kt/requests.go @@ -27,6 +27,7 @@ import ( tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" "github.com/google/trillian/crypto/sigpb" + "github.com/google/keytransparency/core/mutator/entry" ) // CreateUpdateEntryRequest creates UpdateEntryRequest given GetEntryResponse, @@ -40,8 +41,9 @@ func (v *Verifier) CreateUpdateEntryRequest( if err != nil { return nil, fmt.Errorf("ProofToHash(): %v", err) } - prevEntry := new(tpb.Entry) - if err := proto.Unmarshal(getResp.GetLeafProof().GetLeaf().GetLeafValue(), prevEntry); err != nil { + oldLeaf := getResp.GetLeafProof().GetLeaf().GetLeafValue() + prevEntry, err := entry.FromLeafValue(oldLeaf) + if err != nil { return nil, fmt.Errorf("Error unmarshaling Entry from leaf proof: %v", err) } diff --git a/core/mutator/entry/entry_test.go b/core/mutator/entry/entry_test.go index c0d252ab0..cc638d5c9 100644 --- a/core/mutator/entry/entry_test.go +++ b/core/mutator/entry/entry_test.go @@ -203,7 +203,7 @@ func TestFromLeafValue(t *testing.T) { }{ {make([]byte, 0), nil, false}, // empty leaf -> nil, no error {[]byte{2, 2, 2, 2, 2, 2, 2}, nil, true}, // no valid proto Message - {entryB, entry, false}, + {entryB, entry, false}, // valid leaf } { if got, _ := FromLeafValue(tc.leafVal); !reflect.DeepEqual(got, tc.want) { t.Errorf("FromLeafValue(%v)=%v, _ , want %v", tc.leafVal, got, tc.want) From f2840cd3d24ae64a7a6b00232ab0deac9a14867c Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Wed, 9 Aug 2017 21:15:00 +0100 Subject: [PATCH 14/46] gofmt fix some typos --- core/client/kt/requests.go | 4 ++-- core/keyserver/keyserver.go | 1 - core/mutator/entry/entry_test.go | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/client/kt/requests.go b/core/client/kt/requests.go index 1a966a1d2..27737d160 100644 --- a/core/client/kt/requests.go +++ b/core/client/kt/requests.go @@ -24,10 +24,10 @@ import ( "github.com/benlaurie/objecthash/go/objecthash" "github.com/golang/protobuf/proto" + "github.com/google/keytransparency/core/mutator/entry" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" "github.com/google/trillian/crypto/sigpb" - "github.com/google/keytransparency/core/mutator/entry" ) // CreateUpdateEntryRequest creates UpdateEntryRequest given GetEntryResponse, @@ -77,7 +77,7 @@ func (v *Verifier) CreateUpdateEntryRequest( if err != nil { return nil, err } - previous := objecthash.ObjectHash(getResp.GetLeafProof().GetLeaf().GetLeafValue()) + previous := objecthash.ObjectHash(prevEntry) signedkv := &tpb.SignedKV{ KeyValue: kv, Signatures: sigs, diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index 2289e7edf..2cf064391 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -292,7 +292,6 @@ func (s *Server) UpdateEntry(ctx context.Context, in *tpb.UpdateEntryRequest) (* // - Hash of current data matches the expectation in the mutation. // The very first mutation will have resp.LeafProof.MapLeaf.LeafValue=nil. - oldLeafB := resp.GetLeafProof().GetLeaf().GetLeafValue() oldEntry, err := entry.FromLeafValue(oldLeafB) if err != nil { diff --git a/core/mutator/entry/entry_test.go b/core/mutator/entry/entry_test.go index cc638d5c9..2b9072379 100644 --- a/core/mutator/entry/entry_test.go +++ b/core/mutator/entry/entry_test.go @@ -18,6 +18,7 @@ import ( "bytes" "encoding/pem" "fmt" + "reflect" "testing" "github.com/google/keytransparency/core/crypto/dev" @@ -30,7 +31,6 @@ import ( tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian/crypto/sigpb" - "reflect" ) const ( @@ -203,7 +203,7 @@ func TestFromLeafValue(t *testing.T) { }{ {make([]byte, 0), nil, false}, // empty leaf -> nil, no error {[]byte{2, 2, 2, 2, 2, 2, 2}, nil, true}, // no valid proto Message - {entryB, entry, false}, // valid leaf + {entryB, entry, false}, // valid leaf } { if got, _ := FromLeafValue(tc.leafVal); !reflect.DeepEqual(got, tc.want) { t.Errorf("FromLeafValue(%v)=%v, _ , want %v", tc.leafVal, got, tc.want) From 01fba58a7c45dc10f00bb0b6eaa3504bc3d32be4 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Thu, 10 Aug 2017 15:42:18 +0100 Subject: [PATCH 15/46] compile again --- core/monitor/verify.go | 12 ++++++------ core/monitor/verify_test.go | 17 +---------------- impl/monitor/monitor.go | 3 +-- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index ded5ec99f..b42b0f80b 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -19,9 +19,9 @@ package monitor import ( - "fmt" "crypto" "errors" + "fmt" "github.com/golang/glog" @@ -82,7 +82,6 @@ func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutatio return errors.New("TODO: implement verification logic") } - func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { // TODO: export applyMutations in CreateEpoch / signer.go? // @@ -103,8 +102,11 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) // return ErrInvalidMutation //} - - newLeaf, err := mutator.Mutate(m.GetProof().GetLeaf().GetLeafValue(), m.GetUpdate()) + leafVal, err := entry.FromLeafValue(m.GetProof().GetLeaf().GetLeafValue()) + if err != nil { + return ErrInvalidMutation + } + newLeaf, err := mutator.Mutate(leafVal, m.GetUpdate()) if err != nil { // TODO(ismail): do not return; collect other errors if any return ErrInvalidMutation @@ -139,8 +141,6 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { } - - // compute the new leaf and store the intermediate hashes locally. // compute the new root using local intermediate hashes from epoch e. // verify rootHash diff --git a/core/monitor/verify_test.go b/core/monitor/verify_test.go index 11fe19a64..7174c0851 100644 --- a/core/monitor/verify_test.go +++ b/core/monitor/verify_test.go @@ -14,24 +14,9 @@ package monitor -import ( - "testing" - "github.com/google/trillian/merkle" - "fmt" -) - - // TODO(ismail): write extensive tests for verification steps (if not existing // in trillian) const ( emptyMapRootB64 = "xmifEIEqCYCXbZUz2Dh1KCFmFZVn7DUVVxbBQTr1PWo=" - mapID = int64(0) + mapID = int64(0) ) - -func TestServerVerifyMutations(t *testing.T) { - // verifyInclusionProof for empty leaf - if err := merkle.VerifyMapInclusionProof(mapID, index, - leafHash, rootHash, proof, hasher); err != nil { - return fmt.Errorf("VerifyMapInclusionProof(%x): %v", index, err) - } -} \ No newline at end of file diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index abd29816e..3762c0b82 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -35,9 +35,8 @@ import ( tcrypto "github.com/google/trillian/crypto" cmon "github.com/google/keytransparency/core/monitor" - mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - + mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" ) From 16db4f73f31ac31adda5dc6b1e53ac1e8a521d0b Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Thu, 10 Aug 2017 21:26:14 +0100 Subject: [PATCH 16/46] TODO verification --- core/monitor/verify.go | 51 +++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index b42b0f80b..391a6ac2c 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -31,8 +31,12 @@ import ( tcrypto "github.com/google/trillian/crypto" + "bytes" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" + "github.com/google/trillian/merkle" + "github.com/google/trillian/merkle/coniks" + "github.com/google/trillian/storage" ) var ( @@ -75,14 +79,14 @@ func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutatio // logVerifier.VerifyInclusionProof() // mapID := resp.GetSmr().GetMapId() - if err := verifyMutations(allMuts, resp.GetSmr().GetRootHash()); err != nil { + if err := verifyMutations(allMuts, resp.GetSmr().GetRootHash(), resp.GetSmr().GetMapId()); err != nil { return err } return errors.New("TODO: implement verification logic") } -func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { +func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { // TODO: export applyMutations in CreateEpoch / signer.go? // @@ -94,6 +98,9 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { inclusionMap := make(map[[32]byte]*trillian.MapLeafInclusion) updatedLeafMap := make(map[[32]byte]*trillian.MapLeaf) mutator := entry.New() + oldProofNodes := make(map[string]*storage.Node) + hasher := coniks.Default + for _, m := range muts { // verify that the provided leaf’s inclusion proof goes to epoch e-1: // @@ -125,22 +132,34 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte) error { // LeafHash: hasher.HashLeaf(mapID, l.Index, l.LeafValue), LeafValue: newLeaf, } - - //for level, proof := range m.GetProof().GetInclusion() { - // pElement := proof - // if len(pElement) == 0 { - // pElement = hasher.HashEmpty(treeID, sib.Path, level) - // } - // if proofIsRightHandElement { - // runningHash = hasher.HashChildren(runningHash, pElement) - // } else { - // runningHash = hasher.HashChildren(pElement, runningHash) - // } - //} - // - + // cache proof nodes: + for level, proof := range m.GetProof().GetInclusion() { + sid := storage.NewNodeIDFromBigInt(level, index, hasher.BitLen()) + pid := sid.Neighbor() + // TODO Do we need the node revision or is this only used internally? + pNode := &storage.Node{ + NodeID: pid, + Hash: proof, + NodeRevision: 0, + } + if p, ok := oldProofNodes[pid.String()]; ok { + // sanity check: for each mutation overlapping proof nodes should be + // equal: + bytes.Equal(p.Hash, proof) + } else { + oldProofNodes[pid.String()] = pNode + } + } } + // TODO write get function that returns and potentially recomputes proof nodes + // (if neccessary) and a set method that updates recomputed proof nodes and + // call: + // + //hs2 := merkle.NewHStar2(mapID, hasher) + //hs2.HStar2Nodes([]byte{}, hasher.Size(), new []HStar2LeafHash + // get SparseGetNodeFunc, set SparseSetNodeFunc) + // // compute the new leaf and store the intermediate hashes locally. // compute the new root using local intermediate hashes from epoch e. // verify rootHash From 4c8831bed6397347aad958ac16702ba025357aaa Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 11 Aug 2017 17:04:30 +0100 Subject: [PATCH 17/46] Work in progress: compute new root hash --- core/monitor/verify.go | 101 ++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 391a6ac2c..d2ceada61 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -19,24 +19,22 @@ package monitor import ( + "bytes" "crypto" "errors" "fmt" + "math/big" "github.com/golang/glog" - // "github.com/google/trillian" - // "github.com/google/trillian/merkle" - "github.com/google/keytransparency/core/mutator/entry" + "github.com/google/trillian/merkle" + "github.com/google/trillian/merkle/coniks" + "github.com/google/trillian/storage" tcrypto "github.com/google/trillian/crypto" - "bytes" + "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - "github.com/google/trillian" - "github.com/google/trillian/merkle" - "github.com/google/trillian/merkle/coniks" - "github.com/google/trillian/storage" ) var ( @@ -87,18 +85,9 @@ func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutatio } func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { - // TODO: export applyMutations in CreateEpoch / signer.go? - // - - // verify the mutation’s validity against the previous leaf. - // - // entry.VerifyKeys() - // or - // entry.Mutate() // does all checks and returns the new leaf as well - inclusionMap := make(map[[32]byte]*trillian.MapLeafInclusion) - updatedLeafMap := make(map[[32]byte]*trillian.MapLeaf) + newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) mutator := entry.New() - oldProofNodes := make(map[string]*storage.Node) + oldProofNodes := make(map[string][]byte) hasher := coniks.Default for _, m := range muts { @@ -115,53 +104,53 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er } newLeaf, err := mutator.Mutate(leafVal, m.GetUpdate()) if err != nil { - // TODO(ismail): do not return; collect other errors if any + // TODO(ismail): collect all data to reproduce this (expectedRoot, oldLeaf, and mutation) return ErrInvalidMutation } - // update and store intermediate hashes for this new leaf - // (using old inclusion proof and already updated intermediate leafs) - fmt.Println(newLeaf) - // the index shouldn't change: - var index [32]byte - copy(index[:], m.GetProof().GetLeaf().GetIndex()[:32]) - // TODO(ismail): do we actually need these copies? - inclusionMap[index] = m.GetProof() - - updatedLeafMap[index] = &trillian.MapLeaf{ - Index: index[:], - // LeafHash: hasher.HashLeaf(mapID, l.Index, l.LeafValue), - LeafValue: newLeaf, - } - // cache proof nodes: + + index := m.GetProof().GetLeaf().GetIndex() + + newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, hasher.BitLen()) + newLeafH := hasher.HashLeaf(mapID, index, newLeaf) + newLeaves = append(newLeaves, merkle.HStar2LeafHash{ + Index: newLeafnID.BigInt(), + LeafHash: newLeafH, + }) + + sibIDs := newLeafnID.Siblings() for level, proof := range m.GetProof().GetInclusion() { - sid := storage.NewNodeIDFromBigInt(level, index, hasher.BitLen()) - pid := sid.Neighbor() - // TODO Do we need the node revision or is this only used internally? - pNode := &storage.Node{ - NodeID: pid, - Hash: proof, - NodeRevision: 0, - } - if p, ok := oldProofNodes[pid.String()]; ok { + pID := sibIDs[level] + if p, ok := oldProofNodes[pID.String()]; ok { // sanity check: for each mutation overlapping proof nodes should be // equal: - bytes.Equal(p.Hash, proof) + if !bytes.Equal(p, proof) { + // TODO: this is really odd + } } else { - oldProofNodes[pid.String()] = pNode + oldProofNodes[pID.String()] = proof } } } - // TODO write get function that returns and potentially recomputes proof nodes - // (if neccessary) and a set method that updates recomputed proof nodes and - // call: - // - //hs2 := merkle.NewHStar2(mapID, hasher) - //hs2.HStar2Nodes([]byte{}, hasher.Size(), new []HStar2LeafHash - - // get SparseGetNodeFunc, set SparseSetNodeFunc) - // + // TODO write get function that returns old proof nodes by index and level // compute the new leaf and store the intermediate hashes locally. // compute the new root using local intermediate hashes from epoch e. // verify rootHash - return errors.New("TODO: implement verification logic") + + hs2 := merkle.NewHStar2(mapID, hasher) + newRoot, err := hs2.HStar2Nodes([]byte{}, hasher.Size(), newLeaves, + func(depth int, index *big.Int) ([]byte, error) { + nID := storage.NewNodeIDFromBigInt(depth, index, hasher.BitLen()) + if p, ok := oldProofNodes[nID.String()]; ok { + return p, nil + } + return nil, nil + }, nil) + if err != nil { + glog.Errorf("hs2.HStar2Nodes(_): %v", err) + fmt.Errorf("could not compute new root hash: hs2.HStar2Nodes(_): %v", err) + } + if !bytes.Equal(newRoot, expectedRoot) { + return ErrNotMatchingRoot + } + return nil } From a0c94046a96f228ebff49995154986f7438dbcc5 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 14 Aug 2017 13:58:41 +0100 Subject: [PATCH 18/46] Minor cleanup --- core/monitor/monitor.go | 20 ++++++++++++++++++++ core/monitor/verify.go | 32 ++++++++++++++++++-------------- impl/monitor/monitor.go | 2 ++ 3 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 core/monitor/monitor.go diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go new file mode 100644 index 000000000..3afc4852b --- /dev/null +++ b/core/monitor/monitor.go @@ -0,0 +1,20 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +package monitor + +type Monitor struct { + +} \ No newline at end of file diff --git a/core/monitor/verify.go b/core/monitor/verify.go index d2ceada61..2de39bee3 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -14,8 +14,7 @@ // Package monitor implements the monitor service. A monitor repeatedly polls a // key-transparency server's Mutations API and signs Map Roots if it could -// reconstruct -// clients can query. +// reconstruct clients can query. package monitor import ( @@ -35,6 +34,7 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" ) var ( @@ -56,16 +56,21 @@ var ( // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. -func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { +func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, getMutResp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) *mopb.GetMonitoringResponse { + resp := new(mopb.GetMonitoringResponse) + resp.Smr = *getMutResp.Smr + // reset map + resp.Smr.Signature = nil + sig := getMutResp.GetSmr().GetSignature() // verify signature on map root: - if err := tcrypto.VerifyObject(mapPubKey, resp.GetSmr(), resp.GetSmr().GetSignature()); err != nil { + if err := tcrypto.VerifyObject(mapPubKey, resp.Smr, sig); err != nil { glog.Errorf("couldn't verify signature on map root: %v", err) return ErrInvalidMapSignature } // verify signature on log-root: - hash := tcrypto.HashLogRoot(*resp.GetLogRoot()) - if err := tcrypto.Verify(logPubKey, hash, resp.GetLogRoot().GetSignature()); err != nil { + hash := tcrypto.HashLogRoot(*getMutResp.GetLogRoot()) + if err := tcrypto.Verify(logPubKey, hash, getMutResp.GetLogRoot().GetSignature()); err != nil { return ErrInvalidLogSignature } //hasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) @@ -77,7 +82,7 @@ func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, resp *ktpb.GetMutatio // logVerifier.VerifyInclusionProof() // mapID := resp.GetSmr().GetMapId() - if err := verifyMutations(allMuts, resp.GetSmr().GetRootHash(), resp.GetSmr().GetMapId()); err != nil { + if err := verifyMutations(allMuts, getMutResp.GetSmr().GetRootHash(), getMutResp.GetSmr().GetMapId()); err != nil { return err } @@ -102,21 +107,21 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er if err != nil { return ErrInvalidMutation } + + // compute the new leaf newLeaf, err := mutator.Mutate(leafVal, m.GetUpdate()) if err != nil { // TODO(ismail): collect all data to reproduce this (expectedRoot, oldLeaf, and mutation) return ErrInvalidMutation } - index := m.GetProof().GetLeaf().GetIndex() - newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, hasher.BitLen()) - newLeafH := hasher.HashLeaf(mapID, index, newLeaf) + newLeafHash := hasher.HashLeaf(mapID, index, newLeaf) newLeaves = append(newLeaves, merkle.HStar2LeafHash{ Index: newLeafnID.BigInt(), - LeafHash: newLeafH, + LeafHash: newLeafHash, }) - + // store the proof hashes locally to recompute the tree below: sibIDs := newLeafnID.Siblings() for level, proof := range m.GetProof().GetInclusion() { pID := sibIDs[level] @@ -131,8 +136,7 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er } } } - // TODO write get function that returns old proof nodes by index and level - // compute the new leaf and store the intermediate hashes locally. + // compute the new root using local intermediate hashes from epoch e. // verify rootHash diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 3762c0b82..8470b0cd0 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -146,6 +146,8 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] } respSmr := resp.GetSmr() var monitorResp *mopb.GetMonitoringResponse + + // TODO(Ismail): let the verification method in core directly return the response switch err := cmon.VerifyResponse(s.logPubKey, s.mapPubKey, resp, mutations); err { // TODO(ismail): return proper data for failure cases: case cmon.ErrInvalidMutation: From 7c54e26de1ff64779fce254fc32013a3796cebc1 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Mon, 14 Aug 2017 18:18:58 +0100 Subject: [PATCH 19/46] Some cleanup, further splitting up into core/impl --- core/monitor/monitor.go | 24 +++++++++++++-- core/monitor/verify.go | 67 ++++++++++++++++++++++++----------------- impl/monitor/monitor.go | 63 ++++++++------------------------------ 3 files changed, 73 insertions(+), 81 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 3afc4852b..81dc5d050 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -12,9 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. - package monitor +import ( + "crypto" + + "github.com/google/trillian" + "github.com/google/trillian/merkle" + "github.com/google/trillian/merkle/hashers" +) + type Monitor struct { + hasher hashers.MapHasher + logPubKey crypto.PublicKey + mapPubKey crypto.PublicKey + logVerifier merkle.LogVerifier + trusted trillian.SignedLogRoot +} -} \ No newline at end of file +func New(hasher hashers.MapHasher, mapPubKey, logPubKey crypto.PublicKey, logVerifier merkle.LogVerifier) *Monitor { + return &Monitor{ + hasher: hasher, + logVerifier: logVerifier, + logPubKey: logPubKey, + mapPubKey: mapPubKey, + } +} diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 2de39bee3..5730f8e43 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -19,7 +19,6 @@ package monitor import ( "bytes" - "crypto" "errors" "fmt" "math/big" @@ -35,6 +34,7 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" + "time" ) var ( @@ -56,37 +56,49 @@ var ( // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. -func VerifyResponse(logPubKey, mapPubKey crypto.PublicKey, getMutResp *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) *mopb.GetMonitoringResponse { +func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) *mopb.GetMonitoringResponse { resp := new(mopb.GetMonitoringResponse) - resp.Smr = *getMutResp.Smr + seen := time.Now().UnixNano() + resp.SeenTimestampNanos = seen + + // copy of received SMR: + smr := *in.Smr + resp.Smr = &smr // reset map resp.Smr.Signature = nil - sig := getMutResp.GetSmr().GetSignature() + // verify signature on map root: - if err := tcrypto.VerifyObject(mapPubKey, resp.Smr, sig); err != nil { + if err := tcrypto.VerifyObject(m.mapPubKey, resp.Smr, in.GetSmr().GetSignature()); err != nil { glog.Errorf("couldn't verify signature on map root: %v", err) - return ErrInvalidMapSignature + resp.InvalidMapSigProof = in.GetSmr() } - // verify signature on log-root: - hash := tcrypto.HashLogRoot(*getMutResp.GetLogRoot()) - if err := tcrypto.Verify(logPubKey, hash, getMutResp.GetLogRoot().GetSignature()); err != nil { - return ErrInvalidLogSignature + logRoot := in.GetLogRoot() + // Verify SignedLogRoot signature. + hash := tcrypto.HashLogRoot(*logRoot) + if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { + resp.InvalidLogSigProof = logRoot + } + + // Implicitly trust the first root we get. + if m.trusted.TreeSize != 0 { + // Verify consistency proof. + if err := m.logVerifier.VerifyConsistencyProof( + m.trusted.TreeSize, logRoot.TreeSize, + m.trusted.RootHash, logRoot.RootHash, + in.GetLogConsistency()); err != nil { + // TODO + } } - //hasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) - //if err != nil { - // return nil, fmt.Errorf("Failed retrieving LogHasher from registry: %v", err) - //} - // logVerifier := merkle.NewLogVerifier(hasher) - // logVerifier.VerifyConsistencyProof() + + // TODO: // logVerifier.VerifyInclusionProof() - // mapID := resp.GetSmr().GetMapId() - if err := verifyMutations(allMuts, getMutResp.GetSmr().GetRootHash(), getMutResp.GetSmr().GetMapId()); err != nil { - return err + if err := verifyMutations(allMuts, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); err != nil { + // TODO resp.InvalidMutation } - return errors.New("TODO: implement verification logic") + return resp } func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { @@ -97,19 +109,18 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er for _, m := range muts { // verify that the provided leaf’s inclusion proof goes to epoch e-1: - // //if err := merkle.VerifyMapInclusionProof(mapID, index, // leafHash, rootHash, proof, hasher); err != nil { // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) - // return ErrInvalidMutation + // // TODO modify response object //} - leafVal, err := entry.FromLeafValue(m.GetProof().GetLeaf().GetLeafValue()) + oldLeaf, err := entry.FromLeafValue(m.GetProof().GetLeaf().GetLeafValue()) if err != nil { return ErrInvalidMutation } // compute the new leaf - newLeaf, err := mutator.Mutate(leafVal, m.GetUpdate()) + newLeaf, err := mutator.Mutate(oldLeaf, m.GetUpdate()) if err != nil { // TODO(ismail): collect all data to reproduce this (expectedRoot, oldLeaf, and mutation) return ErrInvalidMutation @@ -129,7 +140,7 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er // sanity check: for each mutation overlapping proof nodes should be // equal: if !bytes.Equal(p, proof) { - // TODO: this is really odd + // TODO: this is really odd -> monitor should complain! } } else { oldProofNodes[pID.String()] = proof @@ -137,9 +148,8 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er } } - // compute the new root using local intermediate hashes from epoch e. - // verify rootHash - + // compute the new root using local intermediate hashes from epoch e + // (above proof hashes): hs2 := merkle.NewHStar2(mapID, hasher) newRoot, err := hs2.HStar2Nodes([]byte{}, hasher.Size(), newLeaves, func(depth int, index *big.Int) ([]byte, error) { @@ -153,6 +163,7 @@ func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) er glog.Errorf("hs2.HStar2Nodes(_): %v", err) fmt.Errorf("could not compute new root hash: hs2.HStar2Nodes(_): %v", err) } + // verify rootHash if !bytes.Equal(newRoot, expectedRoot) { return ErrNotMatchingRoot } diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 8470b0cd0..b40905794 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -22,7 +22,6 @@ import ( "bytes" "crypto" "errors" - "fmt" "time" "github.com/golang/glog" @@ -31,6 +30,9 @@ import ( "google.golang.org/grpc/codes" "github.com/google/trillian" + "github.com/google/trillian/merkle" + "github.com/google/trillian/merkle/maphasher" + "github.com/google/trillian/merkle/rfc6962" tcrypto "github.com/google/trillian/crypto" @@ -57,9 +59,7 @@ type Server struct { client mupb.MutationServiceClient pollPeriod time.Duration - mapPubKey crypto.PublicKey - logPubKey crypto.PublicKey - + monitor *cmon.Monitor signer *tcrypto.Signer proccessedSMRs []*mopb.GetMonitoringResponse } @@ -70,10 +70,13 @@ func New(cli mupb.MutationServiceClient, logPubKey, mapPubKey crypto.PublicKey, poll time.Duration) *Server { return &Server{ - client: cli, - pollPeriod: poll, - logPubKey: logPubKey, - mapPubKey: mapPubKey, + client: cli, + pollPeriod: poll, + monitor: cmon.New(maphasher.Default, + mapPubKey, + logPubKey, + merkle.NewLogVerifier(rfc6962.DefaultHasher), + ), signer: signer, proccessedSMRs: make([]*mopb.GetMonitoringResponse, 256), } @@ -130,7 +133,6 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] return nil, err } - seen := time.Now().UnixNano() if got, want := resp.GetSmr(), s.lastSeenSMR(); bytes.Equal(got.GetRootHash(), want.GetRootHash()) && got.GetMapRevision() == want.GetMapRevision() { // We already processed this SMR. Do not update seen SMRs. Do not scroll @@ -144,50 +146,9 @@ func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([] glog.Errorf("s.pageMutations(_): %v", err) return nil, err } - respSmr := resp.GetSmr() - var monitorResp *mopb.GetMonitoringResponse // TODO(Ismail): let the verification method in core directly return the response - switch err := cmon.VerifyResponse(s.logPubKey, s.mapPubKey, resp, mutations); err { - // TODO(ismail): return proper data for failure cases: - case cmon.ErrInvalidMutation: - glog.Errorf("TODO: handle this ErrInvalidMutation properly") - case cmon.ErrInvalidMapSignature: - glog.Infof("Signature on map did not verify: %v", err) - monitorResp = &mopb.GetMonitoringResponse{ - IsValid: false, - SeenTimestampNanos: seen, - InvalidMapSigProof: respSmr, - } - case cmon.ErrInvalidLogSignature: - glog.Infof("Signature on log did not verify: %v", err) - monitorResp = &mopb.GetMonitoringResponse{ - IsValid: false, - SeenTimestampNanos: seen, - InvalidLogSigProof: resp.GetLogRoot(), - } - case cmon.ErrNotMatchingRoot: - glog.Errorf("TODO: handle this ErrNotMatchingRoot properly") - case nil: - // Sign map root with monitor key: - sig, err := s.signer.SignObject(resp.GetSmr().GetRootHash()) - if err != nil { - return nil, fmt.Errorf("s.signer.SignObject(_): %v", err) - } - // update signature on smr: - respSmr.Signature = sig - monitorResp = &mopb.GetMonitoringResponse{ - Smr: respSmr, - IsValid: true, - SeenTimestampNanos: seen, - } - default: - glog.Errorf("Unexpected error: %v", err) - // TODO(ismail): Clarify: Would we still want to create a monitor response - // in this case? - return nil, err - } - + monitorResp := s.monitor.VerifyResponse(resp, mutations) // Update seen/processed signed map roots: s.proccessedSMRs = append(s.proccessedSMRs, monitorResp) From c3a0907b0da7d7b644937a499168eb55592e3b05 Mon Sep 17 00:00:00 2001 From: Ismail Khoffi Date: Fri, 18 Aug 2017 16:21:19 +0100 Subject: [PATCH 20/46] Some of the review comments (this should go to #768) --- core/monitor/monitor.go | 15 ++++++++++----- core/monitor/verify.go | 8 +------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 81dc5d050..3bb67e718 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -16,6 +16,7 @@ package monitor import ( "crypto" + "fmt" "github.com/google/trillian" "github.com/google/trillian/merkle" @@ -30,11 +31,15 @@ type Monitor struct { trusted trillian.SignedLogRoot } -func New(hasher hashers.MapHasher, mapPubKey, logPubKey crypto.PublicKey, logVerifier merkle.LogVerifier) *Monitor { +func New(logTree, mapTree trillian.Tree) (*Monitor, error) { + // Log Hasher. + logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) + if err != nil { + return nil, fmt.Errorf("Failed creating LogHasher: %v", err) + } return &Monitor{ - hasher: hasher, - logVerifier: logVerifier, - logPubKey: logPubKey, - mapPubKey: mapPubKey, + logVerifier: merkle.NewLogVerifier(logHasher), + logPubKey: logTree.GetPublicKey(), + mapPubKey: mapTree.GetPublicKey(), } } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 5730f8e43..100d5de99 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -44,12 +44,6 @@ var ( // ErrNotMatchingRoot occurs when the reconstructed root differs from the one // we received from the server. ErrNotMatchingRoot = errors.New("recreated root does not match") - // ErrInvalidMapSignature occurs when the signature on the observed map root - // is invalid. - ErrInvalidMapSignature = errors.New("invalid signature on map in GetMutationsResponse") - // ErrInvalidLogSignature occurs when the signature on the observed map root - // is invalid. - ErrInvalidLogSignature = errors.New("invalid signature on log in GetMutationsResponse") ) // verifyResponse verifies a response received by the GetMutations API. @@ -101,7 +95,7 @@ func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb. return resp } -func verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { +func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) mutator := entry.New() oldProofNodes := make(map[string][]byte) From 48b5f69fae5183e7f61d419be2d77ca22636c0d3 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 14:36:34 -0400 Subject: [PATCH 21/46] Minor changes: compiles --- core/monitor/monitor.go | 2 +- core/monitor/verify.go | 2 +- impl/monitor/monitor.go | 10 ++-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 3bb67e718..2e3ea481d 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -41,5 +41,5 @@ func New(logTree, mapTree trillian.Tree) (*Monitor, error) { logVerifier: merkle.NewLogVerifier(logHasher), logPubKey: logTree.GetPublicKey(), mapPubKey: mapTree.GetPublicKey(), - } + }, nil } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 100d5de99..087686584 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -88,7 +88,7 @@ func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb. // TODO: // logVerifier.VerifyInclusionProof() - if err := verifyMutations(allMuts, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); err != nil { + if err := m.verifyMutations(allMuts, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); err != nil { // TODO resp.InvalidMutation } diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index b40905794..5e3266b2c 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -30,9 +30,6 @@ import ( "google.golang.org/grpc/codes" "github.com/google/trillian" - "github.com/google/trillian/merkle" - "github.com/google/trillian/merkle/maphasher" - "github.com/google/trillian/merkle/rfc6962" tcrypto "github.com/google/trillian/crypto" @@ -72,11 +69,8 @@ func New(cli mupb.MutationServiceClient, return &Server{ client: cli, pollPeriod: poll, - monitor: cmon.New(maphasher.Default, - mapPubKey, - logPubKey, - merkle.NewLogVerifier(rfc6962.DefaultHasher), - ), + // TODO(ismail) use domain info to properly init. the monitor: + monitor: &cmon.Monitor{}, signer: signer, proccessedSMRs: make([]*mopb.GetMonitoringResponse, 256), } From 352d299388b01bf19329b79a1ab6ca0d98e2c8fa Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 15:39:59 -0400 Subject: [PATCH 22/46] Keep imports relative --- .../keytransparency_v1_types.pb.go | 137 +++++++++--------- .../keytransparency_v1_types.proto | 8 +- 2 files changed, 72 insertions(+), 73 deletions(-) diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go index 1044a313e..bfda36ebf 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.pb.go @@ -828,73 +828,72 @@ func init() { func init() { proto.RegisterFile("keytransparency_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1079 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5d, 0x6e, 0x1b, 0x37, - 0x10, 0x8e, 0xb4, 0x96, 0x2c, 0x8d, 0xff, 0x52, 0xc6, 0xb1, 0x55, 0x15, 0x09, 0x8c, 0x35, 0xda, - 0x26, 0x45, 0x21, 0xc7, 0x6b, 0xc8, 0x6d, 0xd2, 0x87, 0xa6, 0x49, 0x8a, 0xd8, 0xb0, 0x0d, 0x18, - 0x74, 0xe2, 0x3e, 0x2e, 0x68, 0x89, 0x5a, 0x13, 0x5e, 0x2d, 0x59, 0x92, 0x2b, 0x64, 0x0d, 0x14, - 0xe8, 0x01, 0x0a, 0x14, 0xe8, 0x19, 0x7a, 0x86, 0x5e, 0xa0, 0xb7, 0xe8, 0x69, 0x0a, 0x92, 0xbb, - 0xfa, 0xb1, 0xe5, 0xbf, 0x3c, 0xe4, 0xc5, 0x26, 0x67, 0xe6, 0xdb, 0x99, 0xf9, 0xe6, 0x9b, 0xd5, - 0xc2, 0xe3, 0x33, 0x9a, 0x69, 0x49, 0x12, 0x25, 0x88, 0xa4, 0x49, 0x27, 0x0b, 0x07, 0x9b, 0xa1, - 0xce, 0x04, 0x55, 0x2d, 0x21, 0xb9, 0xe6, 0xa8, 0x71, 0xc1, 0xdf, 0x1a, 0x6c, 0xb6, 0xac, 0xbf, - 0xd9, 0x8e, 0x98, 0x3e, 0x4d, 0x4f, 0x5a, 0x1d, 0xde, 0xdf, 0x88, 0x38, 0x8f, 0x62, 0xba, 0xa1, - 0x25, 0x8b, 0x63, 0x46, 0x92, 0x8d, 0x8e, 0xcc, 0x84, 0xe6, 0x1b, 0x67, 0x34, 0x53, 0xe2, 0x24, - 0xff, 0xe7, 0x1e, 0xd8, 0xdc, 0xba, 0x19, 0xa6, 0x58, 0x24, 0x4e, 0xdc, 0xdf, 0x1c, 0xf4, 0xf4, - 0x1a, 0x50, 0x71, 0xc8, 0x43, 0x37, 0x6f, 0x11, 0x1a, 0xf6, 0x89, 0x08, 0x89, 0x60, 0x0e, 0xe2, - 0x6f, 0x42, 0xfd, 0x35, 0xef, 0xf7, 0x99, 0xd6, 0xb4, 0x8b, 0xee, 0x83, 0x77, 0x46, 0xb3, 0x46, - 0x69, 0xad, 0xf4, 0x64, 0x1e, 0x9b, 0x23, 0x42, 0x30, 0xd3, 0x25, 0x9a, 0x34, 0xca, 0xd6, 0x64, - 0xcf, 0xfe, 0x1f, 0x25, 0x98, 0xfb, 0x39, 0xd1, 0x32, 0x7b, 0x2f, 0xba, 0x44, 0x53, 0xf4, 0x02, - 0xaa, 0xa9, 0x3d, 0xd9, 0xa8, 0xb9, 0xc0, 0x6f, 0x5d, 0xc5, 0x5b, 0xeb, 0x88, 0x45, 0x09, 0xed, - 0xee, 0x1d, 0xe3, 0x1c, 0x81, 0x7e, 0x82, 0x7a, 0xa7, 0x48, 0xdf, 0xf0, 0x2c, 0x7c, 0xfd, 0x6a, - 0xf8, 0xb0, 0x52, 0x3c, 0x42, 0xf9, 0x29, 0x54, 0x6c, 0x35, 0xe8, 0x31, 0x80, 0xb3, 0xf6, 0x69, - 0xa2, 0xf3, 0x26, 0xc6, 0x2c, 0x68, 0x1f, 0x96, 0x48, 0xaa, 0x4f, 0xb9, 0x64, 0xe7, 0xb4, 0x1b, - 0x9a, 0xc1, 0x34, 0xca, 0x6b, 0xde, 0xf5, 0x19, 0x0f, 0xd3, 0x93, 0x98, 0x75, 0xf6, 0x68, 0x86, - 0x17, 0x47, 0xd8, 0x3d, 0x9a, 0x29, 0xff, 0xef, 0x12, 0xd4, 0x87, 0x5e, 0xd4, 0x84, 0x59, 0xda, - 0x0d, 0xda, 0xed, 0xcd, 0xe7, 0x2e, 0xf1, 0xce, 0x3d, 0x5c, 0x18, 0xd0, 0x0f, 0xf0, 0xb9, 0x54, - 0x24, 0x1c, 0x50, 0xc9, 0x7a, 0x19, 0x4b, 0xa2, 0x50, 0x9d, 0x92, 0xa0, 0xbd, 0x1d, 0x6e, 0x3d, - 0xfb, 0x2e, 0x70, 0xc4, 0xee, 0xdc, 0xc3, 0x2b, 0x52, 0x91, 0xe3, 0x22, 0xe2, 0xc8, 0x06, 0x18, - 0x3f, 0x0a, 0x60, 0x99, 0x76, 0xba, 0x13, 0x70, 0x11, 0xb4, 0xb7, 0x2d, 0x57, 0x06, 0x87, 0xac, - 0x77, 0x88, 0x3c, 0x0c, 0xda, 0xdb, 0xaf, 0x00, 0x6a, 0x67, 0x34, 0xb3, 0x52, 0xf6, 0x03, 0xa8, - 0xed, 0xd1, 0xec, 0x98, 0xc4, 0x29, 0x9d, 0x32, 0xde, 0x65, 0xa8, 0x0c, 0x8c, 0x2b, 0x9f, 0xaf, - 0xbb, 0xf8, 0x7f, 0x95, 0xa1, 0x56, 0x4c, 0x0a, 0xfd, 0x08, 0x75, 0xf3, 0x30, 0x17, 0x56, 0xba, - 0x69, 0xc0, 0x45, 0x2e, 0x6c, 0x2a, 0x70, 0x59, 0x31, 0x80, 0x62, 0x51, 0x42, 0x74, 0x2a, 0x69, - 0xc1, 0x78, 0x70, 0xb3, 0x44, 0xec, 0xc1, 0x81, 0xec, 0x78, 0xf1, 0xd8, 0x53, 0x50, 0x13, 0x6a, - 0x42, 0xd2, 0x01, 0xe3, 0xa9, 0x72, 0x4c, 0xe0, 0xe1, 0xbd, 0xf9, 0x1e, 0x96, 0x2e, 0x40, 0xc7, - 0x1b, 0xaf, 0xbb, 0xc6, 0xbf, 0x1d, 0x6f, 0x7c, 0x2e, 0x58, 0x69, 0xb9, 0x8d, 0x7b, 0xc3, 0x22, - 0xa6, 0x49, 0x1c, 0x67, 0xae, 0x8a, 0x9c, 0x90, 0x17, 0xe5, 0xef, 0x4b, 0xfe, 0x07, 0xa8, 0x1d, - 0xa4, 0x9a, 0x68, 0xc6, 0x93, 0x31, 0xc5, 0x97, 0xee, 0xac, 0xf8, 0x67, 0x50, 0x11, 0x92, 0xf3, - 0x5e, 0x9e, 0xb9, 0xd9, 0x1a, 0xee, 0xf0, 0x01, 0x11, 0xfb, 0x94, 0xf4, 0x76, 0x93, 0x4e, 0x9c, - 0x2a, 0xc6, 0x13, 0xec, 0x02, 0x7d, 0x06, 0x4b, 0x6f, 0xa9, 0x76, 0x24, 0xd0, 0x5f, 0x53, 0xaa, - 0x34, 0x5a, 0x85, 0xd9, 0x54, 0x51, 0x19, 0xb2, 0x6e, 0xde, 0x54, 0xd5, 0x5c, 0x77, 0xbb, 0xe8, - 0x21, 0x54, 0x89, 0x10, 0xc6, 0x5e, 0xb6, 0xf6, 0x0a, 0x11, 0x62, 0xb7, 0x8b, 0xbe, 0x82, 0xa5, - 0x1e, 0x93, 0x4a, 0x87, 0x5a, 0x52, 0x1a, 0x2a, 0x76, 0x4e, 0x2d, 0x6d, 0x1e, 0x5e, 0xb0, 0xe6, - 0x77, 0x92, 0xd2, 0x23, 0x76, 0x4e, 0xfd, 0xff, 0xca, 0x70, 0x7f, 0x94, 0x4b, 0x09, 0x9e, 0x28, - 0x8a, 0xbe, 0x80, 0xfa, 0x40, 0xf6, 0x42, 0x57, 0xb5, 0x13, 0x4f, 0x6d, 0x20, 0x7b, 0x87, 0xe6, - 0x3e, 0xb9, 0xc0, 0xe5, 0x8f, 0x59, 0x60, 0xf4, 0x1c, 0x20, 0xa6, 0xa4, 0x48, 0xe0, 0xdd, 0x48, - 0x4b, 0xdd, 0x44, 0xbb, 0xec, 0x4f, 0xc1, 0x53, 0x7d, 0xd9, 0x98, 0xb1, 0x98, 0xd5, 0x11, 0xc6, - 0xb1, 0x7e, 0x40, 0x04, 0xe6, 0x5c, 0x63, 0x13, 0x83, 0x02, 0xa8, 0xc5, 0x3c, 0x0a, 0x25, 0xe7, - 0xba, 0x51, 0x99, 0x1e, 0xbf, 0xcf, 0x23, 0x1b, 0x3f, 0x1b, 0xbb, 0x03, 0xfa, 0x1a, 0x96, 0x0c, - 0xa6, 0xc3, 0x13, 0xc5, 0x94, 0x36, 0xad, 0x34, 0xaa, 0x6b, 0xde, 0x93, 0x79, 0xbc, 0x18, 0xf3, - 0xe8, 0xf5, 0xc8, 0x8a, 0xd6, 0x61, 0xc1, 0x04, 0xb2, 0xa2, 0xc6, 0xc6, 0xac, 0x0d, 0x9b, 0x8f, - 0x79, 0x34, 0xac, 0xdb, 0xbc, 0x31, 0x56, 0xf7, 0x99, 0x72, 0xec, 0xee, 0x30, 0xa5, 0xf9, 0x2d, - 0x06, 0xba, 0x0c, 0x15, 0xa5, 0x89, 0xd4, 0x96, 0x5b, 0x0f, 0xbb, 0x8b, 0x19, 0x89, 0x20, 0xd1, - 0xd8, 0x24, 0x2b, 0xb8, 0x66, 0x0c, 0x66, 0x88, 0x63, 0x1a, 0x98, 0xb9, 0x41, 0x03, 0x95, 0x69, - 0x1a, 0xf8, 0x0d, 0x1a, 0x97, 0xab, 0xcc, 0xa5, 0xf0, 0x0a, 0xaa, 0x76, 0x23, 0x54, 0xa3, 0x64, - 0xf7, 0xf8, 0x9b, 0xab, 0x47, 0x7d, 0x51, 0x46, 0x38, 0x47, 0xa2, 0x47, 0x00, 0x09, 0xfd, 0xa0, - 0xc3, 0xf1, 0xb6, 0xea, 0xc6, 0x72, 0x64, 0x0c, 0xfe, 0x3f, 0x25, 0x40, 0xee, 0x87, 0xe5, 0x53, - 0x28, 0x1e, 0xed, 0xc0, 0x3c, 0x35, 0x79, 0xc2, 0x7c, 0xa1, 0x9d, 0x94, 0xbe, 0xbc, 0xba, 0xaf, - 0xb1, 0x5f, 0x3e, 0x3c, 0x47, 0x47, 0x17, 0xff, 0x17, 0x78, 0x30, 0x51, 0x77, 0x4e, 0xd9, 0xcb, - 0x62, 0xdf, 0xdd, 0xab, 0xe2, 0x2e, 0x8c, 0xe5, 0xfb, 0xff, 0x67, 0x09, 0x1e, 0xbc, 0xa5, 0xba, - 0x78, 0xfb, 0xa8, 0x82, 0x92, 0x65, 0xa8, 0x50, 0xc1, 0x3b, 0xa7, 0xf6, 0xc9, 0x1e, 0x76, 0x97, - 0x69, 0x8d, 0x97, 0xa7, 0x35, 0xfe, 0x08, 0xc0, 0x4a, 0x48, 0xf3, 0x33, 0x9a, 0x58, 0x6e, 0xea, - 0xd8, 0x8a, 0xea, 0x9d, 0x31, 0x4c, 0x2a, 0x6c, 0x66, 0x52, 0x61, 0xfe, 0xbf, 0x65, 0x58, 0x9e, - 0xac, 0x28, 0x6f, 0x76, 0x7a, 0x49, 0xf9, 0x96, 0x96, 0xef, 0xb8, 0xa5, 0xde, 0xc7, 0x6f, 0xe9, - 0xcc, 0xed, 0xb6, 0xb4, 0x72, 0x79, 0x4b, 0xd1, 0x4b, 0xa8, 0xf7, 0x8b, 0xbe, 0xec, 0xb6, 0x5f, - 0xfb, 0x7a, 0x2f, 0x28, 0xc0, 0x23, 0x90, 0x99, 0x80, 0x15, 0xf8, 0x18, 0xbd, 0xb3, 0x96, 0xde, - 0x05, 0x63, 0x3e, 0x2c, 0x28, 0xf6, 0x57, 0x2c, 0x89, 0x6f, 0x78, 0x9f, 0xb0, 0x64, 0x37, 0xe9, - 0xf1, 0x7c, 0xae, 0xfe, 0xef, 0x25, 0x78, 0x78, 0xc1, 0x91, 0xd3, 0xbb, 0x06, 0x5e, 0xcc, 0xa3, - 0x5c, 0x49, 0x8b, 0x23, 0x62, 0xcc, 0x50, 0xb1, 0x71, 0x99, 0x88, 0x3e, 0x11, 0x39, 0xd5, 0x97, - 0x22, 0xfa, 0x44, 0xa0, 0x75, 0xf0, 0x06, 0xb2, 0x78, 0xcd, 0x7e, 0xd6, 0xca, 0xbf, 0x4f, 0x47, - 0xdf, 0x39, 0xc6, 0x7b, 0x52, 0xb5, 0x1f, 0x87, 0x5b, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0xea, - 0x22, 0xfb, 0x26, 0x22, 0x0b, 0x00, 0x00, + // 1057 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdd, 0x4e, 0x1b, 0xc7, + 0x17, 0x8f, 0xbd, 0xd8, 0xd8, 0x87, 0xaf, 0xfc, 0x27, 0x04, 0xf6, 0xef, 0x2a, 0x11, 0x5a, 0xd4, + 0x36, 0xad, 0x2a, 0x37, 0x38, 0x82, 0x36, 0xe9, 0x45, 0xd3, 0x24, 0x55, 0x40, 0x80, 0x84, 0x86, + 0x84, 0x5e, 0xae, 0x06, 0x7b, 0xbc, 0x8c, 0x58, 0xef, 0x4c, 0x67, 0x66, 0xad, 0x2c, 0x52, 0xa5, + 0x3e, 0x40, 0xa5, 0x4a, 0x7d, 0x86, 0x3e, 0x43, 0x5f, 0xa0, 0x6f, 0xd1, 0xa7, 0xa9, 0xe6, 0x63, + 0xfd, 0x01, 0x26, 0x84, 0x5c, 0xf4, 0xc6, 0x9e, 0xf3, 0xb5, 0xe7, 0x9c, 0xdf, 0xf9, 0x9d, 0xd9, + 0x85, 0x87, 0xe7, 0xb4, 0xd0, 0x92, 0x64, 0x4a, 0x10, 0x49, 0xb3, 0x6e, 0x11, 0x0f, 0xb7, 0x62, + 0x5d, 0x08, 0xaa, 0xda, 0x42, 0x72, 0xcd, 0x51, 0x78, 0xc9, 0xde, 0x1e, 0x6e, 0xb5, 0xad, 0xbd, + 0xd5, 0xea, 0xca, 0x42, 0x68, 0xfe, 0xf5, 0x39, 0x2d, 0x94, 0x38, 0xf5, 0x7f, 0x2e, 0xaa, 0x15, + 0x7a, 0x9b, 0x62, 0x89, 0x38, 0x75, 0xbf, 0xde, 0xb2, 0xac, 0x25, 0x4b, 0x53, 0x46, 0x32, 0x2f, + 0xaf, 0x95, 0x72, 0x3c, 0x20, 0x22, 0x26, 0x82, 0x39, 0x7d, 0xb4, 0x05, 0xcd, 0x97, 0x7c, 0x30, + 0x60, 0x5a, 0xd3, 0x1e, 0xba, 0x0b, 0xc1, 0x39, 0x2d, 0xc2, 0xca, 0x46, 0xe5, 0xd1, 0x22, 0x36, + 0x47, 0x84, 0x60, 0xae, 0x47, 0x34, 0x09, 0xab, 0x56, 0x65, 0xcf, 0xd1, 0x6f, 0x15, 0x58, 0xf8, + 0x31, 0xd3, 0xb2, 0x78, 0x2b, 0x7a, 0x44, 0x53, 0xf4, 0x0c, 0xea, 0xb9, 0x3d, 0x59, 0xaf, 0x85, + 0x4e, 0xd4, 0xbe, 0xae, 0x97, 0xf6, 0x31, 0x4b, 0x32, 0xda, 0xdb, 0x3f, 0xc1, 0x3e, 0x02, 0xfd, + 0x00, 0xcd, 0x6e, 0x99, 0x3e, 0x0c, 0x6c, 0xf8, 0xe6, 0xf5, 0xe1, 0xa3, 0x4a, 0xf1, 0x38, 0x2a, + 0xca, 0xa1, 0x66, 0xab, 0x41, 0x0f, 0x01, 0x9c, 0x76, 0x40, 0x33, 0xed, 0x9b, 0x98, 0xd0, 0xa0, + 0x03, 0x58, 0x21, 0xb9, 0x3e, 0xe3, 0x92, 0x5d, 0xd0, 0x5e, 0x6c, 0x70, 0x0c, 0xab, 0x1b, 0xc1, + 0xfb, 0x33, 0x1e, 0xe5, 0xa7, 0x29, 0xeb, 0xee, 0xd3, 0x02, 0x2f, 0x8f, 0x63, 0xf7, 0x69, 0xa1, + 0xa2, 0x3f, 0x2b, 0xd0, 0x1c, 0x59, 0x51, 0x0b, 0xe6, 0x69, 0xaf, 0xb3, 0xbd, 0xbd, 0xf5, 0xd4, + 0x25, 0xde, 0xbd, 0x83, 0x4b, 0x05, 0xfa, 0x0e, 0xfe, 0x2f, 0x15, 0x89, 0x87, 0x54, 0xb2, 0x7e, + 0xc1, 0xb2, 0x24, 0x56, 0x67, 0xa4, 0xb3, 0xbd, 0x13, 0x3f, 0x79, 0xfc, 0x4d, 0xc7, 0x01, 0xbb, + 0x7b, 0x07, 0xaf, 0x49, 0x45, 0x4e, 0x4a, 0x8f, 0x63, 0xeb, 0x60, 0xec, 0xa8, 0x03, 0xab, 0xb4, + 0xdb, 0x9b, 0x0a, 0x17, 0x9d, 0xed, 0x1d, 0x8b, 0x95, 0x89, 0x43, 0xd6, 0x3a, 0x8a, 0x3c, 0xea, + 0x6c, 0xef, 0xbc, 0x00, 0x68, 0x9c, 0xd3, 0xc2, 0xd2, 0x2b, 0xea, 0x40, 0x63, 0x9f, 0x16, 0x27, + 0x24, 0xcd, 0xe9, 0x8c, 0xf1, 0xae, 0x42, 0x6d, 0x68, 0x4c, 0x7e, 0xbe, 0x4e, 0x88, 0xfe, 0xa8, + 0x42, 0xa3, 0x9c, 0x14, 0xfa, 0x1e, 0x9a, 0xe6, 0x61, 0xce, 0xad, 0x72, 0xd3, 0x80, 0xcb, 0x5c, + 0xd8, 0x54, 0xe0, 0xb2, 0x62, 0x00, 0xc5, 0x92, 0x8c, 0xe8, 0x5c, 0xd2, 0x12, 0xf1, 0xce, 0xcd, + 0x14, 0xb1, 0x07, 0x17, 0x64, 0xc7, 0x8b, 0x27, 0x9e, 0x82, 0x5a, 0xd0, 0x10, 0x92, 0x0e, 0x19, + 0xcf, 0x95, 0x43, 0x02, 0x8f, 0xe4, 0xd6, 0x5b, 0x58, 0xb9, 0x14, 0x3a, 0xd9, 0x78, 0xd3, 0x35, + 0xfe, 0xd5, 0x64, 0xe3, 0x0b, 0x9d, 0xb5, 0xb6, 0xdb, 0x9d, 0x57, 0x2c, 0x61, 0x9a, 0xa4, 0x69, + 0xe1, 0xaa, 0xf0, 0x80, 0x3c, 0xab, 0x7e, 0x5b, 0x89, 0xde, 0x41, 0xe3, 0x30, 0xd7, 0x44, 0x33, + 0x9e, 0x4d, 0x30, 0xbe, 0x72, 0x6b, 0xc6, 0x3f, 0x86, 0x9a, 0x90, 0x9c, 0xf7, 0x7d, 0xe6, 0x56, + 0x7b, 0xb4, 0xa8, 0x87, 0x44, 0x1c, 0x50, 0xd2, 0xdf, 0xcb, 0xba, 0x69, 0xae, 0x18, 0xcf, 0xb0, + 0x73, 0x8c, 0x18, 0xac, 0xbc, 0xa6, 0xda, 0x81, 0x40, 0x7f, 0xce, 0xa9, 0xd2, 0x68, 0x1d, 0xe6, + 0x73, 0x45, 0x65, 0xcc, 0x7a, 0xbe, 0xa9, 0xba, 0x11, 0xf7, 0x7a, 0xe8, 0x3e, 0xd4, 0x89, 0x10, + 0x46, 0x5f, 0xb5, 0xfa, 0x1a, 0x11, 0x62, 0xaf, 0x87, 0x3e, 0x83, 0x95, 0x3e, 0x93, 0x4a, 0xc7, + 0x5a, 0x52, 0x1a, 0x2b, 0x76, 0x41, 0x2d, 0x6c, 0x01, 0x5e, 0xb2, 0xea, 0x37, 0x92, 0xd2, 0x63, + 0x76, 0x41, 0xa3, 0x7f, 0xaa, 0x70, 0x77, 0x9c, 0x4b, 0x09, 0x9e, 0x29, 0x8a, 0x3e, 0x81, 0xe6, + 0x50, 0xf6, 0x63, 0x57, 0xb5, 0x23, 0x4f, 0x63, 0x28, 0xfb, 0x47, 0x46, 0x9e, 0x5e, 0xe0, 0xea, + 0xc7, 0x2c, 0x30, 0x7a, 0x0a, 0x90, 0x52, 0x52, 0x26, 0x08, 0x6e, 0x84, 0xa5, 0x69, 0xbc, 0x5d, + 0xf6, 0x2f, 0x20, 0x50, 0x03, 0x19, 0xce, 0xd9, 0x98, 0xf5, 0x71, 0x8c, 0x43, 0xfd, 0x90, 0x08, + 0xcc, 0xb9, 0xc6, 0xc6, 0x07, 0x75, 0xa0, 0x91, 0xf2, 0x24, 0x96, 0x9c, 0xeb, 0xb0, 0x36, 0xdb, + 0xff, 0x80, 0x27, 0xd6, 0x7f, 0x3e, 0x75, 0x07, 0xf4, 0x39, 0xac, 0x98, 0x98, 0x2e, 0xcf, 0x14, + 0x53, 0xda, 0xb4, 0x12, 0xd6, 0x37, 0x82, 0x47, 0x8b, 0x78, 0x39, 0xe5, 0xc9, 0xcb, 0xb1, 0x16, + 0x6d, 0xc2, 0x92, 0x71, 0x64, 0x65, 0x8d, 0xe1, 0xbc, 0x75, 0x5b, 0x4c, 0x79, 0x32, 0xaa, 0xdb, + 0xdc, 0x18, 0xeb, 0x07, 0x4c, 0x39, 0x74, 0x77, 0x99, 0xd2, 0xfc, 0x03, 0x06, 0xba, 0x0a, 0x35, + 0xa5, 0x89, 0xd4, 0x16, 0xdb, 0x00, 0x3b, 0xc1, 0x8c, 0x44, 0x90, 0x64, 0x62, 0x92, 0x35, 0xdc, + 0x30, 0x0a, 0x33, 0xc4, 0x09, 0x0e, 0xcc, 0xdd, 0xc0, 0x81, 0xda, 0x2c, 0x0e, 0xfc, 0x02, 0xe1, + 0xd5, 0x2a, 0x3d, 0x15, 0x5e, 0x40, 0xdd, 0x6e, 0x84, 0x0a, 0x2b, 0x76, 0x8f, 0xbf, 0xbc, 0x7e, + 0xd4, 0x97, 0x69, 0x84, 0x7d, 0x24, 0x7a, 0x00, 0x90, 0xd1, 0x77, 0x3a, 0x9e, 0x6c, 0xab, 0x69, + 0x34, 0xc7, 0x46, 0x11, 0xfd, 0x55, 0x01, 0xe4, 0x5e, 0x2c, 0xff, 0x05, 0xe3, 0xd1, 0x2e, 0x2c, + 0x52, 0x93, 0x27, 0xf6, 0x0b, 0xed, 0xa8, 0xf4, 0xe9, 0xf5, 0x7d, 0x4d, 0xbc, 0xf9, 0xf0, 0x02, + 0x1d, 0x0b, 0xd1, 0x4f, 0x70, 0x6f, 0xaa, 0x6e, 0x0f, 0xd9, 0xf3, 0x72, 0xdf, 0xdd, 0x55, 0x71, + 0x1b, 0xc4, 0xfc, 0xfe, 0xff, 0x5e, 0x81, 0x7b, 0xaf, 0xa9, 0x2e, 0x6f, 0x1f, 0x55, 0x42, 0xb2, + 0x0a, 0x35, 0x2a, 0x78, 0xf7, 0xcc, 0x3e, 0x39, 0xc0, 0x4e, 0x98, 0xd5, 0x78, 0x75, 0x56, 0xe3, + 0x0f, 0x00, 0x2c, 0x85, 0x34, 0x3f, 0xa7, 0x99, 0xc5, 0xa6, 0x89, 0x2d, 0xa9, 0xde, 0x18, 0xc5, + 0x34, 0xc3, 0xe6, 0xa6, 0x19, 0x16, 0xfd, 0x5d, 0x85, 0xd5, 0xe9, 0x8a, 0x7c, 0xb3, 0xb3, 0x4b, + 0xf2, 0x5b, 0x5a, 0xbd, 0xe5, 0x96, 0x06, 0x1f, 0xbf, 0xa5, 0x73, 0x1f, 0xb6, 0xa5, 0xb5, 0xab, + 0x5b, 0x8a, 0x9e, 0x43, 0x73, 0x50, 0xf6, 0x65, 0xb7, 0xfd, 0xbd, 0xd7, 0x7b, 0x09, 0x01, 0x1e, + 0x07, 0x99, 0x09, 0x58, 0x82, 0x4f, 0xc0, 0x3b, 0x6f, 0xe1, 0x5d, 0x32, 0xea, 0xa3, 0x12, 0xe2, + 0x68, 0xcd, 0x82, 0xf8, 0x8a, 0x0f, 0x08, 0xcb, 0xf6, 0xb2, 0x3e, 0xf7, 0x73, 0x8d, 0x7e, 0xad, + 0xc0, 0xfd, 0x4b, 0x06, 0x0f, 0xef, 0x06, 0x04, 0x29, 0x4f, 0x3c, 0x93, 0x96, 0xc7, 0xc0, 0x98, + 0xa1, 0x62, 0x63, 0x32, 0x1e, 0x03, 0x22, 0x3c, 0xd4, 0x57, 0x3c, 0x06, 0x44, 0xa0, 0x4d, 0x08, + 0x86, 0xb2, 0xbc, 0x66, 0xff, 0xd7, 0xf6, 0x9f, 0x93, 0xe3, 0xef, 0x1c, 0x63, 0x3d, 0xad, 0xdb, + 0x8f, 0xc3, 0x27, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x87, 0x52, 0x53, 0x62, 0xb6, 0x0a, 0x00, + 0x00, } diff --git a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto index 3b8a038ee..0ab220e7d 100644 --- a/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto +++ b/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto @@ -21,10 +21,10 @@ syntax = "proto3"; // associated with it. package keytransparency.v1.types; -import "github.com/google/trillian/crypto/keyspb/keyspb.proto"; -import "github.com/google/trillian/crypto/sigpb/sigpb.proto"; -import "github.com/google/trillian/trillian.proto"; -import "github.com/google/trillian/trillian_map_api.proto"; +import "crypto/keyspb/keyspb.proto"; +import "crypto/sigpb/sigpb.proto"; +import "trillian.proto"; +import "trillian_map_api.proto"; // // Data types. From 6f75fda733433c23882e53fa0d2659030163c745 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 16:41:21 -0400 Subject: [PATCH 23/46] obsolete change to mutation service proto's gen.go --- impl/proto/mutation_v1_service/gen.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/impl/proto/mutation_v1_service/gen.go b/impl/proto/mutation_v1_service/gen.go index 6d15ee54e..4816f1586 100644 --- a/impl/proto/mutation_v1_service/gen.go +++ b/impl/proto/mutation_v1_service/gen.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --go_out=,plugins=grpc:. mutation_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --go_out=,plugins=grpc:. mutation_v1_service.proto -//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ --grpc-gateway_out=logtostderr=true:. mutation_v1_service.proto +//go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis/ --grpc-gateway_out=logtostderr=true:. mutation_v1_service.proto package mutation_v1_service From d2aaf7df9f0371ca33d3257ae2e71dff501a2bc3 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 18:19:23 -0400 Subject: [PATCH 24/46] Use "autoconfig" from domain info, split transportCreds --- cmd/keytransparency-monitor/main.go | 117 +++++++++++++++++++++++----- core/monitor/verify.go | 2 +- impl/monitor/monitor.go | 5 +- 3 files changed, 99 insertions(+), 25 deletions(-) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index b230c0c7f..179fa167a 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -15,7 +15,9 @@ package main import ( + "crypto/tls" "flag" + "fmt" "net" "net/http" "strings" @@ -23,15 +25,20 @@ import ( "github.com/golang/glog" "github.com/google/keytransparency/impl/monitor" + "github.com/google/trillian" "github.com/google/trillian/crypto" + "github.com/google/trillian/crypto/keys/der" "github.com/google/trillian/crypto/keys/pem" "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" "golang.org/x/net/context" + "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" + kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" ) @@ -41,15 +48,17 @@ var ( keyFile = flag.String("tls-key", "genfiles/server.key", "TLS private key file") certFile = flag.String("tls-cert", "genfiles/server.pem", "TLS cert file") + autoConfig = flag.Bool("autoconfig", true, "Fetch config info from the server's /v1/domain/info") + mapKey = flag.String("map-key", "genfiles/map-rpc-server.pubkey.pem", "Path to public key PEM used to verify the SMH signature") + logKey = flag.String("log-key", "genfiles/log-rpc-server.pubkey.pem", "Path to public key PEM used to verify the STH signature") + signingKey = flag.String("sign-key", "genfiles/monitor_sign-key.pem", "Path to private key PEM for SMH signing") signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") + ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") + insecure = flag.Bool("insecure", false, "Skip TLS checks") + ktCert = flag.String("kt-cert", "genfiles/server.crt", "Path to kt-server's public key") pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") - ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") - ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") - - mapKey = flag.String("map-key", "genfiles/map-rpc-server.pubkey.pem", "Path to public key PEM used to verify the SMH signature") - logKey = flag.String("log-key", "genfiles/log-rpc-server.pubkey.pem", "Path to public key PEM used to verify the STH signature") // TODO(ismail): expose prometheus metrics: a variable that tracks valid/invalid MHs metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") @@ -100,7 +109,7 @@ func main() { ) // Connect to the kt-server's mutation API: - grpcc, err := dial(*ktURL, *ktPEM) + grpcc, err := dial(*ktURL) if err != nil { glog.Fatalf("Error Dialing %v: %v", ktURL, err) } @@ -111,8 +120,13 @@ func main() { if err != nil { glog.Fatalf("Could not create signer from %v: %v", *signingKey, err) } + ctx := context.Background() + logTree, mapTree, err := getTrees(ctx, grpcc) + if err != nil { + glog.Fatalf("Could not read domain info %v:", err) + } - srv := monitor.New(mcc, crypto.NewSHA256Signer(key), *mapKey, *logKey, *pollPeriod) + srv := monitor.New(mcc, crypto.NewSHA256Signer(key), logTree, mapTree, *pollPeriod) mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) @@ -143,24 +157,14 @@ func main() { } } -func dial(ktURL, caFile string) (*grpc.ClientConn, error) { +func dial(ktURL string) (*grpc.ClientConn, error) { var opts []grpc.DialOption - host, _, err := net.SplitHostPort(ktURL) + + transportCreds, err := transportCreds(ktURL, *ktCert, *insecure) if err != nil { return nil, err } - var creds credentials.TransportCredentials - if caFile != "" { - var err error - creds, err = credentials.NewClientTLSFromFile(caFile, host) - if err != nil { - return nil, err - } - } else { - // Use the local set of root certs. - creds = credentials.NewClientTLSFromCert(nil, host) - } - opts = append(opts, grpc.WithTransportCredentials(creds)) + opts = append(opts, grpc.WithTransportCredentials(transportCreds)) // TODO(ismail): authenticate the monitor to the kt-server: cc, err := grpc.Dial(ktURL, opts...) @@ -169,3 +173,74 @@ func dial(ktURL, caFile string) (*grpc.ClientConn, error) { } return cc, nil } + +// TODO(ismail): refactor client and monitor to use the same methods +func transportCreds(ktURL string, ktCert string, insecure bool) (credentials.TransportCredentials, error) { + // copied from keytransparency-client/cmd/root.go: transportCreds + host, _, err := net.SplitHostPort(ktURL) + if err != nil { + return nil, err + } + + switch { + case insecure: // Impatient insecure. + return credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + }), nil + + case ktCert != "": // Custom CA Cert. + return credentials.NewClientTLSFromFile(ktCert, host) + + default: // Use the local set of root certs. + return credentials.NewClientTLSFromCert(nil, host), nil + } +} + +// config selects a source for and returns the client configuration. +func getTrees(ctx context.Context, cc *grpc.ClientConn) (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { + switch { + case *autoConfig: + ktClient := spb.NewKeyTransparencyServiceClient(cc) + resp, err2 := ktClient.GetDomainInfo(ctx, &kpb.GetDomainInfoRequest{}) + if err2 != nil { + err = err2 + return + } + logTree = resp.GetLog() + mapTree = resp.GetMap() + return + default: + return readConfigFromDisk() + } +} + +func readConfigFromDisk() (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { + // Log PubKey. + logPubKey, err := pem.ReadPublicKeyFile(*logKey) + if err != nil { + return nil, nil, fmt.Errorf("Failed to open log public key %v: %v", *logKey, err) + } + logPubPB, err := der.ToPublicProto(logPubKey) + if err != nil { + return nil, nil, fmt.Errorf("failed to serialize log public key: %v", err) + } + + // MapPubKey. + mapPubKey, err := pem.ReadPublicKeyFile(*mapKey) + if err != nil { + return nil, nil, fmt.Errorf("error reading map public key %v: %v", *mapKey, err) + } + mapPubPB, err := der.ToPublicProto(mapPubKey) + if err != nil { + return nil, nil, fmt.Errorf("error seralizeing map public key: %v", err) + } + logTree = &trillian.Tree{ + HashStrategy: trillian.HashStrategy_OBJECT_RFC6962_SHA256, + PublicKey: logPubPB, + } + mapTree = &trillian.Tree{ + HashStrategy: trillian.HashStrategy_CONIKS_SHA512_256, + PublicKey: mapPubPB, + } + return +} diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 087686584..c3d057a85 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -67,7 +67,7 @@ func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb. resp.InvalidMapSigProof = in.GetSmr() } - logRoot := in.GetLogRoot() + logRoot := in.GetLogRoot() // Verify SignedLogRoot signature. hash := tcrypto.HashLogRoot(*logRoot) if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go index 5e3266b2c..d33943c15 100644 --- a/impl/monitor/monitor.go +++ b/impl/monitor/monitor.go @@ -20,7 +20,6 @@ package monitor import ( "bytes" - "crypto" "errors" "time" @@ -64,13 +63,13 @@ type Server struct { // New creates a new instance of the monitor server. func New(cli mupb.MutationServiceClient, signer *tcrypto.Signer, - logPubKey, mapPubKey crypto.PublicKey, + logTree, mapTree *trillian.Tree, poll time.Duration) *Server { return &Server{ client: cli, pollPeriod: poll, // TODO(ismail) use domain info to properly init. the monitor: - monitor: &cmon.Monitor{}, + monitor: &cmon.Monitor{}, signer: signer, proccessedSMRs: make([]*mopb.GetMonitoringResponse, 256), } From e487368553985a1f781189c896299902dc069b7e Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 18:22:37 -0400 Subject: [PATCH 25/46] remove libtool dependency from monitor dockerfile --- cmd/keytransparency-monitor/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/keytransparency-monitor/Dockerfile b/cmd/keytransparency-monitor/Dockerfile index 691703340..bbd0dc8ad 100644 --- a/cmd/keytransparency-monitor/Dockerfile +++ b/cmd/keytransparency-monitor/Dockerfile @@ -5,9 +5,6 @@ ADD ./keytransparency /go/src/github.com/google/keytransparency ADD ./trillian /go/src/github.com/google/trillian WORKDIR /go/src/github.com/google/keytransparency -RUN apt-get update && apt-get install -y libtool libltdl-dev -RUN go get -tags="mysql" ./cmd/keytransparency-monitor - ENTRYPOINT ["/go/bin/keytransparency-monitor"] EXPOSE 8099 From ac156ea445cd11e49e0e9a6476c465237d7e943b Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 18:32:34 -0400 Subject: [PATCH 26/46] remove verification logic completely --- core/monitor/verify.go | 125 +----------------------------------- core/monitor/verify_test.go | 8 +-- 2 files changed, 4 insertions(+), 129 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index c3d057a85..c6590bfc3 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -18,32 +18,11 @@ package monitor import ( - "bytes" - "errors" - "fmt" - "math/big" - "github.com/golang/glog" - - "github.com/google/trillian/merkle" - "github.com/google/trillian/merkle/coniks" - "github.com/google/trillian/storage" - - tcrypto "github.com/google/trillian/crypto" + "time" - "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" - "time" -) - -var ( - // ErrInvalidMutation occurs when verification failed because of an invalid - // mutation. - ErrInvalidMutation = errors.New("invalid mutation") - // ErrNotMatchingRoot occurs when the reconstructed root differs from the one - // we received from the server. - ErrNotMatchingRoot = errors.New("recreated root does not match") ) // verifyResponse verifies a response received by the GetMutations API. @@ -58,108 +37,8 @@ func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb. // copy of received SMR: smr := *in.Smr resp.Smr = &smr - // reset map + // reset map's signature resp.Smr.Signature = nil - // verify signature on map root: - if err := tcrypto.VerifyObject(m.mapPubKey, resp.Smr, in.GetSmr().GetSignature()); err != nil { - glog.Errorf("couldn't verify signature on map root: %v", err) - resp.InvalidMapSigProof = in.GetSmr() - } - - logRoot := in.GetLogRoot() - // Verify SignedLogRoot signature. - hash := tcrypto.HashLogRoot(*logRoot) - if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { - resp.InvalidLogSigProof = logRoot - } - - // Implicitly trust the first root we get. - if m.trusted.TreeSize != 0 { - // Verify consistency proof. - if err := m.logVerifier.VerifyConsistencyProof( - m.trusted.TreeSize, logRoot.TreeSize, - m.trusted.RootHash, logRoot.RootHash, - in.GetLogConsistency()); err != nil { - // TODO - } - } - - // TODO: - // logVerifier.VerifyInclusionProof() - - if err := m.verifyMutations(allMuts, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); err != nil { - // TODO resp.InvalidMutation - } - return resp } - -func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, expectedRoot []byte, mapID int64) error { - newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) - mutator := entry.New() - oldProofNodes := make(map[string][]byte) - hasher := coniks.Default - - for _, m := range muts { - // verify that the provided leaf’s inclusion proof goes to epoch e-1: - //if err := merkle.VerifyMapInclusionProof(mapID, index, - // leafHash, rootHash, proof, hasher); err != nil { - // glog.Errorf("VerifyMapInclusionProof(%x): %v", index, err) - // // TODO modify response object - //} - oldLeaf, err := entry.FromLeafValue(m.GetProof().GetLeaf().GetLeafValue()) - if err != nil { - return ErrInvalidMutation - } - - // compute the new leaf - newLeaf, err := mutator.Mutate(oldLeaf, m.GetUpdate()) - if err != nil { - // TODO(ismail): collect all data to reproduce this (expectedRoot, oldLeaf, and mutation) - return ErrInvalidMutation - } - index := m.GetProof().GetLeaf().GetIndex() - newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, hasher.BitLen()) - newLeafHash := hasher.HashLeaf(mapID, index, newLeaf) - newLeaves = append(newLeaves, merkle.HStar2LeafHash{ - Index: newLeafnID.BigInt(), - LeafHash: newLeafHash, - }) - // store the proof hashes locally to recompute the tree below: - sibIDs := newLeafnID.Siblings() - for level, proof := range m.GetProof().GetInclusion() { - pID := sibIDs[level] - if p, ok := oldProofNodes[pID.String()]; ok { - // sanity check: for each mutation overlapping proof nodes should be - // equal: - if !bytes.Equal(p, proof) { - // TODO: this is really odd -> monitor should complain! - } - } else { - oldProofNodes[pID.String()] = proof - } - } - } - - // compute the new root using local intermediate hashes from epoch e - // (above proof hashes): - hs2 := merkle.NewHStar2(mapID, hasher) - newRoot, err := hs2.HStar2Nodes([]byte{}, hasher.Size(), newLeaves, - func(depth int, index *big.Int) ([]byte, error) { - nID := storage.NewNodeIDFromBigInt(depth, index, hasher.BitLen()) - if p, ok := oldProofNodes[nID.String()]; ok { - return p, nil - } - return nil, nil - }, nil) - if err != nil { - glog.Errorf("hs2.HStar2Nodes(_): %v", err) - fmt.Errorf("could not compute new root hash: hs2.HStar2Nodes(_): %v", err) - } - // verify rootHash - if !bytes.Equal(newRoot, expectedRoot) { - return ErrNotMatchingRoot - } - return nil -} diff --git a/core/monitor/verify_test.go b/core/monitor/verify_test.go index 7174c0851..24483a9da 100644 --- a/core/monitor/verify_test.go +++ b/core/monitor/verify_test.go @@ -14,9 +14,5 @@ package monitor -// TODO(ismail): write extensive tests for verification steps (if not existing -// in trillian) -const ( - emptyMapRootB64 = "xmifEIEqCYCXbZUz2Dh1KCFmFZVn7DUVVxbBQTr1PWo=" - mapID = int64(0) -) +// TODO(ismail): write extensive tests for verification steps, where necessary +// tests should go into integration tests \ No newline at end of file From 9a5e2f91c7e638ffbc53da45838a447e1b41df7a Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 18:44:59 -0400 Subject: [PATCH 27/46] remove everything from proto which is not needed by a non-verifying monitor --- .../monitor_v1_types/monitor_v1_types.pb.go | 159 ++---------------- .../monitor_v1_types/monitor_v1_types.proto | 41 +---- 2 files changed, 17 insertions(+), 183 deletions(-) diff --git a/core/proto/monitor_v1_types/monitor_v1_types.pb.go b/core/proto/monitor_v1_types/monitor_v1_types.pb.go index 6301d6f0a..d0fe0b1a2 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.pb.go +++ b/core/proto/monitor_v1_types/monitor_v1_types.pb.go @@ -12,8 +12,6 @@ It is generated from these files: It has these top-level messages: GetMonitoringRequest - InvalidMutation - NotMatchingMapRootProof GetMonitoringResponse */ package monitor_v1_types @@ -22,7 +20,6 @@ import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import trillian "github.com/google/trillian" -import trillian1 "github.com/google/trillian" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal @@ -54,73 +51,6 @@ func (m *GetMonitoringRequest) GetStart() int64 { return 0 } -// InvalidMutation includes all information to reproduce that there was an -// invalid mutation from epoch e to e+1. -type InvalidMutation struct { - // old_leaf is the inclusion proof to the leaf at epoch e. - OldLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,1,opt,name=old_leaf,json=oldLeaf" json:"old_leaf,omitempty"` - // new_leaf is the inclusion proof to the leaf at epoch e+1. - NewLeaf *trillian1.MapLeafInclusion `protobuf:"bytes,2,opt,name=new_leaf,json=newLeaf" json:"new_leaf,omitempty"` -} - -func (m *InvalidMutation) Reset() { *m = InvalidMutation{} } -func (m *InvalidMutation) String() string { return proto.CompactTextString(m) } -func (*InvalidMutation) ProtoMessage() {} -func (*InvalidMutation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -func (m *InvalidMutation) GetOldLeaf() *trillian1.MapLeafInclusion { - if m != nil { - return m.OldLeaf - } - return nil -} - -func (m *InvalidMutation) GetNewLeaf() *trillian1.MapLeafInclusion { - if m != nil { - return m.NewLeaf - } - return nil -} - -// NotMatchingMapRootProof contains all data necessary to reproduce that set of -// mutations does not produce new expected map root. -type NotMatchingMapRootProof struct { - // map_root contains the map root hash the monitor observed. - MapRoot *trillian.SignedMapRoot `protobuf:"bytes,1,opt,name=map_root,json=mapRoot" json:"map_root,omitempty"` - // old_leafs is a list of inclusion proofs for the leafs in epoch e. - OldLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,2,rep,name=old_leafs,json=oldLeafs" json:"old_leafs,omitempty"` - // new_leafs is a list of inclusion proofs for changed leafs (from epoch e - // to epoch e+1). Hashing these produces a different hash than root hash in - // above's map_root. - NewLeafs []*trillian1.MapLeafInclusion `protobuf:"bytes,3,rep,name=new_leafs,json=newLeafs" json:"new_leafs,omitempty"` -} - -func (m *NotMatchingMapRootProof) Reset() { *m = NotMatchingMapRootProof{} } -func (m *NotMatchingMapRootProof) String() string { return proto.CompactTextString(m) } -func (*NotMatchingMapRootProof) ProtoMessage() {} -func (*NotMatchingMapRootProof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *NotMatchingMapRootProof) GetMapRoot() *trillian.SignedMapRoot { - if m != nil { - return m.MapRoot - } - return nil -} - -func (m *NotMatchingMapRootProof) GetOldLeafs() []*trillian1.MapLeafInclusion { - if m != nil { - return m.OldLeafs - } - return nil -} - -func (m *NotMatchingMapRootProof) GetNewLeafs() []*trillian1.MapLeafInclusion { - if m != nil { - return m.NewLeafs - } - return nil -} - type GetMonitoringResponse struct { // smr contains the map root for the sparse Merkle Tree signed with the // monitor's key on success. If the checks were not successful the @@ -133,26 +63,12 @@ type GetMonitoringResponse struct { // isValid signals if all verification steps for the requested epoch passed // or not. IsValid bool `protobuf:"varint,3,opt,name=isValid" json:"isValid,omitempty"` - // invalidMapSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - InvalidMapSigProof *trillian.SignedMapRoot `protobuf:"bytes,4,opt,name=invalidMapSigProof" json:"invalidMapSigProof,omitempty"` - // invalidLogSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - InvalidLogSigProof *trillian.SignedLogRoot `protobuf:"bytes,5,opt,name=invalidLogSigProof" json:"invalidLogSigProof,omitempty"` - // invalidMutation contains data to reproduce that there was an invalid - // mutation from epoch e to epoch e+1 - InvalidMutation *InvalidMutation `protobuf:"bytes,6,opt,name=invalidMutation" json:"invalidMutation,omitempty"` - // NotMatchingMapRoot contains all data to reproduce that the set of mutations - // does not produce observed new map root. - NotMatchingMapRoot *NotMatchingMapRootProof `protobuf:"bytes,7,opt,name=notMatchingMapRoot" json:"notMatchingMapRoot,omitempty"` } func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } func (m *GetMonitoringResponse) String() string { return proto.CompactTextString(m) } func (*GetMonitoringResponse) ProtoMessage() {} -func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*GetMonitoringResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *GetMonitoringResponse) GetSmr() *trillian.SignedMapRoot { if m != nil { @@ -175,71 +91,26 @@ func (m *GetMonitoringResponse) GetIsValid() bool { return false } -func (m *GetMonitoringResponse) GetInvalidMapSigProof() *trillian.SignedMapRoot { - if m != nil { - return m.InvalidMapSigProof - } - return nil -} - -func (m *GetMonitoringResponse) GetInvalidLogSigProof() *trillian.SignedLogRoot { - if m != nil { - return m.InvalidLogSigProof - } - return nil -} - -func (m *GetMonitoringResponse) GetInvalidMutation() *InvalidMutation { - if m != nil { - return m.InvalidMutation - } - return nil -} - -func (m *GetMonitoringResponse) GetNotMatchingMapRoot() *NotMatchingMapRootProof { - if m != nil { - return m.NotMatchingMapRoot - } - return nil -} - func init() { proto.RegisterType((*GetMonitoringRequest)(nil), "monitor.v1.types.GetMonitoringRequest") - proto.RegisterType((*InvalidMutation)(nil), "monitor.v1.types.InvalidMutation") - proto.RegisterType((*NotMatchingMapRootProof)(nil), "monitor.v1.types.NotMatchingMapRootProof") proto.RegisterType((*GetMonitoringResponse)(nil), "monitor.v1.types.GetMonitoringResponse") } func init() { proto.RegisterFile("monitor_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 437 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xc1, 0x6e, 0x13, 0x31, - 0x10, 0x86, 0x95, 0x2e, 0x6d, 0x82, 0x39, 0x14, 0x59, 0x81, 0xae, 0x72, 0x0a, 0x39, 0x35, 0x12, - 0xda, 0x92, 0x22, 0xc4, 0x23, 0x54, 0x15, 0xd9, 0x0a, 0xb9, 0x08, 0x89, 0xd3, 0xca, 0x4d, 0x1c, - 0x77, 0x24, 0xef, 0x8c, 0x59, 0x4f, 0x52, 0x71, 0xe2, 0xd1, 0xb8, 0xf2, 0x58, 0xc8, 0xbb, 0x9b, - 0xd0, 0xa6, 0x81, 0xf4, 0x66, 0xcf, 0xcc, 0xf7, 0xfb, 0xf7, 0x78, 0x2c, 0x5e, 0x97, 0x84, 0xc0, - 0x54, 0x15, 0xab, 0x49, 0xc1, 0x3f, 0xbc, 0x09, 0x99, 0xaf, 0x88, 0x49, 0xbe, 0x6c, 0xe3, 0xd9, - 0x6a, 0x92, 0xd5, 0xf1, 0xc1, 0xd8, 0x02, 0xdf, 0x2e, 0x6f, 0xb2, 0x19, 0x95, 0x67, 0x96, 0xc8, - 0x3a, 0x73, 0xc6, 0x15, 0x38, 0x07, 0x1a, 0x37, 0x8b, 0x06, 0x1e, 0x4c, 0x9e, 0x50, 0x5a, 0x94, - 0xda, 0x17, 0xda, 0x43, 0x83, 0x8c, 0xde, 0x8a, 0xfe, 0x85, 0xe1, 0xbc, 0x39, 0x14, 0xd0, 0x2a, - 0xf3, 0x7d, 0x69, 0x02, 0xcb, 0xbe, 0x38, 0x0c, 0xac, 0x2b, 0x4e, 0x3b, 0xc3, 0xce, 0x69, 0xa2, - 0x9a, 0xcd, 0xe8, 0xa7, 0x38, 0xbe, 0xc4, 0x95, 0x76, 0x30, 0xcf, 0x97, 0xac, 0x19, 0x08, 0xe5, - 0x07, 0xd1, 0x23, 0x37, 0x2f, 0x9c, 0xd1, 0x8b, 0xba, 0xf6, 0xc5, 0xf9, 0x20, 0xdb, 0xd8, 0xca, - 0xb5, 0x9f, 0x1a, 0xbd, 0xb8, 0xc4, 0x99, 0x5b, 0x06, 0x20, 0x54, 0x5d, 0x72, 0xf3, 0x18, 0x89, - 0x18, 0x9a, 0xbb, 0x06, 0x3b, 0xd8, 0x8f, 0xa1, 0xb9, 0x8b, 0x91, 0xd1, 0xaf, 0x8e, 0x38, 0xb9, - 0x22, 0xce, 0x35, 0xcf, 0x6e, 0x01, 0x6d, 0xae, 0xbd, 0x22, 0xe2, 0xcf, 0x15, 0xd1, 0x42, 0x9e, - 0x8b, 0x5e, 0xbc, 0x5b, 0x45, 0xc4, 0xad, 0x93, 0x93, 0xbf, 0x92, 0xd7, 0x60, 0xd1, 0xcc, 0xdb, - 0x7a, 0xd5, 0x2d, 0x9b, 0x85, 0xfc, 0x28, 0x9e, 0xaf, 0xdd, 0x87, 0xf4, 0x60, 0x98, 0xec, 0xf1, - 0xd1, 0x6b, 0xed, 0x87, 0x08, 0xae, 0xfd, 0x87, 0x34, 0xd9, 0x0f, 0xb6, 0x17, 0x08, 0xa3, 0xdf, - 0x89, 0x78, 0xb5, 0xd5, 0xf1, 0xe0, 0x09, 0x83, 0x91, 0x63, 0x91, 0x84, 0xb2, 0xda, 0x67, 0x3d, - 0xd6, 0xc8, 0x77, 0xa2, 0x1f, 0x8c, 0xc1, 0x82, 0xa1, 0x34, 0x81, 0x75, 0xe9, 0x0b, 0xd4, 0x48, - 0xa1, 0xee, 0x64, 0xa2, 0x64, 0xcc, 0x7d, 0x59, 0xa7, 0xae, 0x62, 0x46, 0xa6, 0xa2, 0x0b, 0xe1, - 0x6b, 0x7c, 0xb9, 0x34, 0x19, 0x76, 0x4e, 0x7b, 0x6a, 0xbd, 0x95, 0x17, 0x42, 0x42, 0xfb, 0xa6, - 0xda, 0x5f, 0x83, 0xad, 0x9b, 0x99, 0x3e, 0xfb, 0xbf, 0x8b, 0x1d, 0xc8, 0x3d, 0xa1, 0x29, 0xd9, - 0x8d, 0xd0, 0xe1, 0x6e, 0xa1, 0x29, 0xd9, 0x07, 0x42, 0xf7, 0x10, 0xf9, 0x49, 0x1c, 0xc3, 0xc3, - 0x29, 0x4b, 0x8f, 0x6a, 0x95, 0x37, 0xd9, 0xf6, 0xef, 0xc8, 0xb6, 0xc6, 0x51, 0x6d, 0x93, 0xf2, - 0x9b, 0x90, 0xf8, 0x68, 0x60, 0xd2, 0x6e, 0xad, 0x37, 0x7e, 0xac, 0xf7, 0x8f, 0xe1, 0x52, 0x3b, - 0x44, 0x6e, 0x8e, 0xea, 0x2f, 0xf4, 0xfe, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdb, 0xda, 0xc5, - 0xc2, 0xcc, 0x03, 0x00, 0x00, + // 208 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x8f, 0xcd, 0x4a, 0x04, 0x31, + 0x10, 0x84, 0x19, 0x07, 0x7f, 0x88, 0x20, 0x12, 0x46, 0x1d, 0x3c, 0x2d, 0x7b, 0x5a, 0x41, 0x82, + 0xab, 0x0f, 0xe1, 0x69, 0x3d, 0x44, 0xf1, 0x1a, 0x22, 0xdb, 0x2c, 0x0d, 0x93, 0xee, 0x98, 0x6e, + 0x17, 0x7c, 0x09, 0x9f, 0x59, 0x26, 0xe3, 0x78, 0xd8, 0x63, 0xd5, 0xf7, 0x41, 0x51, 0xe6, 0x3a, + 0x31, 0xa1, 0x72, 0x09, 0xfb, 0x75, 0xd0, 0xef, 0x0c, 0xe2, 0x72, 0x61, 0x65, 0x7b, 0xf9, 0xd7, + 0xbb, 0xfd, 0xda, 0xd5, 0xfe, 0xf6, 0x42, 0x0b, 0x0e, 0x03, 0x46, 0x9a, 0x8c, 0xe5, 0xbd, 0xe9, + 0x9e, 0x41, 0x37, 0x93, 0x86, 0xb4, 0xf3, 0xf0, 0xf9, 0x05, 0xa2, 0xb6, 0x33, 0xc7, 0xa2, 0xb1, + 0x68, 0xdf, 0x2c, 0x9a, 0x55, 0xeb, 0xa7, 0xb0, 0xfc, 0x69, 0xcc, 0xd5, 0x81, 0x2e, 0x99, 0x49, + 0xc0, 0xde, 0x99, 0x56, 0x52, 0xa9, 0xf6, 0xf9, 0xe3, 0x8d, 0xfb, 0x5f, 0x79, 0xc5, 0x1d, 0xc1, + 0x76, 0x13, 0xb3, 0x67, 0x56, 0x3f, 0x3a, 0xf6, 0xc1, 0x74, 0x02, 0x40, 0x41, 0x31, 0x81, 0x68, + 0x4c, 0x39, 0x50, 0x24, 0x96, 0xfe, 0xa8, 0x2e, 0xd9, 0x91, 0xbd, 0xcd, 0xe8, 0x65, 0x24, 0xb6, + 0x37, 0xa7, 0x28, 0xef, 0x71, 0xc0, 0x6d, 0xdf, 0x2e, 0x9a, 0xd5, 0x99, 0x9f, 0xe3, 0xc7, 0x49, + 0x7d, 0xf1, 0xf4, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x8c, 0xe2, 0xa7, 0x01, 0x01, 0x00, 0x00, } diff --git a/core/proto/monitor_v1_types/monitor_v1_types.proto b/core/proto/monitor_v1_types/monitor_v1_types.proto index 16e0e4bbe..79f1b5697 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.proto +++ b/core/proto/monitor_v1_types/monitor_v1_types.proto @@ -18,8 +18,7 @@ syntax = "proto3"; // package monitor.v1.types; -import "github.com/google/trillian/trillian.proto"; -import "github.com/google/trillian/trillian_map_api.proto"; +import "trillian.proto"; // GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. message GetMonitoringRequest { @@ -28,28 +27,6 @@ message GetMonitoringRequest { int64 start = 1; } -// InvalidMutation includes all information to reproduce that there was an -// invalid mutation from epoch e to e+1. -message InvalidMutation { - // old_leaf is the inclusion proof to the leaf at epoch e. - trillian.MapLeafInclusion old_leaf = 1; - // new_leaf is the inclusion proof to the leaf at epoch e+1. - trillian.MapLeafInclusion new_leaf = 2; -} - -// NotMatchingMapRootProof contains all data necessary to reproduce that set of -// mutations does not produce new expected map root. -message NotMatchingMapRootProof { - // map_root contains the map root hash the monitor observed. - trillian.SignedMapRoot map_root = 1; - // old_leafs is a list of inclusion proofs for the leafs in epoch e. - repeated trillian.MapLeafInclusion old_leafs = 2; - // new_leafs is a list of inclusion proofs for changed leafs (from epoch e - // to epoch e+1). Hashing these produces a different hash than root hash in - // above's map_root. - repeated trillian.MapLeafInclusion new_leafs = 3; -} - message GetMonitoringResponse { // smr contains the map root for the sparse Merkle Tree signed with the // monitor's key on success. If the checks were not successful the @@ -69,18 +46,4 @@ message GetMonitoringResponse { // isValid signals if all verification steps for the requested epoch passed // or not. bool isValid = 3; - // invalidMapSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - trillian.SignedMapRoot invalidMapSigProof = 4; - // invalidLogSigProof contains the signed map root received by the - // key-transparency server, if and only if the key-server's signature was - // invalid. - trillian.SignedLogRoot invalidLogSigProof = 5; - // invalidMutation contains data to reproduce that there was an invalid - // mutation from epoch e to epoch e+1 - InvalidMutation invalidMutation = 6; - // NotMatchingMapRoot contains all data to reproduce that the set of mutations - // does not produce observed new map root. - NotMatchingMapRootProof notMatchingMapRoot = 7; -} \ No newline at end of file + } \ No newline at end of file From 8603214d98b52963cdc754dbd2d155c2ab99b4f2 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 19:11:43 -0400 Subject: [PATCH 28/46] update docker-compose, remove kube-config, always use autoconfig --- cmd/keytransparency-monitor/main.go | 42 ------------------- .../keytransparency-deployment.yml.tmpl | 35 ---------------- docker-compose.yml | 3 -- 3 files changed, 80 deletions(-) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index 179fa167a..e761a7af9 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -17,7 +17,6 @@ package main import ( "crypto/tls" "flag" - "fmt" "net" "net/http" "strings" @@ -27,7 +26,6 @@ import ( "github.com/google/keytransparency/impl/monitor" "github.com/google/trillian" "github.com/google/trillian/crypto" - "github.com/google/trillian/crypto/keys/der" "github.com/google/trillian/crypto/keys/pem" "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" @@ -48,10 +46,6 @@ var ( keyFile = flag.String("tls-key", "genfiles/server.key", "TLS private key file") certFile = flag.String("tls-cert", "genfiles/server.pem", "TLS cert file") - autoConfig = flag.Bool("autoconfig", true, "Fetch config info from the server's /v1/domain/info") - mapKey = flag.String("map-key", "genfiles/map-rpc-server.pubkey.pem", "Path to public key PEM used to verify the SMH signature") - logKey = flag.String("log-key", "genfiles/log-rpc-server.pubkey.pem", "Path to public key PEM used to verify the STH signature") - signingKey = flag.String("sign-key", "genfiles/monitor_sign-key.pem", "Path to private key PEM for SMH signing") signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") @@ -198,8 +192,6 @@ func transportCreds(ktURL string, ktCert string, insecure bool) (credentials.Tra // config selects a source for and returns the client configuration. func getTrees(ctx context.Context, cc *grpc.ClientConn) (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { - switch { - case *autoConfig: ktClient := spb.NewKeyTransparencyServiceClient(cc) resp, err2 := ktClient.GetDomainInfo(ctx, &kpb.GetDomainInfoRequest{}) if err2 != nil { @@ -209,38 +201,4 @@ func getTrees(ctx context.Context, cc *grpc.ClientConn) (mapTree *trillian.Tree, logTree = resp.GetLog() mapTree = resp.GetMap() return - default: - return readConfigFromDisk() - } -} - -func readConfigFromDisk() (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { - // Log PubKey. - logPubKey, err := pem.ReadPublicKeyFile(*logKey) - if err != nil { - return nil, nil, fmt.Errorf("Failed to open log public key %v: %v", *logKey, err) - } - logPubPB, err := der.ToPublicProto(logPubKey) - if err != nil { - return nil, nil, fmt.Errorf("failed to serialize log public key: %v", err) - } - - // MapPubKey. - mapPubKey, err := pem.ReadPublicKeyFile(*mapKey) - if err != nil { - return nil, nil, fmt.Errorf("error reading map public key %v: %v", *mapKey, err) - } - mapPubPB, err := der.ToPublicProto(mapPubKey) - if err != nil { - return nil, nil, fmt.Errorf("error seralizeing map public key: %v", err) - } - logTree = &trillian.Tree{ - HashStrategy: trillian.HashStrategy_OBJECT_RFC6962_SHA256, - PublicKey: logPubPB, - } - mapTree = &trillian.Tree{ - HashStrategy: trillian.HashStrategy_CONIKS_SHA512_256, - PublicKey: mapPubPB, - } - return } diff --git a/deploy/kubernetes/keytransparency-deployment.yml.tmpl b/deploy/kubernetes/keytransparency-deployment.yml.tmpl index 2f6feb0e5..e82ccc1e8 100644 --- a/deploy/kubernetes/keytransparency-deployment.yml.tmpl +++ b/deploy/kubernetes/keytransparency-deployment.yml.tmpl @@ -120,41 +120,6 @@ spec: selector: run: kt-signer --- ------- - apiVersion: apps/v1beta1 - kind: Deployment - metadata: - name: kt-monitor - spec: - strategy: - type: Recreate - template: - metadata: - labels: - run: kt-monitor - spec: - containers: - - name: kt-monitor - image: us.gcr.io/key-transparency/keytransparency-monitor - ports: - - containerPort: 8099 - name: json-grpc - --- - apiVersion: v1 - kind: Service - metadata: - name: kt-monitor - labels: - run: kt-monitor - spec: - type: NodePort - ports: - - port: 8099 - targetPort: 8099 - name: http - selector: - run: kt-monitor - --- apiVersion: v1 kind: Service metadata: diff --git a/docker-compose.yml b/docker-compose.yml index 35a79340d..97388275b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -166,9 +166,6 @@ services: - --tls-cert=genfiles/server.crt - --sign-key=/kt/monitor_sign-key.pem - --password=towel - # TODO(ismail): this needs to be the public-key returned by the createTree operation: - - --map-key=trillian/testdata/map-rpc-server.pubkey.pem - - --log-key=trillian/testdata/log-rpc-server.pubkey.pem - --alsologtostderr - --v=3 image: us.gcr.io/key-transparency/keytransparency-monitor From 42a855be55e57ddd7aadd21833a985803eae484f Mon Sep 17 00:00:00 2001 From: Liamsi Date: Mon, 21 Aug 2017 23:27:33 -0400 Subject: [PATCH 29/46] linter checks --- cmd/keytransparency-monitor/main.go | 18 +++++++++--------- core/monitor/monitor.go | 12 ++++++++++-- core/monitor/verify.go | 3 +-- core/monitor/verify_test.go | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index e761a7af9..304aca059 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -55,7 +55,7 @@ var ( pollPeriod = flag.Duration("poll-period", time.Second*5, "Maximum time between polling the key-server. Ideally, this is equal to the min-period of paramerter of the keyserver.") // TODO(ismail): expose prometheus metrics: a variable that tracks valid/invalid MHs - metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") + // metricsAddr = flag.String("metrics-addr", ":8081", "The ip:port to publish metrics on") ) func grpcGatewayMux(addr string) (*runtime.ServeMux, error) { @@ -192,13 +192,13 @@ func transportCreds(ktURL string, ktCert string, insecure bool) (credentials.Tra // config selects a source for and returns the client configuration. func getTrees(ctx context.Context, cc *grpc.ClientConn) (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { - ktClient := spb.NewKeyTransparencyServiceClient(cc) - resp, err2 := ktClient.GetDomainInfo(ctx, &kpb.GetDomainInfoRequest{}) - if err2 != nil { - err = err2 - return - } - logTree = resp.GetLog() - mapTree = resp.GetMap() + ktClient := spb.NewKeyTransparencyServiceClient(cc) + resp, err2 := ktClient.GetDomainInfo(ctx, &kpb.GetDomainInfoRequest{}) + if err2 != nil { + err = err2 return + } + logTree = resp.GetLog() + mapTree = resp.GetMap() + return } diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 2e3ea481d..1361a1237 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -23,21 +23,29 @@ import ( "github.com/google/trillian/merkle/hashers" ) +// Monitor holds the internal state for a monitor accessing the mutations API +// and for verifying its responses. type Monitor struct { hasher hashers.MapHasher logPubKey crypto.PublicKey mapPubKey crypto.PublicKey logVerifier merkle.LogVerifier - trusted trillian.SignedLogRoot + // TODO(ismail): update last trusted signed log root + //trusted trillian.SignedLogRoot } +// New creates a new instance of the monitor. func New(logTree, mapTree trillian.Tree) (*Monitor, error) { - // Log Hasher. logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) if err != nil { return nil, fmt.Errorf("Failed creating LogHasher: %v", err) } + mapHasher, err := hashers.NewMapHasher(mapTree.GetHashStrategy()) + if err != nil { + return nil, fmt.Errorf("Failed creating MapHasher: %v", err) + } return &Monitor{ + hasher: mapHasher, logVerifier: merkle.NewLogVerifier(logHasher), logPubKey: logTree.GetPublicKey(), mapPubKey: mapTree.GetPublicKey(), diff --git a/core/monitor/verify.go b/core/monitor/verify.go index c6590bfc3..90e1f8b4b 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -18,14 +18,13 @@ package monitor import ( - "time" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" ) -// verifyResponse verifies a response received by the GetMutations API. +// VerifyResponse verifies a response received by the GetMutations API. // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. diff --git a/core/monitor/verify_test.go b/core/monitor/verify_test.go index 24483a9da..fb68f4c2d 100644 --- a/core/monitor/verify_test.go +++ b/core/monitor/verify_test.go @@ -15,4 +15,4 @@ package monitor // TODO(ismail): write extensive tests for verification steps, where necessary -// tests should go into integration tests \ No newline at end of file +// tests should go into integration tests From cdc64de5a259aa1b1cb255b3aa0dee73b8168904 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Tue, 22 Aug 2017 11:18:55 -0400 Subject: [PATCH 30/46] Some fixes to the docker files --- cmd/keytransparency-monitor/Dockerfile | 2 ++ cmd/keytransparency-monitor/main.go | 8 ++++---- docker-compose.yml | 4 ++-- scripts/gen_monitor_keys.sh | 1 - scripts/prepare_server.sh | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) mode change 100644 => 100755 scripts/gen_monitor_keys.sh diff --git a/cmd/keytransparency-monitor/Dockerfile b/cmd/keytransparency-monitor/Dockerfile index bbd0dc8ad..7754fa608 100644 --- a/cmd/keytransparency-monitor/Dockerfile +++ b/cmd/keytransparency-monitor/Dockerfile @@ -5,6 +5,8 @@ ADD ./keytransparency /go/src/github.com/google/keytransparency ADD ./trillian /go/src/github.com/google/trillian WORKDIR /go/src/github.com/google/keytransparency +RUN go get -tags="mysql" ./cmd/keytransparency-monitor + ENTRYPOINT ["/go/bin/keytransparency-monitor"] EXPOSE 8099 diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index 304aca059..8e00c87d9 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -103,7 +103,7 @@ func main() { ) // Connect to the kt-server's mutation API: - grpcc, err := dial(*ktURL) + grpcc, err := dial() if err != nil { glog.Fatalf("Error Dialing %v: %v", ktURL, err) } @@ -151,17 +151,17 @@ func main() { } } -func dial(ktURL string) (*grpc.ClientConn, error) { +func dial() (*grpc.ClientConn, error) { var opts []grpc.DialOption - transportCreds, err := transportCreds(ktURL, *ktCert, *insecure) + transportCreds, err := transportCreds(*ktURL, *ktCert, *insecure) if err != nil { return nil, err } opts = append(opts, grpc.WithTransportCredentials(transportCreds)) // TODO(ismail): authenticate the monitor to the kt-server: - cc, err := grpc.Dial(ktURL, opts...) + cc, err := grpc.Dial(*ktURL, opts...) if err != nil { return nil, err } diff --git a/docker-compose.yml b/docker-compose.yml index 97388275b..7298bd312 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -111,7 +111,7 @@ services: - "8081:8081" # metrics entrypoint: - /go/bin/keytransparency-server - - --addr=0.0.0.0.:8080 + - --addr=0.0.0.0:8080 - --db=test:zaphod@tcp(db:3306)/test - --log-id=$LOG_ID - --log-url=trillian-log:8090 @@ -139,7 +139,7 @@ services: image: us.gcr.io/key-transparency/keytransparency-sequencer restart: always entrypoint: - - /go/bin/keytransparency-signer + - /go/bin/keytransparency-sequencer - --db=test:zaphod@tcp(db:3306)/test - --log-id=$LOG_ID - --log-url=trillian-log:8090 diff --git a/scripts/gen_monitor_keys.sh b/scripts/gen_monitor_keys.sh old mode 100644 new mode 100755 index 09a83ef66..fad8f0be8 --- a/scripts/gen_monitor_keys.sh +++ b/scripts/gen_monitor_keys.sh @@ -41,7 +41,6 @@ if ((INTERACTIVE == 1)); then # Prompts for password: openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -out monitor_sign-key.pem else - openssl ecparam -name prime256v1 -genkey | openssl ec -aes256 -passout pass:$DEFAULT_PWD -out monitor_sign-key.pem fi chmod 600 monitor_sign-key.pem diff --git a/scripts/prepare_server.sh b/scripts/prepare_server.sh index e1e4b2ace..581d61077 100755 --- a/scripts/prepare_server.sh +++ b/scripts/prepare_server.sh @@ -133,7 +133,7 @@ if ((FRONTEND == 1)); then fi if ((MONITOR == 1)); then - ./scripts/gen_monitor_keys.sh + ./scripts/gen_monitor_keys.sh -f fi # Generating .env file From b881c04c86de3246ab01eca3482a2816ad888fc8 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Tue, 22 Aug 2017 14:45:33 -0400 Subject: [PATCH 31/46] WIP: restructuring monitor implementation, split up into client, server, processor --- cmd/keytransparency-monitor/main.go | 11 +- core/monitor/monitor.go | 6 +- core/monitor/response.go | 42 +++++++ core/monitor/verify.go | 21 +--- impl/monitor/client.go | 92 ++++++++++++++ impl/monitor/monitor.go | 184 ---------------------------- impl/monitor/process.go | 32 +++++ impl/monitor/server.go | 69 +++++++++++ 8 files changed, 250 insertions(+), 207 deletions(-) create mode 100644 core/monitor/response.go create mode 100644 impl/monitor/client.go delete mode 100644 impl/monitor/monitor.go create mode 100644 impl/monitor/process.go create mode 100644 impl/monitor/server.go diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index 8e00c87d9..5371601ac 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -35,6 +35,7 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" + cmon "github.com/google/keytransparency/core/monitor" kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" @@ -121,6 +122,10 @@ func main() { } srv := monitor.New(mcc, crypto.NewSHA256Signer(key), logTree, mapTree, *pollPeriod) + mon, err := cmon.New(logTree, mapTree, crypto.NewSHA256Signer(key)) + if err != nil { + glog.Exitf("Failed setting up REST proxy: %v", err) + } mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) @@ -137,12 +142,6 @@ func main() { mux := http.NewServeMux() mux.Handle("/", gwmux) - go func() { - if err := srv.StartPolling(); err != nil { - glog.Fatalf("Could not start polling mutations.") - } - }() - // Serve HTTP2 server over TLS. glog.Infof("Listening on %v", *addr) if err := http.ListenAndServeTLS(*addr, *certFile, *keyFile, diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 1361a1237..711aa9fff 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -21,6 +21,8 @@ import ( "github.com/google/trillian" "github.com/google/trillian/merkle" "github.com/google/trillian/merkle/hashers" + + tcrypto "github.com/google/trillian/crypto" ) // Monitor holds the internal state for a monitor accessing the mutations API @@ -30,12 +32,13 @@ type Monitor struct { logPubKey crypto.PublicKey mapPubKey crypto.PublicKey logVerifier merkle.LogVerifier + signer *tcrypto.Signer // TODO(ismail): update last trusted signed log root //trusted trillian.SignedLogRoot } // New creates a new instance of the monitor. -func New(logTree, mapTree trillian.Tree) (*Monitor, error) { +func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer) (*Monitor, error) { logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) if err != nil { return nil, fmt.Errorf("Failed creating LogHasher: %v", err) @@ -49,5 +52,6 @@ func New(logTree, mapTree trillian.Tree) (*Monitor, error) { logVerifier: merkle.NewLogVerifier(logHasher), logPubKey: logTree.GetPublicKey(), mapPubKey: mapTree.GetPublicKey(), + signer: signer, }, nil } diff --git a/core/monitor/response.go b/core/monitor/response.go new file mode 100644 index 000000000..d5a81a15c --- /dev/null +++ b/core/monitor/response.go @@ -0,0 +1,42 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package monitor + +import ( + "time" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" +) + +// GetSignedResponse generates a signed monitor response on success or provides +// all necessary data to prove that the particular check failed. +// +// TODO(ismail): this should take a list of errors and only sign if all errors +// were nil, otherwise it collects all necessary data to prove that the +// particular check failed +func (m *Monitor) GetSignedResponse(in *ktpb.GetMutationsResponse) (*mopb.GetMonitoringResponse, error) { + resp := new(mopb.GetMonitoringResponse) + seen := time.Now().UnixNano() + resp.SeenTimestampNanos = seen + + // copy of received SMR: + smr := *in.Smr + resp.Smr = &smr + // reset map's signature + resp.Smr.Signature = nil + + return resp, nil +} diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 90e1f8b4b..b55493094 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -18,26 +18,15 @@ package monitor import ( - "time" - ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" ) // VerifyResponse verifies a response received by the GetMutations API. // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response -// because of the max. page size. -func (m *Monitor) VerifyResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) *mopb.GetMonitoringResponse { - resp := new(mopb.GetMonitoringResponse) - seen := time.Now().UnixNano() - resp.SeenTimestampNanos = seen - - // copy of received SMR: - smr := *in.Smr - resp.Smr = &smr - // reset map's signature - resp.Smr.Signature = nil - - return resp +// because of the max. page size. If any verification check failed it returns +// an error. +// TODO(ismail): make this return a list of errors +func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { + return nil } diff --git a/impl/monitor/client.go b/impl/monitor/client.go new file mode 100644 index 000000000..1a3b8b97c --- /dev/null +++ b/impl/monitor/client.go @@ -0,0 +1,92 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package monitor + +// +// This file contains Monitor's grpc client logic: poll mutations from the +// kt-server mutations API and page if necessary. +// + +import ( + "time" + + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" +) + +// Each page contains pageSize profiles. Each profile contains multiple +// keys. Assuming 2 keys per profile (each of size 2048-bit), a page of +// size 16 will contain about 8KB of data. +const pageSize = 16 + +// MutationsClient queries the server side mutations API. +type MutationsClient struct { + client mupb.MutationServiceClient + pollPeriod time.Duration +} + +// StartPolling initiates polling the server side mutations API. It does not +// block returns a channel. +// The caller should listen on the channel to receiving the latest polled +// mutations response including all paged mutations. If anything went wrong +// while polling the response channel contains an error. +func (c *MutationsClient) StartPolling(startEpoch int64) (response chan<- *ktpb.GetMutationsResponse, errChan chan<- error) { + response = make(chan *ktpb.GetMutationsResponse) + errChan = make(chan error) + go func() { + epoch := startEpoch + t := time.NewTicker(c.pollPeriod) + for now := range t.C { + glog.Infof("Polling: %v", now) + // time out if we exceed the poll period: + ctx, _ := context.WithTimeout(context.Background(), c.pollPeriod) + monitorResp, err := c.pollMutations(ctx, epoch) + if err != nil { + glog.Errorf("pollMutations(_): %v", err) + errChan <- err + } + + response <- monitorResp + epoch++ + } + }() + return response +} + +func (s *MutationsClient) pollMutations(ctx context.Context, queryEpoch int64, opts ...grpc.CallOption) (*ktpb.GetMutationsResponse, error) { + response, err := s.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ + PageSize: pageSize, + Epoch: queryEpoch, + }, opts...) + if err != nil { + return nil, err + } + + // Page if necessary: query all mutations in the current epoch + for response.GetNextPageToken() != "" { + req := &ktpb.GetMutationsRequest{PageSize: pageSize} + resp, err := s.client.GetMutations(ctx, req, opts...) + if err != nil { + return nil, err + } + response.Mutations = append(response.Mutations, resp.GetMutations()...) + } + + return response, nil +} diff --git a/impl/monitor/monitor.go b/impl/monitor/monitor.go deleted file mode 100644 index d33943c15..000000000 --- a/impl/monitor/monitor.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package monitor implements the monitor service. A monitor repeatedly polls a -// key-transparency server's Mutations API and signs Map Roots if it could -// reconstruct -// clients can query. -package monitor - -import ( - "bytes" - "errors" - "time" - - "github.com/golang/glog" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - - "github.com/google/trillian" - - tcrypto "github.com/google/trillian/crypto" - - cmon "github.com/google/keytransparency/core/monitor" - ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" - - mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" -) - -// Each page contains pageSize profiles. Each profile contains multiple -// keys. Assuming 2 keys per profile (each of size 2048-bit), a page of -// size 16 will contain about 8KB of data. -const pageSize = 16 - -var ( - // ErrNothingProcessed occurs when the monitor did not process any mutations / - // smrs yet. - ErrNothingProcessed = errors.New("did not process any mutations yet") -) - -// Server holds internal state for the monitor server. -type Server struct { - client mupb.MutationServiceClient - pollPeriod time.Duration - - monitor *cmon.Monitor - signer *tcrypto.Signer - proccessedSMRs []*mopb.GetMonitoringResponse -} - -// New creates a new instance of the monitor server. -func New(cli mupb.MutationServiceClient, - signer *tcrypto.Signer, - logTree, mapTree *trillian.Tree, - poll time.Duration) *Server { - return &Server{ - client: cli, - pollPeriod: poll, - // TODO(ismail) use domain info to properly init. the monitor: - monitor: &cmon.Monitor{}, - signer: signer, - proccessedSMRs: make([]*mopb.GetMonitoringResponse, 256), - } -} - -// StartPolling initiates polling and processing mutations every pollPeriod. -func (s *Server) StartPolling() error { - t := time.NewTicker(s.pollPeriod) - for now := range t.C { - glog.Infof("Polling: %v", now) - ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) - if _, err := s.pollMutations(ctx); err != nil { - glog.Errorf("pollMutations(_): %v", err) - } - } - return nil -} - -// GetSignedMapRoot returns the latest valid signed map root the monitor -// observed. Additionally, the response contains additional data necessary to -// reproduce errors on failure. -// -// Returns the signed map root for the latest epoch the monitor observed. If -// the monitor could not reconstruct the map root given the set of mutations -// from the previous to the current epoch it won't sign the map root and -// additional data will be provided to reproduce the failure. -func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { - if len(s.proccessedSMRs) > 0 { - return s.proccessedSMRs[len(s.proccessedSMRs)-1], nil - } - return nil, ErrNothingProcessed -} - -// GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns -// the monitor's result for a specific map revision. -// -// Returns the signed map root for the specified epoch the monitor observed. -// If the monitor could not reconstruct the map root given the set of -// mutations from the previous to the current epoch it won't sign the map root -// and additional data will be provided to reproduce the failure. -func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { - // TODO(ismail): implement by revision API - return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") -} - -func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { - // TODO(ismail): move everything that does not rely on impl packages (e.g., - // the client here) into core: - resp, err := s.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ - PageSize: pageSize, - Epoch: s.nextRevToQuery(), - }, opts...) - if err != nil { - return nil, err - } - - if got, want := resp.GetSmr(), s.lastSeenSMR(); bytes.Equal(got.GetRootHash(), want.GetRootHash()) && - got.GetMapRevision() == want.GetMapRevision() { - // We already processed this SMR. Do not update seen SMRs. Do not scroll - // pages for further mutations. Return empty mutations list. - glog.Infof("Already processed this SMR with revision %v. Continuing.", got.GetMapRevision()) - return nil, nil - } - - mutations, err := s.pageMutations(ctx, resp, opts...) - if err != nil { - glog.Errorf("s.pageMutations(_): %v", err) - return nil, err - } - - // TODO(Ismail): let the verification method in core directly return the response - monitorResp := s.monitor.VerifyResponse(resp, mutations) - // Update seen/processed signed map roots: - s.proccessedSMRs = append(s.proccessedSMRs, monitorResp) - - return mutations, nil -} - -// pageMutations iterates/pages through all mutations in the case there were -// more then maximum pageSize mutations in between epochs. -// It will modify the passed GetMutationsResponse resp. -func (s *Server) pageMutations(ctx context.Context, resp *ktpb.GetMutationsResponse, - opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { - ms := make([]*ktpb.Mutation, pageSize*2) - ms = append(ms, resp.GetMutations()...) - - // Query all mutations in the current epoch - for resp.GetNextPageToken() != "" { - req := &ktpb.GetMutationsRequest{PageSize: pageSize} - resp, err := s.client.GetMutations(ctx, req, opts...) - if err != nil { - return nil, err - } - ms = append(ms, resp.GetMutations()...) - } - return ms, nil -} - -func (s *Server) lastSeenSMR() *trillian.SignedMapRoot { - if len(s.proccessedSMRs) > 0 { - return s.proccessedSMRs[len(s.proccessedSMRs)-1].GetSmr() - } - return nil -} - -func (s *Server) nextRevToQuery() int64 { - smr := s.lastSeenSMR() - if smr == nil { - return 1 - } - return smr.GetMapRevision() + 1 -} diff --git a/impl/monitor/process.go b/impl/monitor/process.go new file mode 100644 index 000000000..1a3ed7c6f --- /dev/null +++ b/impl/monitor/process.go @@ -0,0 +1,32 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package monitor implements the monitor service. A monitor repeatedly polls a +// key-transparency server's Mutations API and signs Map Roots if it could +// reconstruct +// clients can query. +package monitor + +import ( + "errors" +) + +var ( + // ErrNothingProcessed occurs when the monitor did not process any mutations / + // smrs yet. + ErrNothingProcessed = errors.New("did not process any mutations yet") +) + +// TODO(ismail): call the client, actually process the mutations by calling API +// in core diff --git a/impl/monitor/server.go b/impl/monitor/server.go new file mode 100644 index 000000000..b85d8ceb3 --- /dev/null +++ b/impl/monitor/server.go @@ -0,0 +1,69 @@ +package monitor + +import ( + "time" + + "github.com/golang/glog" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + + "github.com/google/trillian" + + tcrypto "github.com/google/trillian/crypto" + + cmon "github.com/google/keytransparency/core/monitor" + mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" + + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" +) + +// Server holds internal state for the monitor server. It serves monitoring +// responses via a grpc and HTTP API. +type Server struct { + client *MutationsClient + + monitor *cmon.Monitor +} + +// New creates a new instance of the monitor server. +func New(cli mupb.MutationServiceClient, + signer *tcrypto.Signer, + logTree, mapTree *trillian.Tree, + poll time.Duration) *Server { + mon, err := cmon.New(logTree, mapTree, signer) + if err != nil { + glog.Fatalf("Could not create monitor: %v", err) + } + return &Server{ + client: &MutationsClient{ + client: cli, + pollPeriod: poll, + }, + monitor: mon, + } +} + +// GetSignedMapRoot returns the latest valid signed map root the monitor +// observed. Additionally, the response contains additional data necessary to +// reproduce errors on failure. +// +// Returns the signed map root for the latest epoch the monitor observed. If +// the monitor could not reconstruct the map root given the set of mutations +// from the previous to the current epoch it won't sign the map root and +// additional data will be provided to reproduce the failure. +func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { + return nil, ErrNothingProcessed +} + +// GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns +// the monitor's result for a specific map revision. +// +// Returns the signed map root for the specified epoch the monitor observed. +// If the monitor could not reconstruct the map root given the set of +// mutations from the previous to the current epoch it won't sign the map root +// and additional data will be provided to reproduce the failure. +func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { + // TODO(ismail): implement by revision API + return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") +} From 94f750872ca481b4ec2f3205cc6d7bf8dd91f75e Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 23 Aug 2017 15:22:38 -0400 Subject: [PATCH 32/46] restructured non-verifiying monitor --- cmd/keytransparency-monitor/main.go | 39 +++++++-- core/monitor/monitor.go | 31 +++++++- core/monitor/response.go | 42 ---------- .../process.go => core/monitor/sign.go | 29 ++++--- core/monitor/storage/storage.go | 79 +++++++++++++++++++ core/monitor/verify.go | 3 +- .../monitor_v1_types/monitor_v1_types.pb.go | 57 ++++++++----- .../monitor_v1_types/monitor_v1_types.proto | 12 ++- impl/monitor/{ => client}/client.go | 37 ++++++--- impl/monitor/server.go | 63 ++++++++------- 10 files changed, 265 insertions(+), 127 deletions(-) delete mode 100644 core/monitor/response.go rename impl/monitor/process.go => core/monitor/sign.go (57%) create mode 100644 core/monitor/storage/storage.go rename impl/monitor/{ => client}/client.go (73%) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index 5371601ac..71878fcc7 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -35,11 +35,15 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" + "github.com/google/keytransparency/core/monitor/storage" cmon "github.com/google/keytransparency/core/monitor" kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/google/keytransparency/impl/monitor/client" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" + _ "github.com/google/trillian/merkle/coniks" // Register coniks + _ "github.com/google/trillian/merkle/objhasher" // Register objhasher ) var ( @@ -121,12 +125,8 @@ func main() { glog.Fatalf("Could not read domain info %v:", err) } - srv := monitor.New(mcc, crypto.NewSHA256Signer(key), logTree, mapTree, *pollPeriod) - mon, err := cmon.New(logTree, mapTree, crypto.NewSHA256Signer(key)) - if err != nil { - glog.Exitf("Failed setting up REST proxy: %v", err) - } - + store := storage.New() + srv := monitor.New(store) mopb.RegisterMonitorServiceServer(grpcServer, srv) reflection.Register(grpcServer) grpc_prometheus.Register(grpcServer) @@ -142,6 +142,31 @@ func main() { mux := http.NewServeMux() mux.Handle("/", gwmux) + // initialize the mutations API client and feed the responses it got + // into the monitor: + mon, err := cmon.New(logTree, mapTree, crypto.NewSHA256Signer(key), store) + if err != nil { + glog.Exitf("Failed to initialize monitor: %v", err) + } + mutCli := client.New(mcc, *pollPeriod) + responses, errs := mutCli.StartPolling(1) + go func() { + for { + select { + case mutResp := <-responses: + glog.Infof("Received mutations response: %v", mutResp.Epoch) + if err := mon.Process(mutResp); err != nil { + glog.Infof("Error processing mutations response: %v", err) + } + case err := <-errs: + // this is OK if there were no mutations in between: + // TODO(ismail): handle the case when the known maxDuration has + // passed and no epoch was issued? + glog.Infof("Could not retrieve mutations API response %v", err) + } + } + }() + // Serve HTTP2 server over TLS. glog.Infof("Listening on %v", *addr) if err := http.ListenAndServeTLS(*addr, *certFile, *keyFile, @@ -190,7 +215,7 @@ func transportCreds(ktURL string, ktCert string, insecure bool) (credentials.Tra } // config selects a source for and returns the client configuration. -func getTrees(ctx context.Context, cc *grpc.ClientConn) (mapTree *trillian.Tree, logTree *trillian.Tree, err error) { +func getTrees(ctx context.Context, cc *grpc.ClientConn) (logTree *trillian.Tree, mapTree *trillian.Tree, err error) { ktClient := spb.NewKeyTransparencyServiceClient(cc) resp, err2 := ktClient.GetDomainInfo(ctx, &kpb.GetDomainInfoRequest{}) if err2 != nil { diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 711aa9fff..f219f570b 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -17,11 +17,16 @@ package monitor import ( "crypto" "fmt" + "time" + + "github.com/golang/glog" + + "github.com/google/keytransparency/core/monitor/storage" + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" "github.com/google/trillian/merkle" "github.com/google/trillian/merkle/hashers" - tcrypto "github.com/google/trillian/crypto" ) @@ -35,10 +40,11 @@ type Monitor struct { signer *tcrypto.Signer // TODO(ismail): update last trusted signed log root //trusted trillian.SignedLogRoot + store *storage.Storage } // New creates a new instance of the monitor. -func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer) (*Monitor, error) { +func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage.Storage) (*Monitor, error) { logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) if err != nil { return nil, fmt.Errorf("Failed creating LogHasher: %v", err) @@ -53,5 +59,26 @@ func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer) (*Monitor, err logPubKey: logTree.GetPublicKey(), mapPubKey: mapTree.GetPublicKey(), signer: signer, + store: store, }, nil } + +func (m *Monitor) Process(resp *ktpb.GetMutationsResponse) error { + var smr *trillian.SignedMapRoot + var err error + seen := time.Now().Unix() + errs := m.VerifyMutationsResponse(resp) + if len(errs) == 0 { + glog.Infof("Successfully verified mutations response for epoch: %v", resp.Epoch) + smr, err = m.signMapRoot(resp) + if err != nil { + glog.Errorf("Failed to sign map root for epoch %v: %v", resp.Epoch, err) + return fmt.Errorf("m.signMapRoot(_): %v", err) + } + } + if err := m.store.Set(resp.Epoch, seen, smr, resp, errs); err != nil { + glog.Errorf("m.store.Set(%v, %v, _, _, %v): %v", resp.Epoch, seen, errs, err) + return err + } + return nil +} diff --git a/core/monitor/response.go b/core/monitor/response.go deleted file mode 100644 index d5a81a15c..000000000 --- a/core/monitor/response.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package monitor - -import ( - "time" - - ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" -) - -// GetSignedResponse generates a signed monitor response on success or provides -// all necessary data to prove that the particular check failed. -// -// TODO(ismail): this should take a list of errors and only sign if all errors -// were nil, otherwise it collects all necessary data to prove that the -// particular check failed -func (m *Monitor) GetSignedResponse(in *ktpb.GetMutationsResponse) (*mopb.GetMonitoringResponse, error) { - resp := new(mopb.GetMonitoringResponse) - seen := time.Now().UnixNano() - resp.SeenTimestampNanos = seen - - // copy of received SMR: - smr := *in.Smr - resp.Smr = &smr - // reset map's signature - resp.Smr.Signature = nil - - return resp, nil -} diff --git a/impl/monitor/process.go b/core/monitor/sign.go similarity index 57% rename from impl/monitor/process.go rename to core/monitor/sign.go index 1a3ed7c6f..88c32140e 100644 --- a/impl/monitor/process.go +++ b/core/monitor/sign.go @@ -12,21 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package monitor implements the monitor service. A monitor repeatedly polls a -// key-transparency server's Mutations API and signs Map Roots if it could -// reconstruct -// clients can query. package monitor import ( - "errors" -) + "fmt" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" -var ( - // ErrNothingProcessed occurs when the monitor did not process any mutations / - // smrs yet. - ErrNothingProcessed = errors.New("did not process any mutations yet") + "github.com/google/trillian" ) -// TODO(ismail): call the client, actually process the mutations by calling API -// in core +func (m *Monitor) signMapRoot(in *ktpb.GetMutationsResponse) (*trillian.SignedMapRoot, error) { + // copy of received SMR: + smr := *in.Smr + smr.Signature = nil + + sig, err := m.signer.SignObject(smr) + if err != nil { + return nil, fmt.Errorf("SignObject(): %v", err) + } + smr.Signature = sig + + return &smr, nil +} diff --git a/core/monitor/storage/storage.go b/core/monitor/storage/storage.go new file mode 100644 index 000000000..883dbbff7 --- /dev/null +++ b/core/monitor/storage/storage.go @@ -0,0 +1,79 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package storage + +import ( + "errors" + + ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/google/trillian" +) + +var ( + ErrAlreadyStored = errors.New("already stored epoch") + ErrNotFound = errors.New("data for epoch not found") +) + +type MonitoringResult struct { + // in case of success this contains the map root signed by the monitor + Smr *trillian.SignedMapRoot + // response contains the original mutations API response from the server + // in case at least one verification step failed + Response *ktpb.GetMutationsResponse + Seen int64 + Errors []error +} + +type Storage struct { + store map[int64]*MonitoringResult + latest int64 +} + +func New() *Storage { + return &Storage{ + store: make(map[int64]*MonitoringResult), + } +} + +func (s *Storage) Set(epoch int64, + seenNanos int64, + smr *trillian.SignedMapRoot, + response *ktpb.GetMutationsResponse, + errorList []error) error { + // see if we already processed this epoch: + if _, ok := s.store[epoch]; ok { + return ErrAlreadyStored + } + // if not we just store the value: + s.store[epoch] = &MonitoringResult{ + Smr: smr, + Seen: seenNanos, + Response: response, + Errors: errorList, + } + s.latest=epoch + return nil +} + +func (s *Storage) Get(epoch int64) (*MonitoringResult, error) { + if result, ok := s.store[epoch]; ok { + return result, nil + } + return nil, ErrNotFound +} + +func (s *Storage) LatestEpoch() int64 { + return s.latest +} diff --git a/core/monitor/verify.go b/core/monitor/verify.go index b55493094..ea9573696 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -26,7 +26,6 @@ import ( // of received mutations may differ from those included in the initial response // because of the max. page size. If any verification check failed it returns // an error. -// TODO(ismail): make this return a list of errors -func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse, allMuts []*ktpb.Mutation) error { +func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { return nil } diff --git a/core/proto/monitor_v1_types/monitor_v1_types.pb.go b/core/proto/monitor_v1_types/monitor_v1_types.pb.go index d0fe0b1a2..35dec6287 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.pb.go +++ b/core/proto/monitor_v1_types/monitor_v1_types.pb.go @@ -19,6 +19,7 @@ package monitor_v1_types import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import keytransparency_v1_types "github.com/google/keytransparency/core/proto/keytransparency_v1_types" import trillian "github.com/google/trillian" // Reference imports to suppress errors if they are not otherwise used. @@ -60,9 +61,13 @@ type GetMonitoringResponse struct { // signed map root was retrieved and processed. The actual timestamp of the // smr returned by the server is contained in above smr field. SeenTimestampNanos int64 `protobuf:"varint,2,opt,name=seen_timestamp_nanos,json=seenTimestampNanos" json:"seen_timestamp_nanos,omitempty"` - // isValid signals if all verification steps for the requested epoch passed - // or not. - IsValid bool `protobuf:"varint,3,opt,name=isValid" json:"isValid,omitempty"` + // errors contains a list of error string representing the verification checks + // that failed while monitoring the key-transparency server. + Errors []string `protobuf:"bytes,3,rep,name=errors" json:"errors,omitempty"` + // error_data contains the original response from the mutations API if and + // only if at least one verification step failed. It can be used to re-run the + // verification steps. + ErrorData *keytransparency_v1_types.GetMutationsResponse `protobuf:"bytes,4,opt,name=error_data,json=errorData" json:"error_data,omitempty"` } func (m *GetMonitoringResponse) Reset() { *m = GetMonitoringResponse{} } @@ -84,11 +89,18 @@ func (m *GetMonitoringResponse) GetSeenTimestampNanos() int64 { return 0 } -func (m *GetMonitoringResponse) GetIsValid() bool { +func (m *GetMonitoringResponse) GetErrors() []string { if m != nil { - return m.IsValid + return m.Errors } - return false + return nil +} + +func (m *GetMonitoringResponse) GetErrorData() *keytransparency_v1_types.GetMutationsResponse { + if m != nil { + return m.ErrorData + } + return nil } func init() { @@ -99,18 +111,23 @@ func init() { func init() { proto.RegisterFile("monitor_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 208 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x8f, 0xcd, 0x4a, 0x04, 0x31, - 0x10, 0x84, 0x19, 0x07, 0x7f, 0x88, 0x20, 0x12, 0x46, 0x1d, 0x3c, 0x2d, 0x7b, 0x5a, 0x41, 0x82, - 0xab, 0x0f, 0xe1, 0x69, 0x3d, 0x44, 0xf1, 0x1a, 0x22, 0xdb, 0x2c, 0x0d, 0x93, 0xee, 0x98, 0x6e, - 0x17, 0x7c, 0x09, 0x9f, 0x59, 0x26, 0xe3, 0x78, 0xd8, 0x63, 0xd5, 0xf7, 0x41, 0x51, 0xe6, 0x3a, - 0x31, 0xa1, 0x72, 0x09, 0xfb, 0x75, 0xd0, 0xef, 0x0c, 0xe2, 0x72, 0x61, 0x65, 0x7b, 0xf9, 0xd7, - 0xbb, 0xfd, 0xda, 0xd5, 0xfe, 0xf6, 0x42, 0x0b, 0x0e, 0x03, 0x46, 0x9a, 0x8c, 0xe5, 0xbd, 0xe9, - 0x9e, 0x41, 0x37, 0x93, 0x86, 0xb4, 0xf3, 0xf0, 0xf9, 0x05, 0xa2, 0xb6, 0x33, 0xc7, 0xa2, 0xb1, - 0x68, 0xdf, 0x2c, 0x9a, 0x55, 0xeb, 0xa7, 0xb0, 0xfc, 0x69, 0xcc, 0xd5, 0x81, 0x2e, 0x99, 0x49, - 0xc0, 0xde, 0x99, 0x56, 0x52, 0xa9, 0xf6, 0xf9, 0xe3, 0x8d, 0xfb, 0x5f, 0x79, 0xc5, 0x1d, 0xc1, - 0x76, 0x13, 0xb3, 0x67, 0x56, 0x3f, 0x3a, 0xf6, 0xc1, 0x74, 0x02, 0x40, 0x41, 0x31, 0x81, 0x68, - 0x4c, 0x39, 0x50, 0x24, 0x96, 0xfe, 0xa8, 0x2e, 0xd9, 0x91, 0xbd, 0xcd, 0xe8, 0x65, 0x24, 0xb6, - 0x37, 0xa7, 0x28, 0xef, 0x71, 0xc0, 0x6d, 0xdf, 0x2e, 0x9a, 0xd5, 0x99, 0x9f, 0xe3, 0xc7, 0x49, - 0x7d, 0xf1, 0xf4, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x8c, 0xe2, 0xa7, 0x01, 0x01, 0x00, 0x00, + // 281 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x41, 0x4b, 0x03, 0x31, + 0x10, 0x85, 0xa9, 0xab, 0x85, 0x46, 0x10, 0x09, 0xb5, 0x2e, 0x3d, 0x95, 0x9e, 0x2a, 0x48, 0xd6, + 0xea, 0x5f, 0x10, 0x3c, 0xd5, 0x43, 0xf4, 0xbe, 0x4c, 0xdb, 0x61, 0x0d, 0x76, 0x33, 0x31, 0x33, + 0x2d, 0xf4, 0xb7, 0xfa, 0x67, 0x64, 0xb3, 0xed, 0x1e, 0x16, 0xbc, 0x65, 0xe6, 0x7b, 0x99, 0xf7, + 0x78, 0x6a, 0x52, 0x93, 0x77, 0x42, 0xb1, 0x3c, 0x2c, 0x4b, 0x39, 0x06, 0x64, 0x13, 0x22, 0x09, + 0xe9, 0xdb, 0xd3, 0xde, 0x1c, 0x96, 0x26, 0xed, 0xa7, 0xdb, 0xca, 0xc9, 0xd7, 0x7e, 0x6d, 0x36, + 0x54, 0x17, 0x15, 0x51, 0xb5, 0xc3, 0xe2, 0x1b, 0x8f, 0x12, 0xc1, 0x73, 0x80, 0x88, 0x7e, 0x73, + 0x2c, 0x36, 0x14, 0xb1, 0x48, 0xff, 0xfb, 0xa8, 0x3b, 0xff, 0x2f, 0x68, 0x7d, 0xa7, 0x37, 0x12, + 0xdd, 0x6e, 0xe7, 0xc0, 0xb7, 0xf3, 0xfc, 0x51, 0x8d, 0xdf, 0x50, 0x56, 0x6d, 0x18, 0xe7, 0x2b, + 0x8b, 0x3f, 0x7b, 0x64, 0xd1, 0x63, 0x75, 0xc5, 0x02, 0x51, 0xf2, 0xc1, 0x6c, 0xb0, 0xc8, 0x6c, + 0x3b, 0xcc, 0x7f, 0x07, 0xea, 0xae, 0x27, 0xe7, 0x40, 0x9e, 0x51, 0x3f, 0xa8, 0x8c, 0xeb, 0x98, + 0xd4, 0xd7, 0xcf, 0xf7, 0xa6, 0x73, 0xf9, 0x70, 0x95, 0xc7, 0xed, 0x0a, 0x82, 0x25, 0x12, 0xdb, + 0x68, 0xf4, 0x93, 0x1a, 0x33, 0xa2, 0x2f, 0xc5, 0xd5, 0xc8, 0x02, 0x75, 0x28, 0x3d, 0x78, 0xe2, + 0xfc, 0x22, 0x39, 0xe9, 0x86, 0x7d, 0x9e, 0xd1, 0x7b, 0x43, 0xf4, 0x44, 0x0d, 0x31, 0x46, 0x8a, + 0x9c, 0x67, 0xb3, 0x6c, 0x31, 0xb2, 0xa7, 0x49, 0xaf, 0x94, 0x4a, 0xaf, 0x72, 0x0b, 0x02, 0xf9, + 0x65, 0xf2, 0x36, 0xa6, 0xd7, 0x40, 0xd7, 0xb0, 0x69, 0x92, 0xef, 0x05, 0xc4, 0x91, 0xe7, 0x73, + 0x70, 0x3b, 0x4a, 0x17, 0x5e, 0x41, 0x60, 0x3d, 0x4c, 0x95, 0xbc, 0xfc, 0x05, 0x00, 0x00, 0xff, + 0xff, 0x82, 0xa2, 0x4b, 0x16, 0xb4, 0x01, 0x00, 0x00, } diff --git a/core/proto/monitor_v1_types/monitor_v1_types.proto b/core/proto/monitor_v1_types/monitor_v1_types.proto index 79f1b5697..4fdacef17 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.proto +++ b/core/proto/monitor_v1_types/monitor_v1_types.proto @@ -18,6 +18,7 @@ syntax = "proto3"; // package monitor.v1.types; +import "github.com/google/keytransparency/core/proto/keytransparency_v1_types/keytransparency_v1_types.proto"; import "trillian.proto"; // GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. @@ -43,7 +44,12 @@ message GetMonitoringResponse { // response, if any. // - // isValid signals if all verification steps for the requested epoch passed - // or not. - bool isValid = 3; + // errors contains a list of error string representing the verification checks + // that failed while monitoring the key-transparency server. + repeated string errors = 3; + + // error_data contains the original response from the mutations API if and + // only if at least one verification step failed. It can be used to re-run the + // verification steps. + keytransparency.v1.types.GetMutationsResponse error_data = 4; } \ No newline at end of file diff --git a/impl/monitor/client.go b/impl/monitor/client/client.go similarity index 73% rename from impl/monitor/client.go rename to impl/monitor/client/client.go index 1a3b8b97c..f0993b22b 100644 --- a/impl/monitor/client.go +++ b/impl/monitor/client/client.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package monitor +package client // // This file contains Monitor's grpc client logic: poll mutations from the @@ -35,20 +35,28 @@ import ( // size 16 will contain about 8KB of data. const pageSize = 16 -// MutationsClient queries the server side mutations API. -type MutationsClient struct { +// Client queries the server side mutations API. +type Client struct { client mupb.MutationServiceClient pollPeriod time.Duration } +// New initializes a new mutations API monitoring client. +func New(client mupb.MutationServiceClient, pollPeriod time.Duration) *Client { + return &Client{ + client: client, + pollPeriod: pollPeriod, + } +} + // StartPolling initiates polling the server side mutations API. It does not // block returns a channel. // The caller should listen on the channel to receiving the latest polled // mutations response including all paged mutations. If anything went wrong // while polling the response channel contains an error. -func (c *MutationsClient) StartPolling(startEpoch int64) (response chan<- *ktpb.GetMutationsResponse, errChan chan<- error) { - response = make(chan *ktpb.GetMutationsResponse) - errChan = make(chan error) +func (c *Client) StartPolling(startEpoch int64) (<-chan *ktpb.GetMutationsResponse, <-chan error) { + response := make(chan *ktpb.GetMutationsResponse) + errChan := make(chan error) go func() { epoch := startEpoch t := time.NewTicker(c.pollPeriod) @@ -58,18 +66,23 @@ func (c *MutationsClient) StartPolling(startEpoch int64) (response chan<- *ktpb. ctx, _ := context.WithTimeout(context.Background(), c.pollPeriod) monitorResp, err := c.pollMutations(ctx, epoch) if err != nil { - glog.Errorf("pollMutations(_): %v", err) + glog.Infof("pollMutations(_): %v", err) errChan <- err + } else { + // only write to results channel and increment epoch + // if there was no error: + glog.Infof("Got response %v at %v", monitorResp.Epoch, now) + response <- monitorResp + epoch++ } - - response <- monitorResp - epoch++ } }() - return response + return response, errChan } -func (s *MutationsClient) pollMutations(ctx context.Context, queryEpoch int64, opts ...grpc.CallOption) (*ktpb.GetMutationsResponse, error) { +func (s *Client) pollMutations(ctx context.Context, + queryEpoch int64, + opts ...grpc.CallOption) (*ktpb.GetMutationsResponse, error) { response, err := s.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ PageSize: pageSize, Epoch: queryEpoch, diff --git a/impl/monitor/server.go b/impl/monitor/server.go index b85d8ceb3..2af9a3173 100644 --- a/impl/monitor/server.go +++ b/impl/monitor/server.go @@ -1,46 +1,32 @@ package monitor import ( - "time" + "errors" - "github.com/golang/glog" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" - "github.com/google/trillian" - - tcrypto "github.com/google/trillian/crypto" - - cmon "github.com/google/keytransparency/core/monitor" + "github.com/google/keytransparency/core/monitor/storage" mopb "github.com/google/keytransparency/core/proto/monitor_v1_types" +) - mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" +var ( + // ErrNothingProcessed occurs when the monitor did not process any mutations / + // smrs yet. + ErrNothingProcessed = errors.New("did not process any mutations yet") ) // Server holds internal state for the monitor server. It serves monitoring // responses via a grpc and HTTP API. type Server struct { - client *MutationsClient - - monitor *cmon.Monitor + storage *storage.Storage } // New creates a new instance of the monitor server. -func New(cli mupb.MutationServiceClient, - signer *tcrypto.Signer, - logTree, mapTree *trillian.Tree, - poll time.Duration) *Server { - mon, err := cmon.New(logTree, mapTree, signer) - if err != nil { - glog.Fatalf("Could not create monitor: %v", err) - } +func New(storage *storage.Storage) *Server { return &Server{ - client: &MutationsClient{ - client: cli, - pollPeriod: poll, - }, - monitor: mon, + storage: storage, } } @@ -53,7 +39,8 @@ func New(cli mupb.MutationServiceClient, // from the previous to the current epoch it won't sign the map root and // additional data will be provided to reproduce the failure. func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { - return nil, ErrNothingProcessed + latestEpoch := s.storage.LatestEpoch() + return s.getResponseByRevision(latestEpoch) } // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns @@ -64,6 +51,28 @@ func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringReq // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { - // TODO(ismail): implement by revision API - return nil, grpc.Errorf(codes.Unimplemented, "GetSignedMapRoot is unimplemented") + return s.getResponseByRevision(in.GetStart()) +} + +func (s *Server) getResponseByRevision(epoch int64) (*mopb.GetMonitoringResponse, error) { + res, err := s.storage.Get(epoch) + if err == storage.ErrNotFound { + return nil, grpc.Errorf(codes.NotFound, + "Could not find monitoring response for epoch %d", epoch) + } + + resp := &mopb.GetMonitoringResponse{ + Smr: res.Smr, + SeenTimestampNanos: res.Seen, + } + + if len(res.Errors) > 0 { + for _, err := range resp.Errors { + resp.Errors = append(resp.Errors, err) + } + // data to replay the verification steps: + resp.ErrorData = res.Response + } + + return resp, nil } From 04b43540d4eea25a5267ad32e9c4ca6a1bae7573 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 23 Aug 2017 15:48:45 -0400 Subject: [PATCH 33/46] gometalinter --- cmd/keytransparency-monitor/main.go | 2 +- core/monitor/monitor.go | 7 ++-- core/monitor/storage/storage.go | 33 ++++++++++++++----- core/monitor/verify.go | 4 +-- impl/monitor/client/client.go | 10 +++--- impl/monitor/server.go | 25 ++++++++++++-- .../pelletier/go-toml/tomltree_write.go | 2 +- vendor/github.com/spf13/viper/viper.go | 2 +- 8 files changed, 63 insertions(+), 22 deletions(-) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index 71878fcc7..b76685507 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -35,8 +35,8 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/reflection" - "github.com/google/keytransparency/core/monitor/storage" cmon "github.com/google/keytransparency/core/monitor" + "github.com/google/keytransparency/core/monitor/storage" kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/keytransparency/impl/monitor/client" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index f219f570b..419936b28 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -25,9 +25,9 @@ import ( ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" + tcrypto "github.com/google/trillian/crypto" "github.com/google/trillian/merkle" "github.com/google/trillian/merkle/hashers" - tcrypto "github.com/google/trillian/crypto" ) // Monitor holds the internal state for a monitor accessing the mutations API @@ -63,11 +63,14 @@ func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage }, nil } +// Process processes a mutation response received from the keytransparency +// server. Processing includes verifying, signing and storing the resulting +// monitoring response. func (m *Monitor) Process(resp *ktpb.GetMutationsResponse) error { var smr *trillian.SignedMapRoot var err error seen := time.Now().Unix() - errs := m.VerifyMutationsResponse(resp) + errs := m.verifyMutationsResponse(resp) if len(errs) == 0 { glog.Infof("Successfully verified mutations response for epoch: %v", resp.Epoch) smr, err = m.signMapRoot(resp) diff --git a/core/monitor/storage/storage.go b/core/monitor/storage/storage.go index 883dbbff7..dc815d599 100644 --- a/core/monitor/storage/storage.go +++ b/core/monitor/storage/storage.go @@ -22,31 +22,45 @@ import ( ) var ( + // ErrAlreadyStored is raised if the caller tries storing a response which + // has already been stored. ErrAlreadyStored = errors.New("already stored epoch") - ErrNotFound = errors.New("data for epoch not found") + // ErrNotFound is raised if the caller tries to retrieve data for an epoch + // which has not been processed and stored yet. + ErrNotFound = errors.New("data for epoch not found") ) +// MonitoringResult stores all data type MonitoringResult struct { - // in case of success this contains the map root signed by the monitor + // Smr contains the map root signed by the monitor in case all verifications + // have passed. Smr *trillian.SignedMapRoot - // response contains the original mutations API response from the server - // in case at least one verification step failed + // Seen is the the unix timestamp at which the mutations response has been + // received. + Seen int64 + // Errors contains a string representation of the verifications steps that + // failed. + Errors []error + // Response contains the original mutations API response from the server + // in case at least one verification step failed. Response *ktpb.GetMutationsResponse - Seen int64 - Errors []error } +// Storage is an in-memory store for the monitoring results. type Storage struct { - store map[int64]*MonitoringResult + store map[int64]*MonitoringResult latest int64 } +// New initializes a func New() *Storage { return &Storage{ store: make(map[int64]*MonitoringResult), } } +// Set internally stores the given data as a MonitoringResult which can be +// retrieved by Get. func (s *Storage) Set(epoch int64, seenNanos int64, smr *trillian.SignedMapRoot, @@ -63,10 +77,12 @@ func (s *Storage) Set(epoch int64, Response: response, Errors: errorList, } - s.latest=epoch + s.latest = epoch return nil } +// Get returns the MonitoringResult for the given epoch. It returns an error +// if the result does not exist. func (s *Storage) Get(epoch int64) (*MonitoringResult, error) { if result, ok := s.store[epoch]; ok { return result, nil @@ -74,6 +90,7 @@ func (s *Storage) Get(epoch int64) (*MonitoringResult, error) { return nil, ErrNotFound } +// LatestEpoch is a convenience method to retrieve the latest stored epoch. func (s *Storage) LatestEpoch() int64 { return s.latest } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index ea9573696..1deadfb45 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -21,11 +21,11 @@ import ( ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" ) -// VerifyResponse verifies a response received by the GetMutations API. +// verifyMutationsResponse verifies a response received by the GetMutations API. // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. If any verification check failed it returns // an error. -func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { +func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { return nil } diff --git a/impl/monitor/client/client.go b/impl/monitor/client/client.go index f0993b22b..18245eb76 100644 --- a/impl/monitor/client/client.go +++ b/impl/monitor/client/client.go @@ -15,7 +15,7 @@ package client // -// This file contains Monitor's grpc client logic: poll mutations from the +// This file contains Monitor'c grpc client logic: poll mutations from the // kt-server mutations API and page if necessary. // @@ -44,7 +44,7 @@ type Client struct { // New initializes a new mutations API monitoring client. func New(client mupb.MutationServiceClient, pollPeriod time.Duration) *Client { return &Client{ - client: client, + client: client, pollPeriod: pollPeriod, } } @@ -80,10 +80,10 @@ func (c *Client) StartPolling(startEpoch int64) (<-chan *ktpb.GetMutationsRespon return response, errChan } -func (s *Client) pollMutations(ctx context.Context, +func (c *Client) pollMutations(ctx context.Context, queryEpoch int64, opts ...grpc.CallOption) (*ktpb.GetMutationsResponse, error) { - response, err := s.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ + response, err := c.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ PageSize: pageSize, Epoch: queryEpoch, }, opts...) @@ -94,7 +94,7 @@ func (s *Client) pollMutations(ctx context.Context, // Page if necessary: query all mutations in the current epoch for response.GetNextPageToken() != "" { req := &ktpb.GetMutationsRequest{PageSize: pageSize} - resp, err := s.client.GetMutations(ctx, req, opts...) + resp, err := c.client.GetMutations(ctx, req, opts...) if err != nil { return nil, err } diff --git a/impl/monitor/server.go b/impl/monitor/server.go index 2af9a3173..a00488b80 100644 --- a/impl/monitor/server.go +++ b/impl/monitor/server.go @@ -1,3 +1,24 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package monitor implements the monitor service. A monitor repeatedly polls a +// key-transparency server's Mutations API and signs Map Roots if it could +// reconstruct +// clients can query. + +// Package monitor contains an implementation of a Monitor server which can be +// queried for monitoring results. package monitor import ( @@ -67,8 +88,8 @@ func (s *Server) getResponseByRevision(epoch int64) (*mopb.GetMonitoringResponse } if len(res.Errors) > 0 { - for _, err := range resp.Errors { - resp.Errors = append(resp.Errors, err) + for _, err := range res.Errors { + resp.Errors = append(resp.Errors, err.Error()) } // data to replay the verification steps: resp.ErrorData = res.Response diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go index 6a7fa1745..4df87eba0 100644 --- a/vendor/github.com/pelletier/go-toml/tomltree_write.go +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -4,11 +4,11 @@ import ( "bytes" "fmt" "io" + "reflect" "sort" "strconv" "strings" "time" - "reflect" ) // encodes a string to a TOML-compliant string value diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index 31b41a6b2..ee1e6c6b7 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -53,7 +53,7 @@ func init() { type remoteConfigFactory interface { Get(rp RemoteProvider) (io.Reader, error) Watch(rp RemoteProvider) (io.Reader, error) - WatchChannel(rp RemoteProvider)(<-chan *RemoteResponse, chan bool) + WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool) } // RemoteConfig is optional, see the remote package From 16724f5f40fbf51d580ea0642a7a7ba17b41f6ab Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 23 Aug 2017 16:38:49 -0400 Subject: [PATCH 34/46] renamed API urls --- .../monitor_v1_types/monitor_v1_types.pb.go | 59 +++++++++++-------- .../monitor_v1_types/monitor_v1_types.proto | 10 +++- impl/monitor/server.go | 2 +- .../monitor_v1_service.pb.go | 37 ++++++------ .../monitor_v1_service.pb.gw.go | 41 +++++++++++-- .../monitor_v1_service.proto | 8 +-- 6 files changed, 101 insertions(+), 56 deletions(-) diff --git a/core/proto/monitor_v1_types/monitor_v1_types.pb.go b/core/proto/monitor_v1_types/monitor_v1_types.pb.go index 35dec6287..79762a88f 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.pb.go +++ b/core/proto/monitor_v1_types/monitor_v1_types.pb.go @@ -35,9 +35,12 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. type GetMonitoringRequest struct { - // start specifies the start epoch number from which monitoring results will - // be returned (ranging from [start, latestObserved] and starting at 1). - Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + // epoch specifies the for which the monitoring results will + // be returned (epochs start at 1). + Epoch int64 `protobuf:"varint,1,opt,name=epoch" json:"epoch,omitempty"` + // ktURL is the URL of the keytransparency server for which the monitoring + // result will be returned. + Kt_URL string `protobuf:"bytes,2,opt,name=kt_URL,json=ktURL" json:"kt_URL,omitempty"` } func (m *GetMonitoringRequest) Reset() { *m = GetMonitoringRequest{} } @@ -45,13 +48,20 @@ func (m *GetMonitoringRequest) String() string { return proto.Compact func (*GetMonitoringRequest) ProtoMessage() {} func (*GetMonitoringRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (m *GetMonitoringRequest) GetStart() int64 { +func (m *GetMonitoringRequest) GetEpoch() int64 { if m != nil { - return m.Start + return m.Epoch } return 0 } +func (m *GetMonitoringRequest) GetKt_URL() string { + if m != nil { + return m.Kt_URL + } + return "" +} + type GetMonitoringResponse struct { // smr contains the map root for the sparse Merkle Tree signed with the // monitor's key on success. If the checks were not successful the @@ -111,23 +121,24 @@ func init() { func init() { proto.RegisterFile("monitor_v1_types.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 281 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x41, 0x4b, 0x03, 0x31, - 0x10, 0x85, 0xa9, 0xab, 0x85, 0x46, 0x10, 0x09, 0xb5, 0x2e, 0x3d, 0x95, 0x9e, 0x2a, 0x48, 0xd6, - 0xea, 0x5f, 0x10, 0x3c, 0xd5, 0x43, 0xf4, 0xbe, 0x4c, 0xdb, 0x61, 0x0d, 0x76, 0x33, 0x31, 0x33, - 0x2d, 0xf4, 0xb7, 0xfa, 0x67, 0x64, 0xb3, 0xed, 0x1e, 0x16, 0xbc, 0x65, 0xe6, 0x7b, 0x99, 0xf7, - 0x78, 0x6a, 0x52, 0x93, 0x77, 0x42, 0xb1, 0x3c, 0x2c, 0x4b, 0x39, 0x06, 0x64, 0x13, 0x22, 0x09, - 0xe9, 0xdb, 0xd3, 0xde, 0x1c, 0x96, 0x26, 0xed, 0xa7, 0xdb, 0xca, 0xc9, 0xd7, 0x7e, 0x6d, 0x36, - 0x54, 0x17, 0x15, 0x51, 0xb5, 0xc3, 0xe2, 0x1b, 0x8f, 0x12, 0xc1, 0x73, 0x80, 0x88, 0x7e, 0x73, - 0x2c, 0x36, 0x14, 0xb1, 0x48, 0xff, 0xfb, 0xa8, 0x3b, 0xff, 0x2f, 0x68, 0x7d, 0xa7, 0x37, 0x12, - 0xdd, 0x6e, 0xe7, 0xc0, 0xb7, 0xf3, 0xfc, 0x51, 0x8d, 0xdf, 0x50, 0x56, 0x6d, 0x18, 0xe7, 0x2b, - 0x8b, 0x3f, 0x7b, 0x64, 0xd1, 0x63, 0x75, 0xc5, 0x02, 0x51, 0xf2, 0xc1, 0x6c, 0xb0, 0xc8, 0x6c, - 0x3b, 0xcc, 0x7f, 0x07, 0xea, 0xae, 0x27, 0xe7, 0x40, 0x9e, 0x51, 0x3f, 0xa8, 0x8c, 0xeb, 0x98, - 0xd4, 0xd7, 0xcf, 0xf7, 0xa6, 0x73, 0xf9, 0x70, 0x95, 0xc7, 0xed, 0x0a, 0x82, 0x25, 0x12, 0xdb, - 0x68, 0xf4, 0x93, 0x1a, 0x33, 0xa2, 0x2f, 0xc5, 0xd5, 0xc8, 0x02, 0x75, 0x28, 0x3d, 0x78, 0xe2, - 0xfc, 0x22, 0x39, 0xe9, 0x86, 0x7d, 0x9e, 0xd1, 0x7b, 0x43, 0xf4, 0x44, 0x0d, 0x31, 0x46, 0x8a, - 0x9c, 0x67, 0xb3, 0x6c, 0x31, 0xb2, 0xa7, 0x49, 0xaf, 0x94, 0x4a, 0xaf, 0x72, 0x0b, 0x02, 0xf9, - 0x65, 0xf2, 0x36, 0xa6, 0xd7, 0x40, 0xd7, 0xb0, 0x69, 0x92, 0xef, 0x05, 0xc4, 0x91, 0xe7, 0x73, - 0x70, 0x3b, 0x4a, 0x17, 0x5e, 0x41, 0x60, 0x3d, 0x4c, 0x95, 0xbc, 0xfc, 0x05, 0x00, 0x00, 0xff, - 0xff, 0x82, 0xa2, 0x4b, 0x16, 0xb4, 0x01, 0x00, 0x00, + // 301 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xc1, 0x6b, 0xc2, 0x30, + 0x18, 0xc5, 0xe9, 0x3a, 0x05, 0x33, 0x18, 0x23, 0xa8, 0x2b, 0x9e, 0xc4, 0x93, 0xbb, 0xa4, 0x73, + 0xfb, 0x13, 0x36, 0xd8, 0x45, 0x77, 0xc8, 0xe6, 0x39, 0xc4, 0xfa, 0x51, 0x83, 0x36, 0x5f, 0x96, + 0x7c, 0x0a, 0xfe, 0xad, 0xfb, 0x67, 0x46, 0x53, 0xed, 0xa1, 0xb0, 0x5b, 0xdf, 0xf7, 0x6b, 0xde, + 0x7b, 0x3c, 0x36, 0xae, 0xd0, 0x1a, 0x42, 0xaf, 0x4e, 0x0b, 0x45, 0x67, 0x07, 0x41, 0x38, 0x8f, + 0x84, 0xfc, 0xe1, 0x72, 0x17, 0xa7, 0x85, 0x88, 0xf7, 0xc9, 0xb6, 0x34, 0xb4, 0x3b, 0x6e, 0x44, + 0x81, 0x55, 0x5e, 0x22, 0x96, 0x07, 0xc8, 0xf7, 0x70, 0x26, 0xaf, 0x6d, 0x70, 0xda, 0x83, 0x2d, + 0xce, 0x79, 0x81, 0x1e, 0xf2, 0xf8, 0xbe, 0x8b, 0x5a, 0xfb, 0x7f, 0x41, 0x93, 0x3b, 0xb9, 0x27, + 0x6f, 0x0e, 0x07, 0xa3, 0x6d, 0xa3, 0x67, 0x6f, 0x6c, 0xf8, 0x01, 0xb4, 0x6a, 0xca, 0x18, 0x5b, + 0x4a, 0xf8, 0x39, 0x42, 0x20, 0x3e, 0x64, 0x3d, 0x70, 0x58, 0xec, 0xb2, 0x64, 0x9a, 0xcc, 0x53, + 0xd9, 0x08, 0x3e, 0x62, 0xfd, 0x3d, 0xa9, 0xb5, 0x5c, 0x66, 0x37, 0xd3, 0x64, 0x3e, 0x90, 0xbd, + 0x3d, 0xad, 0xe5, 0x72, 0xf6, 0x9b, 0xb0, 0x51, 0xc7, 0x25, 0x38, 0xb4, 0x01, 0xf8, 0x13, 0x4b, + 0x43, 0xe5, 0xa3, 0xc9, 0xdd, 0xcb, 0xa3, 0x68, 0xc3, 0xbf, 0x4c, 0x69, 0x61, 0xbb, 0xd2, 0x4e, + 0x22, 0x92, 0xac, 0xff, 0xe1, 0xcf, 0x6c, 0x18, 0x00, 0xac, 0x22, 0x53, 0x41, 0x20, 0x5d, 0x39, + 0x65, 0xb5, 0xc5, 0x10, 0x93, 0x52, 0xc9, 0x6b, 0xf6, 0x7d, 0x45, 0x9f, 0x35, 0xe1, 0x63, 0xd6, + 0x07, 0xef, 0xd1, 0x87, 0x2c, 0x9d, 0xa6, 0xf3, 0x81, 0xbc, 0x28, 0xbe, 0x62, 0x2c, 0x7e, 0xa9, + 0xad, 0x26, 0x9d, 0xdd, 0xc6, 0x6c, 0x21, 0x3a, 0xc3, 0xb4, 0xc3, 0x8b, 0xba, 0xf9, 0x91, 0x34, + 0x19, 0xb4, 0xe1, 0x5a, 0x5c, 0x0e, 0xa2, 0xc3, 0xbb, 0x26, 0xbd, 0xe9, 0xc7, 0xa5, 0x5e, 0xff, + 0x02, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xdc, 0x29, 0x97, 0xcb, 0x01, 0x00, 0x00, } diff --git a/core/proto/monitor_v1_types/monitor_v1_types.proto b/core/proto/monitor_v1_types/monitor_v1_types.proto index 4fdacef17..48a964601 100644 --- a/core/proto/monitor_v1_types/monitor_v1_types.proto +++ b/core/proto/monitor_v1_types/monitor_v1_types.proto @@ -23,9 +23,13 @@ import "trillian.proto"; // GetMonitoringRequest contains the input parameters of the GetMonitoring APIs. message GetMonitoringRequest { - // start specifies the start epoch number from which monitoring results will - // be returned (ranging from [start, latestObserved] and starting at 1). - int64 start = 1; + // epoch specifies the for which the monitoring results will + // be returned (epochs start at 1). + int64 epoch = 1; + + // ktURL is the URL of the keytransparency server for which the monitoring + // result will be returned. + string kt_URL = 2; } message GetMonitoringResponse { diff --git a/impl/monitor/server.go b/impl/monitor/server.go index a00488b80..84118b608 100644 --- a/impl/monitor/server.go +++ b/impl/monitor/server.go @@ -72,7 +72,7 @@ func (s *Server) GetSignedMapRoot(ctx context.Context, in *mopb.GetMonitoringReq // mutations from the previous to the current epoch it won't sign the map root // and additional data will be provided to reproduce the failure. func (s *Server) GetSignedMapRootByRevision(ctx context.Context, in *mopb.GetMonitoringRequest) (*mopb.GetMonitoringResponse, error) { - return s.getResponseByRevision(in.GetStart()) + return s.getResponseByRevision(in.GetEpoch()) } func (s *Server) getResponseByRevision(epoch int64) (*mopb.GetMonitoringResponse, error) { diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go index 66c84e6aa..1f6e270b0 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.go @@ -176,22 +176,23 @@ var _MonitorService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("monitor_v1_service.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 261 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x90, 0xaf, 0x4e, 0x03, 0x41, - 0x10, 0xc6, 0xd3, 0x0a, 0xc4, 0x09, 0x42, 0x36, 0xfc, 0xcb, 0xa5, 0x18, 0x04, 0xb8, 0x9b, 0x14, - 0x1c, 0x12, 0x53, 0x55, 0x73, 0xc5, 0x37, 0xdb, 0x63, 0xb2, 0x6c, 0xe8, 0xcd, 0x2c, 0x3b, 0xd3, - 0x4d, 0x2e, 0x04, 0x01, 0x1a, 0xc7, 0x23, 0xf0, 0x48, 0xbc, 0x02, 0x0f, 0x42, 0x72, 0xb7, 0xa2, - 0x80, 0xc0, 0x60, 0xe7, 0x9b, 0xef, 0x37, 0xbf, 0x4c, 0x71, 0xdc, 0x32, 0x79, 0xe5, 0xb8, 0x4c, - 0xd3, 0xa5, 0x60, 0x4c, 0xbe, 0xc1, 0x2a, 0x44, 0x56, 0x36, 0x26, 0x27, 0x55, 0x9a, 0x56, 0x39, - 0x29, 0x6f, 0x9c, 0xd7, 0xbb, 0xcd, 0xaa, 0x6a, 0xb8, 0x05, 0xc7, 0xec, 0xd6, 0x08, 0xf7, 0xd8, - 0x69, 0xb4, 0x24, 0xc1, 0x46, 0xa4, 0xa6, 0x83, 0x86, 0x23, 0x42, 0x4f, 0x80, 0x2d, 0xb4, 0x76, - 0x01, 0xe5, 0xd7, 0x60, 0xb8, 0x54, 0x4e, 0x32, 0xca, 0x06, 0x0f, 0x96, 0x88, 0xd5, 0xaa, 0x67, - 0xca, 0xe9, 0xc5, 0xfb, 0xb8, 0xd8, 0x9d, 0x0f, 0xc5, 0xc5, 0xa0, 0x61, 0x9e, 0x47, 0xc5, 0xde, - 0x0c, 0x75, 0xe1, 0x1d, 0xe1, 0xed, 0xdc, 0x86, 0x9a, 0x59, 0xcd, 0x59, 0xb5, 0x25, 0x3c, 0xe0, - 0x67, 0xa8, 0xb9, 0xe9, 0xc9, 0xd5, 0xf8, 0xb0, 0x41, 0xd1, 0xf2, 0xfc, 0xcf, 0x3d, 0x09, 0x4c, - 0x82, 0xa7, 0x93, 0x97, 0x8f, 0xcf, 0xb7, 0xf1, 0xa1, 0xd9, 0x87, 0x34, 0x85, 0xd6, 0x06, 0x88, - 0xcc, 0x2a, 0x57, 0x6b, 0xab, 0x28, 0x6a, 0x5e, 0x47, 0x45, 0xf9, 0xd3, 0xe1, 0xba, 0xab, 0x31, - 0x79, 0xf1, 0x4c, 0xff, 0x6f, 0x73, 0xd2, 0xdb, 0x1c, 0x99, 0x83, 0x6f, 0x36, 0xf0, 0x28, 0x6a, - 0xa3, 0x3e, 0xad, 0x76, 0xfa, 0x67, 0x5d, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x85, 0xab, - 0x1e, 0xd0, 0x01, 0x00, 0x00, + // 273 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x90, 0xb1, 0x4e, 0xc3, 0x40, + 0x0c, 0x86, 0xd5, 0x0e, 0x0c, 0x19, 0x10, 0xba, 0x09, 0x45, 0x4c, 0x0c, 0x14, 0x18, 0x62, 0x0a, + 0x1b, 0x23, 0x4b, 0x17, 0xba, 0xa4, 0x30, 0x47, 0xd7, 0x60, 0xa5, 0xa7, 0x26, 0xf6, 0x71, 0x76, + 0x22, 0x45, 0x55, 0x17, 0x5e, 0x01, 0x76, 0x9e, 0x87, 0x99, 0x57, 0xe0, 0x41, 0x90, 0x92, 0x20, + 0x55, 0x30, 0x74, 0x61, 0xf5, 0xef, 0xff, 0xf3, 0x27, 0x47, 0xc7, 0x15, 0x93, 0x53, 0x0e, 0x59, + 0x33, 0xcd, 0x04, 0x43, 0xe3, 0x72, 0x4c, 0x7c, 0x60, 0x65, 0x63, 0x86, 0x24, 0x69, 0xa6, 0xc9, + 0x90, 0xc4, 0x0f, 0x85, 0xd3, 0x55, 0xbd, 0x4c, 0x72, 0xae, 0xa0, 0x60, 0x2e, 0x4a, 0x84, 0x35, + 0xb6, 0x1a, 0x2c, 0x89, 0xb7, 0x01, 0x29, 0x6f, 0x21, 0xe7, 0x80, 0xd0, 0x11, 0x60, 0x07, 0xad, + 0xad, 0x47, 0xf9, 0x33, 0xe8, 0x2f, 0xc5, 0x27, 0x03, 0xca, 0x7a, 0x07, 0x96, 0x88, 0xd5, 0xaa, + 0x63, 0x1a, 0xd2, 0xeb, 0x8f, 0x71, 0x74, 0x38, 0xef, 0x8b, 0x8b, 0x5e, 0xc3, 0xbc, 0x8d, 0xa2, + 0xa3, 0x19, 0xea, 0xc2, 0x15, 0x84, 0x4f, 0x73, 0xeb, 0x53, 0x66, 0x35, 0x67, 0xc9, 0x8e, 0x70, + 0x8f, 0x9f, 0xa1, 0x0e, 0x4d, 0x47, 0x45, 0x8a, 0xcf, 0x35, 0x8a, 0xc6, 0x93, 0xbd, 0x7b, 0xe2, + 0x99, 0x04, 0x4f, 0xe1, 0xe5, 0xf3, 0xeb, 0x75, 0x7c, 0x61, 0x26, 0xd0, 0x4c, 0x7f, 0xd4, 0x61, + 0xb3, 0xd6, 0xec, 0x31, 0xbd, 0xdf, 0x42, 0x65, 0x3d, 0x04, 0x94, 0xba, 0x54, 0xb9, 0x2d, 0xad, + 0xa2, 0xa8, 0x79, 0x1f, 0x45, 0xf1, 0x6f, 0xad, 0xbb, 0x36, 0xc5, 0xc6, 0x89, 0x63, 0xfa, 0x7f, + 0xc1, 0xab, 0x4e, 0xf0, 0xd2, 0x9c, 0xef, 0x13, 0x84, 0x0d, 0x7a, 0xce, 0x57, 0xdb, 0xe5, 0x41, + 0xf7, 0xd2, 0x9b, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x96, 0x6d, 0xf3, 0xf6, 0x01, 0x00, + 0x00, } diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go index 26786982a..69269299b 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go +++ b/impl/proto/monitor_v1_service/monitor_v1_service.pb.gw.go @@ -29,13 +29,31 @@ var _ = runtime.String var _ = utilities.NewDoubleArray var ( - filter_MonitorService_GetSignedMapRoot_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + filter_MonitorService_GetSignedMapRoot_0 = &utilities.DoubleArray{Encoding: map[string]int{"kt_URL": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} ) func request_MonitorService_GetSignedMapRoot_0(ctx context.Context, marshaler runtime.Marshaler, client MonitorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq monitor_v1_types.GetMonitoringRequest var metadata runtime.ServerMetadata + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["kt_URL"] + if !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", "kt_URL") + } + + protoReq.Kt_URL, err = runtime.String(val) + + if err != nil { + return nil, metadata, err + } + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_MonitorService_GetSignedMapRoot_0); err != nil { return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err) } @@ -56,12 +74,23 @@ func request_MonitorService_GetSignedMapRootByRevision_0(ctx context.Context, ma _ = err ) - val, ok = pathParams["start"] + val, ok = pathParams["kt_URL"] + if !ok { + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", "kt_URL") + } + + protoReq.Kt_URL, err = runtime.String(val) + + if err != nil { + return nil, metadata, err + } + + val, ok = pathParams["epoch"] if !ok { - return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", "start") + return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", "epoch") } - protoReq.Start, err = runtime.Int64(val) + protoReq.Epoch, err = runtime.Int64(val) if err != nil { return nil, metadata, err @@ -162,9 +191,9 @@ func RegisterMonitorServiceHandler(ctx context.Context, mux *runtime.ServeMux, c } var ( - pattern_MonitorService_GetSignedMapRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "map", "roots"}, "latest")) + pattern_MonitorService_GetSignedMapRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4}, []string{"v1", "monitor", "kt_URL", "map", "results"}, "latest")) - pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "map", "roots", "start"}, "")) + pattern_MonitorService_GetSignedMapRootByRevision_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"v1", "monitor", "kt_URL", "map", "results", "epoch"}, "")) ) var ( diff --git a/impl/proto/monitor_v1_service/monitor_v1_service.proto b/impl/proto/monitor_v1_service/monitor_v1_service.proto index 509afe90a..eae54884a 100644 --- a/impl/proto/monitor_v1_service/monitor_v1_service.proto +++ b/impl/proto/monitor_v1_service/monitor_v1_service.proto @@ -28,8 +28,8 @@ import "google/api/annotations.proto"; // // - Signed Map Roots can be collected using the GetSignedMapRoot APIs. // - Monitor resources are named: -// - /v1/map/roots/* -// - /v1/map/roots:latest +// - /v1/monitor/{kt-url}/map/results/{epoch} +// - /v1/monitor/{kt-url}/map/results:latest // service MonitorService { // GetSignedMapRoot returns the latest valid signed map root the monitor @@ -42,7 +42,7 @@ service MonitorService { // additional data will be provided to reproduce the failure. rpc GetSignedMapRoot(monitor.v1.types.GetMonitoringRequest) returns (monitor.v1.types.GetMonitoringResponse) { - option (google.api.http) = { get: "/v1/map/roots:latest" }; + option (google.api.http) = { get: "/v1/monitor/{kt_URL}/map/results:latest" }; } // GetSignedMapRootByRevision works similar to GetSignedMapRoot but returns @@ -54,7 +54,7 @@ service MonitorService { // and additional data will be provided to reproduce the failure. rpc GetSignedMapRootByRevision(monitor.v1.types.GetMonitoringRequest) returns(monitor.v1.types.GetMonitoringResponse) { - option (google.api.http) = { get: "/v1/map/roots/{start}" }; + option (google.api.http) = { get: "/v1/monitor/{kt_URL}/map/results/{epoch}" }; } } From 2152cd495955915c1756cbbf7183d522d493f999 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Wed, 23 Aug 2017 18:58:27 -0400 Subject: [PATCH 35/46] WIP: reintroduce verification --- core/monitor/monitor.go | 4 +- core/monitor/verify.go | 173 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 5 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 419936b28..72c941bcc 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -39,8 +39,8 @@ type Monitor struct { logVerifier merkle.LogVerifier signer *tcrypto.Signer // TODO(ismail): update last trusted signed log root - //trusted trillian.SignedLogRoot - store *storage.Storage + trusted *trillian.SignedLogRoot + store *storage.Storage } // New creates a new instance of the monitor. diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 1deadfb45..50374af31 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -18,14 +18,181 @@ package monitor import ( + "bytes" + "errors" + "math/big" + + "github.com/golang/glog" + + "github.com/google/trillian/merkle" + "github.com/google/trillian/storage" + + tcrypto "github.com/google/trillian/crypto" + + "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" ) -// verifyMutationsResponse verifies a response received by the GetMutations API. +var ( + // ErrInvalidMutation occurs when verification failed because of an invalid + // mutation. + ErrInvalidMutation = errors.New("invalid mutation") + // ErrNotMatchingMapRoot occurs when the reconstructed root differs from the one + // we received from the server. + ErrNotMatchingMapRoot = errors.New("recreated root does not match") + // ErrInvalidMapSignature occurs if the map roots signature does not verify. + ErrInvalidMapSignature = errors.New("invalid signature on map root") + // ErrInvalidLogSignature occurs if the log roots signature does not verify. + ErrInvalidLogSignature = errors.New("invalid signature on log root") + // ErrInconsistentProofs occurs when the server returned different hashes + // for the same inclusion proof node in the tree. + ErrInconsistentProofs = errors.New("inconsistent inclusion proofs") + // ErrInvalidConsistencyProof occurs when the log consistency proof does not + // verify. + ErrInvalidConsistencyProof = errors.New("invalid log consistency proof") +) + +// verifyResponse verifies a response received by the GetMutations API. // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response -// because of the max. page size. If any verification check failed it returns -// an error. +// because of the max. page size. func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { + errList := make([]error, 0) + // copy of singed map root + smr := *in.GetSmr() + // reset to the state before it was signed: + smr.Signature = nil + // verify signature on map root: + if err := tcrypto.VerifyObject(m.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { + glog.Infof("couldn't verify signature on map root: %v", err) + errList = append(errList, ErrInvalidMapSignature) + } + + logRoot := in.GetLogRoot() + // Verify SignedLogRoot signature. + hash := tcrypto.HashLogRoot(*logRoot) + if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { + glog.Infof("couldn't verify signature on log root: %v", err) + errList = append(errList, ErrInvalidLogSignature) + } + + if m.trusted != nil { + // Verify consistency proof: + err := m.logVerifier.VerifyConsistencyProof( + m.trusted.TreeSize, logRoot.TreeSize, + m.trusted.RootHash, logRoot.RootHash, + in.GetLogConsistency()) + if err != nil { + errList = append(errList, ErrInvalidConsistencyProof) + } + } else { + // trust the first log root we see, don't verify anything yet + m.trusted = in.GetLogRoot() + } + + // m.logVerifier.VerifyInclusionProof() + // + // retrieve the old root hash from storage! + monRes, err := m.store.Get(in.Epoch - 1) + if err != nil { + glog.Infof("Could not retrieve previous monitoring result: %v", err) + } + // we need the old root for verifying the inclusion of the old leafs in the + // previous epoch. Storage always stores the mutations response independent + // from if the checks succeeded or not. + oldRoot := monRes.Response.GetSmr().GetRootHash() + + if err := m.verifyMutations(in.GetMutations(), oldRoot, + in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { + errList = append(errList, err...) + } + + return errList +} + +func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoot []byte, mapID int64) []error { + errList := make([]error, 0) + mutator := entry.New() + oldProofNodes := make(map[string][]byte) + newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) + + for _, mut := range muts { + oldLeaf, err := entry.FromLeafValue(mut.GetProof().GetLeaf().GetLeafValue()) + if err != nil { + errList = append(errList, ErrInvalidMutation) + } + + // verify that the provided leaf’s inclusion proof goes to epoch e-1: + index := mut.GetProof().GetLeaf().GetIndex() + leafHash := mut.GetProof().GetLeaf().GetLeafHash() + if err := merkle.VerifyMapInclusionProof(mapID, index, + leafHash, oldRoot, mut.GetProof().GetInclusion(), m.hasher); err != nil { + glog.Infof("VerifyMapInclusionProof(%x): %v", index, err) + errList = append(errList, err) + } + + // compute the new leaf + newLeaf, err := mutator.Mutate(oldLeaf, mut.GetUpdate()) + if err != nil { + errList = append(errList, ErrInvalidMutation) + } + newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, m.hasher.BitLen()) + newLeafHash := m.hasher.HashLeaf(mapID, index, newLeaf) + newLeaves = append(newLeaves, merkle.HStar2LeafHash{ + Index: newLeafnID.BigInt(), + LeafHash: newLeafHash, + }) + + // store the proof hashes locally to recompute the tree below: + sibIDs := newLeafnID.Siblings() + // TODO(ismail) iterate over the sibIDs instead! + for level, proof := range mut.GetProof().GetInclusion() { + pID := sibIDs[level] + if p, ok := oldProofNodes[pID.String()]; ok { + // sanity check: for each mut overlapping proof nodes should be + // equal: + if !bytes.Equal(p, proof) { + // TODO(ismail): remove this check and this error type as + // soon as the server does not return interior proof nodes + // multiple times + // + // this is really odd and should never happen + errList = append(errList, ErrInconsistentProofs) + } + } else { + oldProofNodes[pID.String()] = proof + } + } + } + if err := m.validateMapRoot(expectedNewRoot, mapID, newLeaves, oldProofNodes); err != nil { + errList = append(errList, err) + } + + return errList +} + +func (m *Monitor) validateMapRoot(expectedRoot []byte, mapID int64, mutatedLeaves []merkle.HStar2LeafHash, oldProofNodes map[string][]byte) error { + // compute the new root using local intermediate hashes from epoch e + // (above proof hashes): + hs2 := merkle.NewHStar2(mapID, m.hasher) + newRoot, err := hs2.HStar2Nodes([]byte{}, m.hasher.Size(), mutatedLeaves, + func(depth int, index *big.Int) ([]byte, error) { + nID := storage.NewNodeIDFromBigInt(depth, index, m.hasher.BitLen()) + if p, ok := oldProofNodes[nID.String()]; ok { + return p, nil + } + return nil, nil + }, nil) + + if err != nil { + glog.Errorf("hs2.HStar2Nodes(_): %v", err) + // TODO(ismail): figure out what to return here + } + + // verify rootHash + if !bytes.Equal(newRoot, expectedRoot) { + return ErrNotMatchingMapRoot + } + return nil } From e6e9a7d4d1ee146f4d93bb381cc7434054a21dca Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 12:26:11 -0400 Subject: [PATCH 36/46] more verification steps --- core/monitor/monitor.go | 11 +++-- core/monitor/verify.go | 102 ++++++++++++++++++++++++++-------------- 2 files changed, 73 insertions(+), 40 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 72c941bcc..640f03633 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -33,14 +33,14 @@ import ( // Monitor holds the internal state for a monitor accessing the mutations API // and for verifying its responses. type Monitor struct { - hasher hashers.MapHasher + logHasher hashers.LogHasher + mapHasher hashers.MapHasher logPubKey crypto.PublicKey mapPubKey crypto.PublicKey logVerifier merkle.LogVerifier signer *tcrypto.Signer - // TODO(ismail): update last trusted signed log root - trusted *trillian.SignedLogRoot - store *storage.Storage + trusted *trillian.SignedLogRoot + store *storage.Storage } // New creates a new instance of the monitor. @@ -54,7 +54,8 @@ func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage return nil, fmt.Errorf("Failed creating MapHasher: %v", err) } return &Monitor{ - hasher: mapHasher, + mapHasher: mapHasher, + logHasher: logHasher, logVerifier: merkle.NewLogVerifier(logHasher), logPubKey: logTree.GetPublicKey(), mapPubKey: mapTree.GetPublicKey(), diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 50374af31..07811fedc 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -19,6 +19,7 @@ package monitor import ( "bytes" + "encoding/json" "errors" "math/big" @@ -37,8 +38,8 @@ var ( // ErrInvalidMutation occurs when verification failed because of an invalid // mutation. ErrInvalidMutation = errors.New("invalid mutation") - // ErrNotMatchingMapRoot occurs when the reconstructed root differs from the one - // we received from the server. + // ErrNotMatchingMapRoot occurs when the reconstructed root differs from the + // one we received from the server. ErrNotMatchingMapRoot = errors.New("recreated root does not match") // ErrInvalidMapSignature occurs if the map roots signature does not verify. ErrInvalidMapSignature = errors.New("invalid signature on map root") @@ -47,9 +48,12 @@ var ( // ErrInconsistentProofs occurs when the server returned different hashes // for the same inclusion proof node in the tree. ErrInconsistentProofs = errors.New("inconsistent inclusion proofs") - // ErrInvalidConsistencyProof occurs when the log consistency proof does not - // verify. - ErrInvalidConsistencyProof = errors.New("invalid log consistency proof") + // ErrInvalidLogConsistencyProof occurs when the log consistency proof does + // not verify. + ErrInvalidLogConsistencyProof = errors.New("invalid log consistency proof") + // ErrInvalidLogInclusion occurs if the inclusion proof for the signed map + // root into the log does not verify. + ErrInvalidLogInclusion = errors.New("invalid log inclusion proof") ) // verifyResponse verifies a response received by the GetMutations API. @@ -58,15 +62,10 @@ var ( // because of the max. page size. func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { errList := make([]error, 0) - // copy of singed map root - smr := *in.GetSmr() - // reset to the state before it was signed: - smr.Signature = nil - // verify signature on map root: - if err := tcrypto.VerifyObject(m.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { - glog.Infof("couldn't verify signature on map root: %v", err) - errList = append(errList, ErrInvalidMapSignature) - } + + // + // log verification + // logRoot := in.GetLogRoot() // Verify SignedLogRoot signature. @@ -76,32 +75,67 @@ func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error errList = append(errList, ErrInvalidLogSignature) } - if m.trusted != nil { + if m.trusted != nil && m.trusted.GetTreeSize() > 0 { // Verify consistency proof: err := m.logVerifier.VerifyConsistencyProof( m.trusted.TreeSize, logRoot.TreeSize, m.trusted.RootHash, logRoot.RootHash, in.GetLogConsistency()) if err != nil { - errList = append(errList, ErrInvalidConsistencyProof) + errList = append(errList, ErrInvalidLogConsistencyProof) } } else { // trust the first log root we see, don't verify anything yet m.trusted = in.GetLogRoot() } - // m.logVerifier.VerifyInclusionProof() + b, err := json.Marshal(in.GetSmr()) + if err != nil { + glog.Errorf("json.Marshal(): %v", err) + // Encoding error + } + leafIndex := in.GetSmr().GetMapRevision() + treeSize := in.GetLogRoot().GetTreeSize() + leafHash := m.logHasher.HashLeaf(b) + err = m.logVerifier.VerifyInclusionProof( + leafIndex, + treeSize, + in.GetLogInclusion(), + in.GetLogRoot().GetRootHash(), + leafHash) + if err != nil { + glog.Errorf("m.logVerifier.VerifyInclusionProof((%v, %v, _): %v", leafIndex, treeSize, err) + errList = append(errList, ErrInvalidLogInclusion) + } + // + // map verification + // + + // copy of singed map root + smr := *in.GetSmr() + // reset to the state before it was signed: + smr.Signature = nil + // verify signature on map root: + if err := tcrypto.VerifyObject(m.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { + glog.Infof("couldn't verify signature on map root: %v", err) + errList = append(errList, ErrInvalidMapSignature) + } + // retrieve the old root hash from storage! monRes, err := m.store.Get(in.Epoch - 1) if err != nil { glog.Infof("Could not retrieve previous monitoring result: %v", err) } + + // + // mutations verification: + // + // we need the old root for verifying the inclusion of the old leafs in the // previous epoch. Storage always stores the mutations response independent // from if the checks succeeded or not. oldRoot := monRes.Response.GetSmr().GetRootHash() - if err := m.verifyMutations(in.GetMutations(), oldRoot, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { errList = append(errList, err...) @@ -126,9 +160,9 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo index := mut.GetProof().GetLeaf().GetIndex() leafHash := mut.GetProof().GetLeaf().GetLeafHash() if err := merkle.VerifyMapInclusionProof(mapID, index, - leafHash, oldRoot, mut.GetProof().GetInclusion(), m.hasher); err != nil { + leafHash, oldRoot, mut.GetProof().GetInclusion(), m.mapHasher); err != nil { glog.Infof("VerifyMapInclusionProof(%x): %v", index, err) - errList = append(errList, err) + errList = append(errList, ErrInvalidMutation) } // compute the new leaf @@ -136,8 +170,8 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo if err != nil { errList = append(errList, ErrInvalidMutation) } - newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, m.hasher.BitLen()) - newLeafHash := m.hasher.HashLeaf(mapID, index, newLeaf) + newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, m.mapHasher.BitLen()) + newLeafHash := m.mapHasher.HashLeaf(mapID, index, newLeaf) newLeaves = append(newLeaves, merkle.HStar2LeafHash{ Index: newLeafnID.BigInt(), LeafHash: newLeafHash, @@ -145,25 +179,23 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo // store the proof hashes locally to recompute the tree below: sibIDs := newLeafnID.Siblings() - // TODO(ismail) iterate over the sibIDs instead! - for level, proof := range mut.GetProof().GetInclusion() { - pID := sibIDs[level] - if p, ok := oldProofNodes[pID.String()]; ok { + proofs := mut.GetProof().GetInclusion() + for level, sibID := range sibIDs { + proof := proofs[level] + if p, ok := oldProofNodes[sibID.String()]; ok { // sanity check: for each mut overlapping proof nodes should be // equal: if !bytes.Equal(p, proof) { - // TODO(ismail): remove this check and this error type as - // soon as the server does not return interior proof nodes - // multiple times - // // this is really odd and should never happen errList = append(errList, ErrInconsistentProofs) } } else { - oldProofNodes[pID.String()] = proof + oldProofNodes[sibID.String()] = proof } + } } + if err := m.validateMapRoot(expectedNewRoot, mapID, newLeaves, oldProofNodes); err != nil { errList = append(errList, err) } @@ -174,10 +206,10 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo func (m *Monitor) validateMapRoot(expectedRoot []byte, mapID int64, mutatedLeaves []merkle.HStar2LeafHash, oldProofNodes map[string][]byte) error { // compute the new root using local intermediate hashes from epoch e // (above proof hashes): - hs2 := merkle.NewHStar2(mapID, m.hasher) - newRoot, err := hs2.HStar2Nodes([]byte{}, m.hasher.Size(), mutatedLeaves, + hs2 := merkle.NewHStar2(mapID, m.mapHasher) + newRoot, err := hs2.HStar2Nodes([]byte{}, m.mapHasher.Size(), mutatedLeaves, func(depth int, index *big.Int) ([]byte, error) { - nID := storage.NewNodeIDFromBigInt(depth, index, m.hasher.BitLen()) + nID := storage.NewNodeIDFromBigInt(depth, index, m.mapHasher.BitLen()) if p, ok := oldProofNodes[nID.String()]; ok { return p, nil } @@ -186,7 +218,7 @@ func (m *Monitor) validateMapRoot(expectedRoot []byte, mapID int64, mutatedLeave if err != nil { glog.Errorf("hs2.HStar2Nodes(_): %v", err) - // TODO(ismail): figure out what to return here + return ErrNotMatchingMapRoot } // verify rootHash From 1b14d9da502acd1a747dadadab9ea614e9b550be Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 17:13:17 -0400 Subject: [PATCH 37/46] first crack on the integration tests --- core/monitor/monitor.go | 4 +- core/monitor/verify.go | 18 ++++--- impl/monitor/client/client.go | 8 +-- integration/monitor_test.go | 95 +++++++++++++++++++++++++++++++++++ integration/testutil.go | 8 ++- 5 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 integration/monitor_test.go diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 640f03633..f9b850b0b 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -33,6 +33,7 @@ import ( // Monitor holds the internal state for a monitor accessing the mutations API // and for verifying its responses. type Monitor struct { + mapID int64 logHasher hashers.LogHasher mapHasher hashers.MapHasher logPubKey crypto.PublicKey @@ -54,6 +55,7 @@ func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage return nil, fmt.Errorf("Failed creating MapHasher: %v", err) } return &Monitor{ + mapID: mapTree.TreeId, mapHasher: mapHasher, logHasher: logHasher, logVerifier: merkle.NewLogVerifier(logHasher), @@ -71,7 +73,7 @@ func (m *Monitor) Process(resp *ktpb.GetMutationsResponse) error { var smr *trillian.SignedMapRoot var err error seen := time.Now().Unix() - errs := m.verifyMutationsResponse(resp) + errs := m.VerifyMutationsResponse(resp) if len(errs) == 0 { glog.Infof("Successfully verified mutations response for epoch: %v", resp.Epoch) smr, err = m.signMapRoot(resp) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 07811fedc..2d2f43b82 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -56,11 +56,11 @@ var ( ErrInvalidLogInclusion = errors.New("invalid log inclusion proof") ) -// verifyResponse verifies a response received by the GetMutations API. +// VerifyMutationsResponse verifies a response received by the GetMutations API. // Additionally to the response it takes a complete list of mutations. The list // of received mutations may differ from those included in the initial response // because of the max. page size. -func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { +func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error { errList := make([]error, 0) // @@ -135,10 +135,15 @@ func (m *Monitor) verifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // we need the old root for verifying the inclusion of the old leafs in the // previous epoch. Storage always stores the mutations response independent // from if the checks succeeded or not. - oldRoot := monRes.Response.GetSmr().GetRootHash() - if err := m.verifyMutations(in.GetMutations(), oldRoot, - in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { - errList = append(errList, err...) + var oldRoot []byte + if m.store.LatestEpoch() > 0 { + oldRoot = monRes.Response.GetSmr().GetRootHash() + if err := m.verifyMutations(in.GetMutations(), oldRoot, + in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { + errList = append(errList, err...) + } + } else { + // TODO oldRoot is the hash of the initial tree } return errList @@ -192,7 +197,6 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo } else { oldProofNodes[sibID.String()] = proof } - } } diff --git a/impl/monitor/client/client.go b/impl/monitor/client/client.go index 18245eb76..13e15be5e 100644 --- a/impl/monitor/client/client.go +++ b/impl/monitor/client/client.go @@ -64,9 +64,9 @@ func (c *Client) StartPolling(startEpoch int64) (<-chan *ktpb.GetMutationsRespon glog.Infof("Polling: %v", now) // time out if we exceed the poll period: ctx, _ := context.WithTimeout(context.Background(), c.pollPeriod) - monitorResp, err := c.pollMutations(ctx, epoch) + monitorResp, err := c.PollMutations(ctx, epoch) if err != nil { - glog.Infof("pollMutations(_): %v", err) + glog.Infof("PollMutations(_): %v", err) errChan <- err } else { // only write to results channel and increment epoch @@ -80,7 +80,9 @@ func (c *Client) StartPolling(startEpoch int64) (<-chan *ktpb.GetMutationsRespon return response, errChan } -func (c *Client) pollMutations(ctx context.Context, +// PollMutations polls GetMutationsResponses from the configured +// key-transparency server's mutations API. +func (c *Client) PollMutations(ctx context.Context, queryEpoch int64, opts ...grpc.CallOption) (*ktpb.GetMutationsResponse, error) { response, err := c.client.GetMutations(ctx, &ktpb.GetMutationsRequest{ diff --git a/integration/monitor_test.go b/integration/monitor_test.go new file mode 100644 index 000000000..c80faad97 --- /dev/null +++ b/integration/monitor_test.go @@ -0,0 +1,95 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package integration + +import ( + "context" + + "testing" + + "github.com/google/keytransparency/core/monitor" + "github.com/google/keytransparency/core/monitor/storage" + // kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + // spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" + mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" + "github.com/google/trillian/crypto" + "github.com/google/keytransparency/impl/monitor/client" + "github.com/google/trillian/crypto/keys/pem" + "time" + stestonly "github.com/google/trillian/storage/testonly" +) + +const ( + monitorPrivKey = `-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAV7H3qRi/cj/w04vEQBFjLdhcXRbZR4ouT5zaAy1XUHoAoGCCqGSM49 +AwEHoUQDQgAEqUDbATN2maGIm6YQLpjx67bYN1hxPPdF0VrPTZe36yQhH+GCwZQV +amFdON6OhjYnBmJWe4fVnbxny0PfpkvXtg== +-----END EC PRIVATE KEY-----` +) + +func TestMonitorEmptyStart(t *testing.T) { + bctx := context.Background() + env := NewEnv(t) + defer env.Close(t) + env.Client.RetryCount = 0 + + // setup monitor: + + // TODO(ismail) setup a proper log environment in the integration + // environment, then use GetDomainInfo here: + //c := spb.NewKeyTransparencyServiceClient(env.Conn) + //resp, err := c.GetDomainInfo(bctx, &kpb.GetDomainInfoRequest{}) + //if err != nil { + // t.Fatalf("Couldn't retrieve domain info: %v", err) + //} + signer, err := pem.UnmarshalPrivateKey(monitorPrivKey, "") + if err != nil { + t.Fatalf("Couldn't create signer: %v", err) + } + logTree := stestonly.LogTree + mapTree := stestonly.MapTree + store := storage.New() + mon, err := monitor.New(logTree, mapTree, crypto.NewSHA256Signer(signer), store) + if err != nil { + t.Fatalf("Couldn't create monitor: %v", err) + } + + // start with no mutations, sequencer initially runs + if err := env.Signer.CreateEpoch(bctx, true); err != nil { + t.Fatalf("CreateEpoch(_): %v", err) + } + mcc := mupb.NewMutationServiceClient(env.Conn) + mutCli := client.New(mcc, time.Second) + // verify first SMR + mutResp, err := mutCli.PollMutations(bctx, 1) + if err != nil { + t.Fatalf("Could not query mutations: %v", err) + } + _ = mon + if err := mon.Process(mutResp); err != nil { + t.Fatalf("Monitor could process mutations: %v", err) + } + resp, err := store.Get(1) + if err != nil { + t.Fatalf("Could not read monitoring response: %v", err) + } + for _, err := range resp.Errors { + t.Errorf("Got error: %v", err) + } + + + + // TODO start, client sends one mutation, sequencer "signs", monitor verifies +} diff --git a/integration/testutil.go b/integration/testutil.go index 5a0198f3e..51529f75a 100644 --- a/integration/testutil.go +++ b/integration/testutil.go @@ -44,7 +44,10 @@ import ( _ "github.com/mattn/go-sqlite3" // Use sqlite database for testing. pb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" + mpb "github.com/google/keytransparency/impl/proto/mutation_v1_service" + cmutation "github.com/google/keytransparency/core/mutation" stestonly "github.com/google/trillian/storage/testonly" + "github.com/google/keytransparency/impl/mutation" ) const ( @@ -154,13 +157,14 @@ func NewEnv(t *testing.T) *Env { authz := authorization.New() tlog := fake.NewFakeTrillianLogClient() - tadmin := trillian.NewTrillianAdminClient(nil) factory := transaction.NewFactory(sqldb) - server := keyserver.New(logID, tlog, mapID, mapEnv.MapClient, tadmin, commitments, + server := keyserver.New(logID, tlog, mapID, mapEnv.MapClient, mapEnv.AdminClient, commitments, vrfPriv, mutator, auth, authz, factory, mutations) s := grpc.NewServer() + msrv := mutation.New(cmutation.New(logID, mapID, tlog, mapEnv.MapClient, mutations, factory)) pb.RegisterKeyTransparencyServiceServer(s, server) + mpb.RegisterMutationServiceServer(s, msrv) // Signer signer := sequencer.New(mapID, mapEnv.MapClient, logID, tlog, mutator, mutations, factory) From acfe0f7b739dcbcf5222e7360fc346772017f40b Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 19:54:47 -0400 Subject: [PATCH 38/46] 2nd first crack on the integration tests --- core/client/kt/verify.go | 4 ++++ core/monitor/monitor.go | 44 ++++++++++++++++++++++--------------- core/monitor/verify.go | 29 ++++++++++++++++++------ integration/monitor_test.go | 42 +++++++++++++++-------------------- integration/testutil.go | 20 ++++++++++++----- 5 files changed, 84 insertions(+), 55 deletions(-) diff --git a/core/client/kt/verify.go b/core/client/kt/verify.go index d11d0e290..248691cc7 100644 --- a/core/client/kt/verify.go +++ b/core/client/kt/verify.go @@ -120,6 +120,10 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str // by removing the signature from the object. smr := *in.GetSmr() smr.Signature = nil // Remove the signature from the object to be verified. + fmt.Println("CLIENT tcrypto.VerifyObject:") + fmt.Println(v.mapPubKey) + fmt.Println(smr) + fmt.Println(in.GetSmr().GetSignature()) if err := tcrypto.VerifyObject(v.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { Vlog.Printf("✗ Signed Map Head signature verification failed.") return fmt.Errorf("sig.Verify(SMR): %v", err) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index f9b850b0b..649fb8a7c 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -25,27 +25,30 @@ import ( ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" "github.com/google/trillian" + "github.com/google/trillian/client" tcrypto "github.com/google/trillian/crypto" "github.com/google/trillian/merkle" "github.com/google/trillian/merkle/hashers" + "github.com/google/trillian/crypto/keys/der" ) // Monitor holds the internal state for a monitor accessing the mutations API // and for verifying its responses. type Monitor struct { - mapID int64 - logHasher hashers.LogHasher - mapHasher hashers.MapHasher - logPubKey crypto.PublicKey - mapPubKey crypto.PublicKey - logVerifier merkle.LogVerifier - signer *tcrypto.Signer - trusted *trillian.SignedLogRoot - store *storage.Storage + mapID int64 + logHasher hashers.LogHasher + mapHasher hashers.MapHasher + logPubKey crypto.PublicKey + mapPubKey crypto.PublicKey + logVerifier merkle.LogVerifier + logVerifierCli client.LogVerifier + signer *tcrypto.Signer + trusted *trillian.SignedLogRoot + store *storage.Storage } // New creates a new instance of the monitor. -func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage.Storage) (*Monitor, error) { +func New(logverifierCli client.LogVerifier, logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage.Storage) (*Monitor, error) { logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) if err != nil { return nil, fmt.Errorf("Failed creating LogHasher: %v", err) @@ -54,15 +57,20 @@ func New(logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage if err != nil { return nil, fmt.Errorf("Failed creating MapHasher: %v", err) } + mapPubKey, err := der.UnmarshalPublicKey(mapTree.GetPublicKey().GetDer()) + if err != nil { + return nil, fmt.Errorf("Could not unmarshal map public key: %v", err) + } return &Monitor{ - mapID: mapTree.TreeId, - mapHasher: mapHasher, - logHasher: logHasher, - logVerifier: merkle.NewLogVerifier(logHasher), - logPubKey: logTree.GetPublicKey(), - mapPubKey: mapTree.GetPublicKey(), - signer: signer, - store: store, + logVerifierCli: logverifierCli, + mapID: mapTree.TreeId, + mapHasher: mapHasher, + logHasher: logHasher, + logVerifier: merkle.NewLogVerifier(logHasher), + logPubKey: logTree.GetPublicKey(), + mapPubKey: mapPubKey, + signer: signer, + store: store, }, nil } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 2d2f43b82..77a0a8123 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -32,6 +32,7 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "fmt" ) var ( @@ -66,12 +67,23 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // // log verification // + if m.trusted == nil { + m.trusted = in.GetLogRoot() + } + + // TODO(ismail): pass in a (trillian) logverifier instead + // - create an equivalent map verifier (in trillian) + // between different error types (like below) + // - create a set of fixed error messages so the caller can differentiate + if err := m.logVerifierCli.VerifyRoot(m.trusted, in.GetLogRoot(), in.GetLogInclusion()); err != nil { + errList = append(errList, err) + } logRoot := in.GetLogRoot() // Verify SignedLogRoot signature. hash := tcrypto.HashLogRoot(*logRoot) if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { - glog.Infof("couldn't verify signature on log root: %v", err) + glog.Infof("couldn't verify signature on log root: %v: %v", logRoot, err) errList = append(errList, ErrInvalidLogSignature) } @@ -117,17 +129,15 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // reset to the state before it was signed: smr.Signature = nil // verify signature on map root: + fmt.Println("tcrypto.VerifyObject:") + fmt.Println(m.mapPubKey) + fmt.Println(smr) + fmt.Println(in.GetSmr().GetSignature()) if err := tcrypto.VerifyObject(m.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { glog.Infof("couldn't verify signature on map root: %v", err) errList = append(errList, ErrInvalidMapSignature) } - // retrieve the old root hash from storage! - monRes, err := m.store.Get(in.Epoch - 1) - if err != nil { - glog.Infof("Could not retrieve previous monitoring result: %v", err) - } - // // mutations verification: // @@ -137,6 +147,11 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // from if the checks succeeded or not. var oldRoot []byte if m.store.LatestEpoch() > 0 { + // retrieve the old root hash from storage! + monRes, err := m.store.Get(in.Epoch - 1) + if err != nil { + glog.Infof("Could not retrieve previous monitoring result: %v", err) + } oldRoot = monRes.Response.GetSmr().GetRootHash() if err := m.verifyMutations(in.GetMutations(), oldRoot, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { diff --git a/integration/monitor_test.go b/integration/monitor_test.go index c80faad97..fc4465951 100644 --- a/integration/monitor_test.go +++ b/integration/monitor_test.go @@ -16,19 +16,19 @@ package integration import ( "context" - "testing" + "time" "github.com/google/keytransparency/core/monitor" "github.com/google/keytransparency/core/monitor/storage" - // kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - // spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" + "github.com/google/keytransparency/impl/monitor/client" + kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" "github.com/google/trillian/crypto" - "github.com/google/keytransparency/impl/monitor/client" "github.com/google/trillian/crypto/keys/pem" - "time" - stestonly "github.com/google/trillian/storage/testonly" + + "github.com/google/keytransparency/core/fake" ) const ( @@ -49,27 +49,23 @@ func TestMonitorEmptyStart(t *testing.T) { // TODO(ismail) setup a proper log environment in the integration // environment, then use GetDomainInfo here: - //c := spb.NewKeyTransparencyServiceClient(env.Conn) - //resp, err := c.GetDomainInfo(bctx, &kpb.GetDomainInfoRequest{}) - //if err != nil { - // t.Fatalf("Couldn't retrieve domain info: %v", err) - //} + c := spb.NewKeyTransparencyServiceClient(env.Conn) + resp, err := c.GetDomainInfo(bctx, &kpb.GetDomainInfoRequest{}) + if err != nil { + t.Fatalf("Couldn't retrieve domain info: %v", err) + } signer, err := pem.UnmarshalPrivateKey(monitorPrivKey, "") if err != nil { t.Fatalf("Couldn't create signer: %v", err) } - logTree := stestonly.LogTree - mapTree := stestonly.MapTree + logTree := resp.Log + mapTree := resp.Map store := storage.New() - mon, err := monitor.New(logTree, mapTree, crypto.NewSHA256Signer(signer), store) + mon, err := monitor.New(fake.NewFakeTrillianLogVerifier(), logTree, mapTree, crypto.NewSHA256Signer(signer), store) if err != nil { t.Fatalf("Couldn't create monitor: %v", err) } - - // start with no mutations, sequencer initially runs - if err := env.Signer.CreateEpoch(bctx, true); err != nil { - t.Fatalf("CreateEpoch(_): %v", err) - } + // Initialization and CreateEpoch is called by NewEnv mcc := mupb.NewMutationServiceClient(env.Conn) mutCli := client.New(mcc, time.Second) // verify first SMR @@ -81,15 +77,13 @@ func TestMonitorEmptyStart(t *testing.T) { if err := mon.Process(mutResp); err != nil { t.Fatalf("Monitor could process mutations: %v", err) } - resp, err := store.Get(1) + mresp, err := store.Get(1) if err != nil { t.Fatalf("Could not read monitoring response: %v", err) } - for _, err := range resp.Errors { + for _, err := range mresp.Errors { t.Errorf("Got error: %v", err) } - - - // TODO start, client sends one mutation, sequencer "signs", monitor verifies + // TODO client sends one mutation, sequencer "signs", monitor verifies } diff --git a/integration/testutil.go b/integration/testutil.go index 51529f75a..52c7f1fb5 100644 --- a/integration/testutil.go +++ b/integration/testutil.go @@ -50,10 +50,6 @@ import ( "github.com/google/keytransparency/impl/mutation" ) -const ( - logID = 0 -) - // NewDB creates a new in-memory database for testing. func NewDB(t testing.TB) *sql.DB { db, err := sql.Open("sqlite3", "file:dummy.db?mode=memory&cache=shared") @@ -133,12 +129,25 @@ func NewEnv(t *testing.T) *Env { t.Fatalf("CreateTree(): %v", err) } mapID := tree.TreeId - mapPubKey, err := der.UnmarshalPublicKey(tree.GetPublicKey().GetDer()) if err != nil { t.Fatalf("Failed to load signing keypair: %v", err) } + // Configure log. + logTree, err := mapEnv.AdminClient.CreateTree(ctx, &trillian.CreateTreeRequest{ + Tree: stestonly.LogTree, + }) + //logPubKey, err := der.UnmarshalPublicKey(tree.GetPublicKey().GetDer()) + //if err != nil { + // t.Fatalf("Failed to load signing keypair: %v", err) + //} + + if err != nil { + t.Fatalf("CreateTree(): %v", err) + } + logID := logTree.GetTreeId() + // Common data structures. mutations, err := mutations.New(sqldb, mapID) if err != nil { @@ -155,7 +164,6 @@ func NewEnv(t *testing.T) *Env { t.Fatalf("Failed to create committer: %v", err) } authz := authorization.New() - tlog := fake.NewFakeTrillianLogClient() factory := transaction.NewFactory(sqldb) From 6a5e4682aa2c785b658d5aa7eee1cab26752dbb3 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 20:48:56 -0400 Subject: [PATCH 39/46] Don't create new tree on deployed server if they already exist --- scripts/configure_trillian.sh | 22 ++++++++++++++++++++++ scripts/deploy.sh | 15 ++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/scripts/configure_trillian.sh b/scripts/configure_trillian.sh index 34d3de110..a9a808d1b 100644 --- a/scripts/configure_trillian.sh +++ b/scripts/configure_trillian.sh @@ -3,8 +3,30 @@ # Defaults from docker-compose.yml. LOG_URL=localhost:8091 MAP_URL=localhost:8094 +KT_URL=localhost:8080 + LOCAL=true +function retrieveTrees() +{ + if [ "$LOCAL" = true ]; then + JSON=`curl -f http://${KT_URL}/v1/domain/info` + else + KTSRV=$(kubectl get pods --selector=run=kt-server -o jsonpath={.items[*].metadata.name}) + JSON=`kubectl exec -i ${KTSRV} -- curl http://kt-server:8080/v1/domain/info` + fi + + export LOG_ID=`echo ${JSON} | jq -r 'log.tree_id'` + echo "-----BEGIN PUBLIC KEY-----" > genfiles/trillian-log.pem + echo ${JSON} | jq -r 'log.public_key.der' | cat >> genfiles/trillian-log.pem + echo "-----END PUBLIC KEY-----" >> genfiles/trillian-log.pem + + export MAP_ID=`echo ${JSON} | jq -r 'map.tree_id'` + echo "-----BEGIN PUBLIC KEY-----" > genfiles/trillian-map.pem + echo ${JSON} | jq -r 'map.public_key.der' | cat >> genfiles/trillian-map.pem + echo "-----END PUBLIC KEY-----" >> genfiles/trillian-map.pem +} + function createLog() { if [ "$LOCAL" = true ]; then diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 95b8dfda7..b1c6c254d 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -40,7 +40,7 @@ function main() pushKTImgs waitForTrillian - createTreeAndSetIDs + createTreeIfNeccessaryAndSetIDs # Need to (re)build kt-signer after writing the public-keys docker-compose build kt-signer @@ -103,16 +103,21 @@ function waitForTrillian() fi } -function createTreeAndSetIDs() +function createTreeIfNeccessaryAndSetIDs() { - LOG_ID="" - MAP_ID="" + # first request domain info: + retrieveTrees + + if [ -n "$LOG_ID" ] && [ -n "$MAP_ID" ]; then + echo "Using existing trees with MAP_ID=$MAP_ID and LOG_ID=$LOG_ID" + fi + COUNTER=0 + export LOCAL=false; until [ -n "$LOG_ID" ] || [ $COUNTER -gt $MAX_RETRY ]; do # RPC was not available yet, wait and retry: sleep 10; let COUNTER+=1; - export LOCAL=false; createLog && createMap done From 26c01247e151e917a4832d319ca1a8f358c15e28 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 21:33:46 -0400 Subject: [PATCH 40/46] Don't create new tree on deployed server if they already exist --- scripts/configure_trillian.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/configure_trillian.sh b/scripts/configure_trillian.sh index a9a808d1b..99c2adb58 100644 --- a/scripts/configure_trillian.sh +++ b/scripts/configure_trillian.sh @@ -16,14 +16,14 @@ function retrieveTrees() JSON=`kubectl exec -i ${KTSRV} -- curl http://kt-server:8080/v1/domain/info` fi - export LOG_ID=`echo ${JSON} | jq -r 'log.tree_id'` + export LOG_ID=`echo ${JSON} | jq -r '.log.tree_id'` echo "-----BEGIN PUBLIC KEY-----" > genfiles/trillian-log.pem - echo ${JSON} | jq -r 'log.public_key.der' | cat >> genfiles/trillian-log.pem + echo ${JSON} | jq -r '.log.public_key.der' | cat >> genfiles/trillian-log.pem echo "-----END PUBLIC KEY-----" >> genfiles/trillian-log.pem - export MAP_ID=`echo ${JSON} | jq -r 'map.tree_id'` + export MAP_ID=`echo ${JSON} | jq -r '.map.tree_id'` echo "-----BEGIN PUBLIC KEY-----" > genfiles/trillian-map.pem - echo ${JSON} | jq -r 'map.public_key.der' | cat >> genfiles/trillian-map.pem + echo ${JSON} | jq -r '.map.public_key.der' | cat >> genfiles/trillian-map.pem echo "-----END PUBLIC KEY-----" >> genfiles/trillian-map.pem } From 0f4b582adf1904ceb9312024d1e50b6fb95d5c56 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 21:35:56 -0400 Subject: [PATCH 41/46] use client.LogVerifier instead merkler.LogVerifier --- core/monitor/monitor.go | 40 +++++++++++++------------------- core/monitor/verify.go | 51 +++++++++-------------------------------- 2 files changed, 27 insertions(+), 64 deletions(-) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 649fb8a7c..8b4ff26a0 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -35,24 +35,19 @@ import ( // Monitor holds the internal state for a monitor accessing the mutations API // and for verifying its responses. type Monitor struct { - mapID int64 - logHasher hashers.LogHasher - mapHasher hashers.MapHasher - logPubKey crypto.PublicKey - mapPubKey crypto.PublicKey - logVerifier merkle.LogVerifier - logVerifierCli client.LogVerifier - signer *tcrypto.Signer - trusted *trillian.SignedLogRoot - store *storage.Storage + mapID int64 + logHasher hashers.LogHasher + mapHasher hashers.MapHasher + logPubKey crypto.PublicKey + mapPubKey crypto.PublicKey + logVerifier client.LogVerifier + signer *tcrypto.Signer + trusted *trillian.SignedLogRoot + store *storage.Storage } // New creates a new instance of the monitor. -func New(logverifierCli client.LogVerifier, logTree, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage.Storage) (*Monitor, error) { - logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) - if err != nil { - return nil, fmt.Errorf("Failed creating LogHasher: %v", err) - } +func New(logverifierCli client.LogVerifier, mapTree *trillian.Tree, signer *tcrypto.Signer, store *storage.Storage) (*Monitor, error) { mapHasher, err := hashers.NewMapHasher(mapTree.GetHashStrategy()) if err != nil { return nil, fmt.Errorf("Failed creating MapHasher: %v", err) @@ -62,15 +57,12 @@ func New(logverifierCli client.LogVerifier, logTree, mapTree *trillian.Tree, sig return nil, fmt.Errorf("Could not unmarshal map public key: %v", err) } return &Monitor{ - logVerifierCli: logverifierCli, - mapID: mapTree.TreeId, - mapHasher: mapHasher, - logHasher: logHasher, - logVerifier: merkle.NewLogVerifier(logHasher), - logPubKey: logTree.GetPublicKey(), - mapPubKey: mapPubKey, - signer: signer, - store: store, + logVerifier: logverifierCli, + mapID: mapTree.TreeId, + mapHasher: mapHasher, + mapPubKey: mapPubKey, + signer: signer, + store: store, }, nil } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 77a0a8123..1bcb10208 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -32,7 +32,6 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - "fmt" ) var ( @@ -73,33 +72,15 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // TODO(ismail): pass in a (trillian) logverifier instead - // - create an equivalent map verifier (in trillian) - // between different error types (like below) // - create a set of fixed error messages so the caller can differentiate - if err := m.logVerifierCli.VerifyRoot(m.trusted, in.GetLogRoot(), in.GetLogInclusion()); err != nil { + // between different error types (like below) + // - also, create an equivalent map verifier (in trillian) + if err := m.logVerifier.VerifyRoot(m.trusted, in.GetLogRoot(), in.GetLogConsistency()); err != nil { + // this could be one of ErrInvalidLogSignature, ErrInvalidLogConsistencyProof errList = append(errList, err) } - logRoot := in.GetLogRoot() - // Verify SignedLogRoot signature. - hash := tcrypto.HashLogRoot(*logRoot) - if err := tcrypto.Verify(m.logPubKey, hash, logRoot.GetSignature()); err != nil { - glog.Infof("couldn't verify signature on log root: %v: %v", logRoot, err) - errList = append(errList, ErrInvalidLogSignature) - } - - if m.trusted != nil && m.trusted.GetTreeSize() > 0 { - // Verify consistency proof: - err := m.logVerifier.VerifyConsistencyProof( - m.trusted.TreeSize, logRoot.TreeSize, - m.trusted.RootHash, logRoot.RootHash, - in.GetLogConsistency()) - if err != nil { - errList = append(errList, ErrInvalidLogConsistencyProof) - } - } else { - // trust the first log root we see, don't verify anything yet - m.trusted = in.GetLogRoot() - } + // updated trusted log root + m.trusted = in.GetLogRoot() b, err := json.Marshal(in.GetSmr()) if err != nil { @@ -108,15 +89,9 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error } leafIndex := in.GetSmr().GetMapRevision() treeSize := in.GetLogRoot().GetTreeSize() - leafHash := m.logHasher.HashLeaf(b) - err = m.logVerifier.VerifyInclusionProof( - leafIndex, - treeSize, - in.GetLogInclusion(), - in.GetLogRoot().GetRootHash(), - leafHash) + err = m.logVerifier.VerifyInclusionAtIndex(in.GetLogRoot(), b, leafIndex, in.GetLogInclusion()) if err != nil { - glog.Errorf("m.logVerifier.VerifyInclusionProof((%v, %v, _): %v", leafIndex, treeSize, err) + glog.Errorf("m.logVerifier.VerifyInclusionAtIndex((%v, %v, _): %v", leafIndex, treeSize, err) errList = append(errList, ErrInvalidLogInclusion) } @@ -129,24 +104,20 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // reset to the state before it was signed: smr.Signature = nil // verify signature on map root: - fmt.Println("tcrypto.VerifyObject:") - fmt.Println(m.mapPubKey) - fmt.Println(smr) - fmt.Println(in.GetSmr().GetSignature()) if err := tcrypto.VerifyObject(m.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { glog.Infof("couldn't verify signature on map root: %v", err) errList = append(errList, ErrInvalidMapSignature) } // - // mutations verification: + // mutations verification // // we need the old root for verifying the inclusion of the old leafs in the // previous epoch. Storage always stores the mutations response independent // from if the checks succeeded or not. var oldRoot []byte - if m.store.LatestEpoch() > 0 { + if m.store.LatestEpoch() > 1 { // retrieve the old root hash from storage! monRes, err := m.store.Get(in.Epoch - 1) if err != nil { @@ -158,7 +129,7 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error errList = append(errList, err...) } } else { - // TODO oldRoot is the hash of the initial tree + // TODO oldRoot is the hash of the initial empty sparse merkle tree } return errList From c3cedaf5da761687e0641a6df05b4fecc93dbc03 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 21:58:24 -0400 Subject: [PATCH 42/46] Use trillian logverifier instead --- cmd/keytransparency-monitor/main.go | 20 ++++++++++++++++---- core/client/kt/verify.go | 4 ---- core/monitor/monitor.go | 7 ++----- core/monitor/verify.go | 15 ++------------- integration/monitor_test.go | 8 ++++---- integration/testutil.go | 4 ++-- 6 files changed, 26 insertions(+), 32 deletions(-) diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index b76685507..c422008c4 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -42,7 +42,10 @@ import ( spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" - _ "github.com/google/trillian/merkle/coniks" // Register coniks + tlogcli "github.com/google/trillian/client" + "github.com/google/trillian/crypto/keys/der" + _ "github.com/google/trillian/merkle/coniks" // Register coniks + "github.com/google/trillian/merkle/hashers" _ "github.com/google/trillian/merkle/objhasher" // Register objhasher ) @@ -141,13 +144,22 @@ func main() { // Insert handlers for other http paths here. mux := http.NewServeMux() mux.Handle("/", gwmux) + logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) + if err != nil { + glog.Fatalf("Could not initialize log hasher: %v", err) + } + logPubKey, err := der.UnmarshalPublicKey(logTree.GetPublicKey().GetDer()) + if err != nil { + glog.Fatalf("Failed parsing Log public key: %v", err) + } + logVerifier := tlogcli.NewLogVerifier(logHasher, logPubKey) - // initialize the mutations API client and feed the responses it got - // into the monitor: - mon, err := cmon.New(logTree, mapTree, crypto.NewSHA256Signer(key), store) + mon, err := cmon.New(logVerifier, mapTree, crypto.NewSHA256Signer(key), store) if err != nil { glog.Exitf("Failed to initialize monitor: %v", err) } + // initialize the mutations API client and feed the responses it got + // into the monitor: mutCli := client.New(mcc, *pollPeriod) responses, errs := mutCli.StartPolling(1) go func() { diff --git a/core/client/kt/verify.go b/core/client/kt/verify.go index 248691cc7..d11d0e290 100644 --- a/core/client/kt/verify.go +++ b/core/client/kt/verify.go @@ -120,10 +120,6 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str // by removing the signature from the object. smr := *in.GetSmr() smr.Signature = nil // Remove the signature from the object to be verified. - fmt.Println("CLIENT tcrypto.VerifyObject:") - fmt.Println(v.mapPubKey) - fmt.Println(smr) - fmt.Println(in.GetSmr().GetSignature()) if err := tcrypto.VerifyObject(v.mapPubKey, smr, in.GetSmr().GetSignature()); err != nil { Vlog.Printf("✗ Signed Map Head signature verification failed.") return fmt.Errorf("sig.Verify(SMR): %v", err) diff --git a/core/monitor/monitor.go b/core/monitor/monitor.go index 8b4ff26a0..f1981ec3b 100644 --- a/core/monitor/monitor.go +++ b/core/monitor/monitor.go @@ -27,18 +27,15 @@ import ( "github.com/google/trillian" "github.com/google/trillian/client" tcrypto "github.com/google/trillian/crypto" - "github.com/google/trillian/merkle" - "github.com/google/trillian/merkle/hashers" "github.com/google/trillian/crypto/keys/der" + "github.com/google/trillian/merkle/hashers" ) // Monitor holds the internal state for a monitor accessing the mutations API // and for verifying its responses. type Monitor struct { mapID int64 - logHasher hashers.LogHasher mapHasher hashers.MapHasher - logPubKey crypto.PublicKey mapPubKey crypto.PublicKey logVerifier client.LogVerifier signer *tcrypto.Signer @@ -52,7 +49,7 @@ func New(logverifierCli client.LogVerifier, mapTree *trillian.Tree, signer *tcry if err != nil { return nil, fmt.Errorf("Failed creating MapHasher: %v", err) } - mapPubKey, err := der.UnmarshalPublicKey(mapTree.GetPublicKey().GetDer()) + mapPubKey, err := der.UnmarshalPublicKey(mapTree.GetPublicKey().GetDer()) if err != nil { return nil, fmt.Errorf("Could not unmarshal map public key: %v", err) } diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 1bcb10208..02ce17be9 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -70,11 +70,6 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error m.trusted = in.GetLogRoot() } - - // TODO(ismail): pass in a (trillian) logverifier instead - // - create a set of fixed error messages so the caller can differentiate - // between different error types (like below) - // - also, create an equivalent map verifier (in trillian) if err := m.logVerifier.VerifyRoot(m.trusted, in.GetLogRoot(), in.GetLogConsistency()); err != nil { // this could be one of ErrInvalidLogSignature, ErrInvalidLogConsistencyProof errList = append(errList, err) @@ -85,7 +80,7 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error b, err := json.Marshal(in.GetSmr()) if err != nil { glog.Errorf("json.Marshal(): %v", err) - // Encoding error + errList = append(errList, ErrInvalidMapSignature) } leafIndex := in.GetSmr().GetMapRevision() treeSize := in.GetLogRoot().GetTreeSize() @@ -95,9 +90,7 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error errList = append(errList, ErrInvalidLogInclusion) } - // // map verification - // // copy of singed map root smr := *in.GetSmr() @@ -109,9 +102,7 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error errList = append(errList, ErrInvalidMapSignature) } - // // mutations verification - // // we need the old root for verifying the inclusion of the old leafs in the // previous epoch. Storage always stores the mutations response independent @@ -128,9 +119,7 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { errList = append(errList, err...) } - } else { - // TODO oldRoot is the hash of the initial empty sparse merkle tree - } + } // TODO else oldRoot is the hash of the initial empty sparse merkle tree return errList } diff --git a/integration/monitor_test.go b/integration/monitor_test.go index fc4465951..768c67953 100644 --- a/integration/monitor_test.go +++ b/integration/monitor_test.go @@ -21,8 +21,8 @@ import ( "github.com/google/keytransparency/core/monitor" "github.com/google/keytransparency/core/monitor/storage" - "github.com/google/keytransparency/impl/monitor/client" kpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "github.com/google/keytransparency/impl/monitor/client" spb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mupb "github.com/google/keytransparency/impl/proto/mutation_v1_service" "github.com/google/trillian/crypto" @@ -54,14 +54,14 @@ func TestMonitorEmptyStart(t *testing.T) { if err != nil { t.Fatalf("Couldn't retrieve domain info: %v", err) } - signer, err := pem.UnmarshalPrivateKey(monitorPrivKey, "") + signer, err := pem.UnmarshalPrivateKey(monitorPrivKey, "") if err != nil { t.Fatalf("Couldn't create signer: %v", err) } - logTree := resp.Log + //logTree := resp.Log mapTree := resp.Map store := storage.New() - mon, err := monitor.New(fake.NewFakeTrillianLogVerifier(), logTree, mapTree, crypto.NewSHA256Signer(signer), store) + mon, err := monitor.New(fake.NewFakeTrillianLogVerifier(), mapTree, crypto.NewSHA256Signer(signer), store) if err != nil { t.Fatalf("Couldn't create monitor: %v", err) } diff --git a/integration/testutil.go b/integration/testutil.go index 52c7f1fb5..172b3915f 100644 --- a/integration/testutil.go +++ b/integration/testutil.go @@ -43,11 +43,11 @@ import ( _ "github.com/mattn/go-sqlite3" // Use sqlite database for testing. + cmutation "github.com/google/keytransparency/core/mutation" + "github.com/google/keytransparency/impl/mutation" pb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" mpb "github.com/google/keytransparency/impl/proto/mutation_v1_service" - cmutation "github.com/google/keytransparency/core/mutation" stestonly "github.com/google/trillian/storage/testonly" - "github.com/google/keytransparency/impl/mutation" ) // NewDB creates a new in-memory database for testing. From 269d0426e7aab9784993581e18a568a7771743ac Mon Sep 17 00:00:00 2001 From: Liamsi Date: Thu, 24 Aug 2017 23:16:12 -0400 Subject: [PATCH 43/46] WIP: fix mutator bug --- core/monitor/verify.go | 11 +++++++++-- core/mutation/mutation.go | 12 +++++++++--- integration/monitor_test.go | 30 ++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 02ce17be9..253d870c8 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -32,6 +32,7 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" + "fmt" ) var ( @@ -108,13 +109,15 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // previous epoch. Storage always stores the mutations response independent // from if the checks succeeded or not. var oldRoot []byte - if m.store.LatestEpoch() > 1 { + if m.store.LatestEpoch() > 0 { + fmt.Println("Called") // retrieve the old root hash from storage! monRes, err := m.store.Get(in.Epoch - 1) if err != nil { glog.Infof("Could not retrieve previous monitoring result: %v", err) } oldRoot = monRes.Response.GetSmr().GetRootHash() + if err := m.verifyMutations(in.GetMutations(), oldRoot, in.GetSmr().GetRootHash(), in.GetSmr().GetMapId()); len(err) > 0 { errList = append(errList, err...) @@ -129,7 +132,7 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo mutator := entry.New() oldProofNodes := make(map[string][]byte) newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) - + glog.Infof("verifyMutations() called with %v mutations.", len(muts)) for _, mut := range muts { oldLeaf, err := entry.FromLeafValue(mut.GetProof().GetLeaf().GetLeafValue()) if err != nil { @@ -146,8 +149,12 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo } // compute the new leaf + fmt.Println("old leaf: ") + fmt.Println(mut.GetProof().GetLeaf().GetLeafValue()) + fmt.Println(oldLeaf) newLeaf, err := mutator.Mutate(oldLeaf, mut.GetUpdate()) if err != nil { + glog.Infof("Mutation did not verify: %v", err) errList = append(errList, ErrInvalidMutation) } newLeafnID := storage.NewNodeIDFromPrefixSuffix(index, storage.Suffix{}, m.mapHasher.BitLen()) diff --git a/core/mutation/mutation.go b/core/mutation/mutation.go index a8fa2e548..3c3f5f5a7 100644 --- a/core/mutation/mutation.go +++ b/core/mutation/mutation.go @@ -106,7 +106,13 @@ func (s *Server) GetMutations(ctx context.Context, in *tpb.GetMutationsRequest) } // Get leaf proofs. // TODO: allow leaf proofs to be optional. - proofs, err := s.inclusionProofs(ctx, indexes, in.Epoch) + var epoch int64 + if in.Epoch > 1 { + epoch = in.Epoch-1 + } else { + epoch = 1 + } + proofs, err := s.inclusionProofs(ctx, indexes, epoch) if err != nil { return nil, err } @@ -114,10 +120,10 @@ func (s *Server) GetMutations(ctx context.Context, in *tpb.GetMutationsRequest) mutations[i].Proof = p } - // MapRevisions start at 1. Log leave's index starts at 0. + // MapRevisions start at 1. Log leave's index starts at 1. // MapRevision should be at least 1 since the Signer is // supposed to create at least one revision on startup. - respEpoch := resp.GetMapRoot().GetMapRevision() - 1 + respEpoch := resp.GetMapRoot().GetMapRevision() // Fetch log proofs. logRoot, logConsistency, logInclusion, err := s.logProofs(ctx, in.GetFirstTreeSize(), respEpoch) if err != nil { diff --git a/integration/monitor_test.go b/integration/monitor_test.go index 768c67953..ed0f48854 100644 --- a/integration/monitor_test.go +++ b/integration/monitor_test.go @@ -29,6 +29,8 @@ import ( "github.com/google/trillian/crypto/keys/pem" "github.com/google/keytransparency/core/fake" + "github.com/google/keytransparency/core/crypto/signatures" + "github.com/google/keytransparency/cmd/keytransparency-client/grpcc" ) const ( @@ -73,7 +75,6 @@ func TestMonitorEmptyStart(t *testing.T) { if err != nil { t.Fatalf("Could not query mutations: %v", err) } - _ = mon if err := mon.Process(mutResp); err != nil { t.Fatalf("Monitor could process mutations: %v", err) } @@ -85,5 +86,30 @@ func TestMonitorEmptyStart(t *testing.T) { t.Errorf("Got error: %v", err) } - // TODO client sends one mutation, sequencer "signs", monitor verifies + // client sends one mutation, sequencer "signs", monitor verifies + userID := "test@test.com" + signers := []signatures.Signer{createSigner(t, testPrivKey1)} + authorizedKeys := []*kpb.PublicKey{getAuthorizedKey(testPubKey1)} + + _, err = env.Client.Update(GetNewOutgoingContextWithFakeAuth("test@test.com"), userID, appID, []byte("testProfile"), signers, authorizedKeys) + if err != grpcc.ErrRetry { + t.Fatalf("Could not send update request: %v", err) + } + if err := env.Signer.CreateEpoch(bctx, false); err != nil { + t.Errorf("CreateEpoch(_): %v", err) + } + mutResp, err = mutCli.PollMutations(bctx, 2) + if err != nil { + t.Fatalf("Could not query mutations: %v", err) + } + if err := mon.Process(mutResp); err != nil { + t.Fatalf("Monitor could not process mutations: %v", err) + } + mresp, err = store.Get(2) + if err != nil { + t.Fatalf("Could not read monitoring response: %v", err) + } + for _, err := range mresp.Errors { + t.Errorf("Got error: %v", err) + } } From d550d59d7eca4a390f28aace3c1de4a5592e4cfc Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 25 Aug 2017 00:20:59 -0400 Subject: [PATCH 44/46] All verifications pass --- core/monitor/verify.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index 253d870c8..dc39c4342 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -141,9 +141,9 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo // verify that the provided leaf’s inclusion proof goes to epoch e-1: index := mut.GetProof().GetLeaf().GetIndex() - leafHash := mut.GetProof().GetLeaf().GetLeafHash() + leaf := mut.GetProof().GetLeaf().GetLeafValue() if err := merkle.VerifyMapInclusionProof(mapID, index, - leafHash, oldRoot, mut.GetProof().GetInclusion(), m.mapHasher); err != nil { + leaf, oldRoot, mut.GetProof().GetInclusion(), m.mapHasher); err != nil { glog.Infof("VerifyMapInclusionProof(%x): %v", index, err) errList = append(errList, ErrInvalidMutation) } @@ -177,11 +177,15 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo errList = append(errList, ErrInconsistentProofs) } } else { - oldProofNodes[sibID.String()] = proof + if len(proof) > 0 { + oldProofNodes[sibID.String()] = proof + } } } } - + fmt.Println(newLeaves) + fmt.Println(expectedNewRoot) + fmt.Println(oldProofNodes) if err := m.validateMapRoot(expectedNewRoot, mapID, newLeaves, oldProofNodes); err != nil { errList = append(errList, err) } @@ -193,7 +197,7 @@ func (m *Monitor) validateMapRoot(expectedRoot []byte, mapID int64, mutatedLeave // compute the new root using local intermediate hashes from epoch e // (above proof hashes): hs2 := merkle.NewHStar2(mapID, m.mapHasher) - newRoot, err := hs2.HStar2Nodes([]byte{}, m.mapHasher.Size(), mutatedLeaves, + newRoot, err := hs2.HStar2Nodes([]byte{}, m.mapHasher.BitLen(), mutatedLeaves, func(depth int, index *big.Int) ([]byte, error) { nID := storage.NewNodeIDFromBigInt(depth, index, m.mapHasher.BitLen()) if p, ok := oldProofNodes[nID.String()]; ok { From 913b298c0b99eb33cff4b9f6ee57382f5912f79b Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 25 Aug 2017 11:28:23 -0400 Subject: [PATCH 45/46] remove debug output, some minor cleanup --- core/monitor/verify.go | 8 -------- integration/monitor_test.go | 6 ++---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/core/monitor/verify.go b/core/monitor/verify.go index dc39c4342..e477786cd 100644 --- a/core/monitor/verify.go +++ b/core/monitor/verify.go @@ -32,7 +32,6 @@ import ( "github.com/google/keytransparency/core/mutator/entry" ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" - "fmt" ) var ( @@ -110,7 +109,6 @@ func (m *Monitor) VerifyMutationsResponse(in *ktpb.GetMutationsResponse) []error // from if the checks succeeded or not. var oldRoot []byte if m.store.LatestEpoch() > 0 { - fmt.Println("Called") // retrieve the old root hash from storage! monRes, err := m.store.Get(in.Epoch - 1) if err != nil { @@ -149,9 +147,6 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo } // compute the new leaf - fmt.Println("old leaf: ") - fmt.Println(mut.GetProof().GetLeaf().GetLeafValue()) - fmt.Println(oldLeaf) newLeaf, err := mutator.Mutate(oldLeaf, mut.GetUpdate()) if err != nil { glog.Infof("Mutation did not verify: %v", err) @@ -183,9 +178,6 @@ func (m *Monitor) verifyMutations(muts []*ktpb.Mutation, oldRoot, expectedNewRoo } } } - fmt.Println(newLeaves) - fmt.Println(expectedNewRoot) - fmt.Println(oldProofNodes) if err := m.validateMapRoot(expectedNewRoot, mapID, newLeaves, oldProofNodes); err != nil { errList = append(errList, err) } diff --git a/integration/monitor_test.go b/integration/monitor_test.go index ed0f48854..483a80471 100644 --- a/integration/monitor_test.go +++ b/integration/monitor_test.go @@ -41,16 +41,13 @@ amFdON6OhjYnBmJWe4fVnbxny0PfpkvXtg== -----END EC PRIVATE KEY-----` ) -func TestMonitorEmptyStart(t *testing.T) { +func TestMonitor(t *testing.T) { bctx := context.Background() env := NewEnv(t) defer env.Close(t) env.Client.RetryCount = 0 // setup monitor: - - // TODO(ismail) setup a proper log environment in the integration - // environment, then use GetDomainInfo here: c := spb.NewKeyTransparencyServiceClient(env.Conn) resp, err := c.GetDomainInfo(bctx, &kpb.GetDomainInfoRequest{}) if err != nil { @@ -63,6 +60,7 @@ func TestMonitorEmptyStart(t *testing.T) { //logTree := resp.Log mapTree := resp.Map store := storage.New() + // TODO(ismail): setup and use a real logVerifier instead: mon, err := monitor.New(fake.NewFakeTrillianLogVerifier(), mapTree, crypto.NewSHA256Signer(signer), store) if err != nil { t.Fatalf("Couldn't create monitor: %v", err) From d25aa7e80f0ba43481339fc7b9f28e7d95841c42 Mon Sep 17 00:00:00 2001 From: Liamsi Date: Fri, 25 Aug 2017 14:15:47 -0400 Subject: [PATCH 46/46] Hacky monitor result web-site --- cmd/keytransparency-monitor/main.go | 65 ++++++++++++++----- .../web/monitoring.tmpl | 19 ++++++ 2 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 cmd/keytransparency-monitor/web/monitoring.tmpl diff --git a/cmd/keytransparency-monitor/main.go b/cmd/keytransparency-monitor/main.go index c422008c4..a209da21d 100644 --- a/cmd/keytransparency-monitor/main.go +++ b/cmd/keytransparency-monitor/main.go @@ -47,16 +47,17 @@ import ( _ "github.com/google/trillian/merkle/coniks" // Register coniks "github.com/google/trillian/merkle/hashers" _ "github.com/google/trillian/merkle/objhasher" // Register objhasher + "html/template" ) var ( addr = flag.String("addr", ":8099", "The ip:port combination to listen on") - keyFile = flag.String("tls-key", "genfiles/server.key", "TLS private key file") - certFile = flag.String("tls-cert", "genfiles/server.pem", "TLS cert file") + keyFile = flag.String("tls-key", "../../genfiles/server.key", "TLS private key file") + certFile = flag.String("tls-cert", "../../genfiles/server.pem", "TLS cert file") - signingKey = flag.String("sign-key", "genfiles/monitor_sign-key.pem", "Path to private key PEM for SMH signing") + signingKey = flag.String("sign-key", "../../genfiles/monitor_sign-key.pem", "Path to private key PEM for SMH signing") signingKeyPassword = flag.String("password", "towel", "Password of the private key PEM file for SMH signing") - ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") + ktURL = flag.String("kt-url", "35.184.134.53:8080", "URL of key-server.") insecure = flag.Bool("insecure", false, "Skip TLS checks") ktCert = flag.String("kt-cert", "genfiles/server.crt", "Path to kt-server's public key") @@ -68,11 +69,11 @@ var ( func grpcGatewayMux(addr string) (*runtime.ServeMux, error) { ctx := context.Background() - creds, err := credentials.NewClientTLSFromFile(*certFile, "") - if err != nil { - return nil, err - } - dopts := []grpc.DialOption{grpc.WithTransportCredentials(creds)} + //creds, err := credentials.NewClientTLSFromFile(*certFile, "") + //if err != nil { + // return nil, err + //} + dopts := []grpc.DialOption{grpc.WithInsecure()} gwmux := runtime.NewServeMux() if err := mopb.RegisterMonitorServiceHandlerFromEndpoint(ctx, gwmux, addr, dopts); err != nil { return nil, err @@ -95,19 +96,47 @@ func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Ha }) } -func main() { - flag.Parse() +// Hackathon only code. Remove later! +type resHandler struct { + store *storage.Storage +} + +func (h *resHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + max := h.store.LatestEpoch() + results := make([]*storage.MonitoringResult, max) + for i:=int64(1); i<= max ; i++ { + monRes, err := h.store.Get(i) + if err != nil { + glog.Errorf("Couldn't retrieve mon result: %v", err) + } + results[i-1] = monRes + } + // TODO(ismail) make this file path configurable so that it can be found in + // docker as well + tmpl, err := template.ParseFiles("/Users/khoffi/go/src/github.com/google/keytransparency/cmd/keytransparency-monitor/web/monitoring.tmpl") + if err != nil { + glog.Errorf("Could not parse template: %v", err) + } - creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + err = tmpl.Execute(w, results) if err != nil { - glog.Exitf("Failed to load server credentials %v", err) + glog.Errorf("Could not write result: %v", err) } +} + +func main() { + flag.Parse() + + //creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile) + //if err != nil { + // glog.Exitf("Failed to load server credentials %v", err) + //} // Create gRPC server. grpcServer := grpc.NewServer( - grpc.Creds(creds), + //grpc.Creds(creds), grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), - grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), + //grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), ) // Connect to the kt-server's mutation API: @@ -143,6 +172,10 @@ func main() { // Insert handlers for other http paths here. mux := http.NewServeMux() + + resultHandler := &resHandler{store:store} + mux.Handle("/monitor", resultHandler) + mux.Handle("/", gwmux) logHasher, err := hashers.NewLogHasher(logTree.GetHashStrategy()) if err != nil { @@ -181,7 +214,7 @@ func main() { // Serve HTTP2 server over TLS. glog.Infof("Listening on %v", *addr) - if err := http.ListenAndServeTLS(*addr, *certFile, *keyFile, + if err := http.ListenAndServe(*addr, /**certFile, *keyFile,*/ grpcHandlerFunc(grpcServer, mux)); err != nil { glog.Errorf("ListenAndServeTLS: %v", err) } diff --git a/cmd/keytransparency-monitor/web/monitoring.tmpl b/cmd/keytransparency-monitor/web/monitoring.tmpl new file mode 100644 index 000000000..419ccfb9b --- /dev/null +++ b/cmd/keytransparency-monitor/web/monitoring.tmpl @@ -0,0 +1,19 @@ +{{range .}} + + + + + + + + {{range .Errors}} + + + + {{end}} +
+
+
+   +
Epoch: {{.Response.Epoch}}
Map-id: {{.Response.Smr.MapId}}
Log-id: {{.Response.LogRoot.LogId}}
SMR roothash: {{.Response.Smr.RootHash}}
 
Errors:
   Error: {{.}}
+{{end}} \ No newline at end of file