Skip to content
This repository was archived by the owner on Oct 11, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 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
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
10 changes: 10 additions & 0 deletions cmd/keytransparency-monitor/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
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

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

EXPOSE 8099
246 changes: 246 additions & 0 deletions cmd/keytransparency-monitor/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// 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"
"fmt"
"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/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"
)

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

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

// 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)
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)
}

srv := monitor.New(mcc, crypto.NewSHA256Signer(key), logTree, mapTree, *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 string) (*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) (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
}
45 changes: 45 additions & 0 deletions core/monitor/monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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"

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

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{
logVerifier: merkle.NewLogVerifier(logHasher),
logPubKey: logTree.GetPublicKey(),
mapPubKey: mapTree.GetPublicKey(),
}, nil
}
Loading