Skip to content
This repository was archived by the owner on Oct 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
20f3b16
WIP: monitor binary
liamsi Jul 12, 2017
f681eb8
revert local changes, add TODOs
liamsi Jul 28, 2017
77a14fb
Add to kubernetes config and deploy script
liamsi Jul 31, 2017
bb41010
Add to kubernetes config and deploy script
liamsi Jul 31, 2017
ad4af54
Review comments:
liamsi Aug 10, 2017
1bcaa67
* Change mutator interface to accept SignedKV objects directly
liamsi Aug 9, 2017
fa1eb0b
Change mutator interface to accept proto.Message
liamsi Aug 9, 2017
d6eddf0
Use nil in Update/Mutate instead &tpb.Entry{}
liamsi Aug 9, 2017
be831c5
Use nil in Update/Mutate instead &tpb.Entry{} on keyserver as well
liamsi Aug 9, 2017
23c0a7d
Use nil in Update/Mutate instead &tpb.Entry{} on signer as well
liamsi Aug 9, 2017
cd4edd5
Add helper method to Entry to avoid code duplication
liamsi Aug 9, 2017
0a2850d
Add helper method to Entry to avoid code duplication (tests)
liamsi Aug 9, 2017
4d3a88d
Use helper method to Entry to avoid code duplication
liamsi Aug 9, 2017
f2840cd
gofmt
liamsi Aug 9, 2017
01fba58
compile again
liamsi Aug 10, 2017
16db4f7
TODO verification
liamsi Aug 10, 2017
4c8831b
Work in progress: compute new root hash
liamsi Aug 11, 2017
a0c9404
Minor cleanup
liamsi Aug 14, 2017
972eb31
Merge branch 'master' into mvp_monitor
liamsi Aug 14, 2017
7c54e26
Some cleanup, further splitting up into core/impl
liamsi Aug 14, 2017
fda51ba
Merge branch 'master' into mvp_monitor
liamsi Aug 14, 2017
3e6ed89
Merge branch 'master' into mvp_monitor
liamsi Aug 15, 2017
bac1ab6
Merge remote-tracking branch 'origin/master' into mvp_monitor
liamsi Aug 18, 2017
08e7e11
Merge remote-tracking branch 'origin/master' into mvp_monitor
liamsi Aug 18, 2017
de1845f
Merge remote-tracking branch 'origin/master' into mvp_monitor
liamsi Aug 18, 2017
c3a0907
Some of the review comments (this should go to #768)
liamsi Aug 18, 2017
48b5f69
Minor changes: compiles
liamsi Aug 21, 2017
352d299
Keep imports relative
liamsi Aug 21, 2017
6f75fda
obsolete change to mutation service proto's gen.go
liamsi Aug 21, 2017
d2aaf7d
Use "autoconfig" from domain info, split transportCreds
liamsi Aug 21, 2017
e487368
remove libtool dependency from monitor dockerfile
liamsi Aug 21, 2017
ac156ea
remove verification logic completely
liamsi Aug 21, 2017
9a5e2f9
remove everything from proto which is not needed by a non-verifying m…
liamsi Aug 21, 2017
4646ef8
Merge branch 'master' into non_verifying_monitor
liamsi Aug 21, 2017
8603214
update docker-compose, remove kube-config, always use autoconfig
liamsi Aug 21, 2017
42a855b
linter checks
liamsi Aug 22, 2017
cdc64de
Some fixes to the docker files
liamsi Aug 22, 2017
b881c04
WIP: restructuring monitor implementation, split up into client, serv…
liamsi Aug 22, 2017
94f7508
restructured non-verifiying monitor
liamsi Aug 23, 2017
04b4354
gometalinter
liamsi Aug 23, 2017
1544646
Merge branch 'master' into non_verifying_monitor
liamsi Aug 23, 2017
16724f5
renamed API urls
liamsi Aug 23, 2017
f881945
Merge remote-tracking branch 'isma-fork/non_verifying_monitor' into n…
liamsi Aug 23, 2017
73f77dd
Merge branch 'master' into non_verifying_monitor
liamsi Aug 23, 2017
547f727
Merge branch 'master' into non_verifying_monitor
liamsi Aug 23, 2017
153d655
Fix travis build
liamsi Aug 24, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions cmd/keytransparency-monitor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang

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 go get -tags="mysql" ./cmd/keytransparency-monitor

ENTRYPOINT ["/go/bin/keytransparency-monitor"]

EXPOSE 8099
228 changes: 228 additions & 0 deletions cmd/keytransparency-monitor/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// 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 (
"crypto/tls"
"flag"
"net"
"net/http"
"strings"
"time"

"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/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"

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"
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 (
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")

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.")

// 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()
if err != nil {
glog.Fatalf("Error Dialing %v: %v", ktURL, err)
}
mcc := mupb.NewMutationServiceClient(grpcc)

// Read signing key:
key, err := pem.ReadPrivateKeyFile(*signingKey, *signingKeyPassword)
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)
}

store := storage.New()
srv := monitor.New(store)
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)

// 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,
grpcHandlerFunc(grpcServer, mux)); err != nil {
glog.Errorf("ListenAndServeTLS: %v", err)
}
}

func dial() (*grpc.ClientConn, error) {
var opts []grpc.DialOption

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...)
if err != nil {
return nil, err
}
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) (logTree *trillian.Tree, mapTree *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()
return
}
87 changes: 87 additions & 0 deletions core/monitor/monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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 (
"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"
tcrypto "github.com/google/trillian/crypto"
"github.com/google/trillian/merkle"
"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
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, store *storage.Storage) (*Monitor, error) {
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(),
signer: signer,
store: store,
}, 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)
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
}
37 changes: 37 additions & 0 deletions core/monitor/sign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 (
"fmt"

ktpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types"

"github.com/google/trillian"
)

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
}
Loading