github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/server/trillian_log_signer/main.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // The trillian_log_signer binary runs the log signing code. 16 package main 17 18 import ( 19 "context" 20 "flag" 21 "fmt" 22 "net/http" 23 "os" 24 "time" 25 26 "github.com/golang/glog" 27 "github.com/google/trillian/cmd" 28 "github.com/google/trillian/extension" 29 "github.com/google/trillian/log" 30 "github.com/google/trillian/monitoring/prometheus" 31 "github.com/google/trillian/server" 32 "github.com/google/trillian/storage" 33 "github.com/google/trillian/util" 34 "github.com/google/trillian/util/election" 35 "github.com/google/trillian/util/etcd" 36 "github.com/prometheus/client_golang/prometheus/promhttp" 37 38 // Register key ProtoHandlers 39 _ "github.com/google/trillian/crypto/keys/der/proto" 40 _ "github.com/google/trillian/crypto/keys/pem/proto" 41 _ "github.com/google/trillian/crypto/keys/pkcs11/proto" 42 // Load hashers 43 _ "github.com/google/trillian/merkle/objhasher" 44 _ "github.com/google/trillian/merkle/rfc6962" 45 ) 46 47 var ( 48 httpEndpoint = flag.String("http_endpoint", "localhost:8091", "Endpoint for HTTP (host:port, empty means disabled)") 49 tlsCertFile = flag.String("tls_cert_file", "", "Path to the TLS server certificate. If unset, the server will use unsecured connections.") 50 tlsKeyFile = flag.String("tls_key_file", "", "Path to the TLS server key. If unset, the server will use unsecured connections.") 51 sequencerIntervalFlag = flag.Duration("sequencer_interval", time.Second*10, "Time between each sequencing pass through all logs") 52 batchSizeFlag = flag.Int("batch_size", 50, "Max number of leaves to process per batch") 53 numSeqFlag = flag.Int("num_sequencers", 10, "Number of sequencer workers to run in parallel") 54 sequencerGuardWindowFlag = flag.Duration("sequencer_guard_window", 0, "If set, the time elapsed before submitted leaves are eligible for sequencing") 55 forceMaster = flag.Bool("force_master", false, "If true, assume master for all logs") 56 etcdHTTPService = flag.String("etcd_http_service", "trillian-logsigner-http", "Service name to announce our HTTP endpoint under") 57 lockDir = flag.String("lock_file_path", "/test/multimaster", "etcd lock file directory path") 58 healthzTimeout = flag.Duration("healthz_timeout", time.Second*5, "Timeout used during healthz checks") 59 60 quotaIncreaseFactor = flag.Float64("quota_increase_factor", log.QuotaIncreaseFactor, 61 "Increase factor for tokens replenished by sequencing-based quotas (1 means a 1:1 relationship between sequenced leaves and replenished tokens)."+ 62 "Only effective for --quota_system=etcd.") 63 64 preElectionPause = flag.Duration("pre_election_pause", 1*time.Second, "Maximum time to wait before starting elections") 65 masterCheckInterval = flag.Duration("master_check_interval", 5*time.Second, "Interval between checking mastership still held") 66 masterHoldInterval = flag.Duration("master_hold_interval", 60*time.Second, "Minimum interval to hold mastership for") 67 resignOdds = flag.Int("resign_odds", 10, "Chance of resigning mastership after each check, the N in 1-in-N") 68 69 configFile = flag.String("config", "", "Config file containing flags, file contents can be overridden by command line flags") 70 ) 71 72 func main() { 73 flag.Parse() 74 defer glog.Flush() 75 76 if *configFile != "" { 77 if err := cmd.ParseFlagFile(*configFile); err != nil { 78 glog.Exitf("Failed to load flags from config file %q: %s", *configFile, err) 79 } 80 } 81 82 glog.CopyStandardLogTo("WARNING") 83 glog.Info("**** Log Signer Starting ****") 84 85 mf := prometheus.MetricFactory{} 86 87 sp, err := server.NewStorageProviderFromFlags(mf) 88 if err != nil { 89 glog.Exitf("Failed to get storage provider: %v", err) 90 } 91 defer sp.Close() 92 93 client, err := etcd.NewClient(*server.EtcdServers) 94 if err != nil { 95 glog.Exitf("Failed to connect to etcd at %v: %v", server.EtcdServers, err) 96 } 97 if client != nil { 98 defer client.Close() 99 } 100 101 ctx, cancel := context.WithCancel(context.Background()) 102 defer cancel() 103 go util.AwaitSignal(ctx, cancel) 104 105 hostname, _ := os.Hostname() 106 instanceID := fmt.Sprintf("%s.%d", hostname, os.Getpid()) 107 var electionFactory election.Factory 108 switch { 109 case *forceMaster: 110 glog.Warning("**** Acting as master for all logs ****") 111 electionFactory = election.NoopFactory{InstanceID: instanceID} 112 case client != nil: 113 electionFactory = etcd.NewElectionFactory(instanceID, client, *lockDir) 114 default: 115 glog.Exit("Either --force_master or --etcd_servers must be supplied") 116 } 117 118 qm, err := server.NewQuotaManagerFromFlags() 119 if err != nil { 120 glog.Exitf("Error creating quota manager: %v", err) 121 } 122 123 registry := extension.Registry{ 124 AdminStorage: sp.AdminStorage(), 125 LogStorage: sp.LogStorage(), 126 ElectionFactory: electionFactory, 127 QuotaManager: qm, 128 MetricFactory: mf, 129 } 130 131 // Start HTTP server (optional) 132 if *httpEndpoint != "" { 133 // Announce our endpoint to etcd if so configured. 134 unannounceHTTP := server.AnnounceSelf(ctx, client, *etcdHTTPService, *httpEndpoint) 135 defer unannounceHTTP() 136 137 glog.Infof("Creating HTTP server starting on %v", *httpEndpoint) 138 http.Handle("/metrics", promhttp.Handler()) 139 http.HandleFunc("/healthz", healthzFunc(sp.AdminStorage(), *healthzTimeout)) 140 if err := util.StartHTTPServer(*httpEndpoint, *tlsCertFile, *tlsKeyFile); err != nil { 141 glog.Exitf("Failed to start HTTP server on %v: %v", *httpEndpoint, err) 142 } 143 } 144 145 // Start the sequencing loop, which will run until we terminate the process. This controls 146 // both sequencing and signing. 147 // TODO(Martin2112): Should respect read only mode and the flags in tree control etc 148 log.QuotaIncreaseFactor = *quotaIncreaseFactor 149 sequencerManager := server.NewSequencerManager(registry, *sequencerGuardWindowFlag) 150 info := server.LogOperationInfo{ 151 Registry: registry, 152 BatchSize: *batchSizeFlag, 153 NumWorkers: *numSeqFlag, 154 RunInterval: *sequencerIntervalFlag, 155 TimeSource: util.SystemTimeSource{}, 156 ElectionConfig: election.RunnerConfig{ 157 PreElectionPause: *preElectionPause, 158 MasterCheckInterval: *masterCheckInterval, 159 MasterHoldInterval: *masterHoldInterval, 160 ResignOdds: *resignOdds, 161 TimeSource: util.SystemTimeSource{}, 162 }, 163 } 164 sequencerTask := server.NewLogOperationManager(info, sequencerManager) 165 sequencerTask.OperationLoop(ctx) 166 167 // Give things a few seconds to tidy up 168 glog.Infof("Stopping server, about to exit") 169 time.Sleep(time.Second * 5) 170 } 171 172 func healthzFunc(as storage.AdminStorage, deadline time.Duration) func(http.ResponseWriter, *http.Request) { 173 if deadline == 0 { 174 deadline = 5 * time.Second 175 } 176 return func(w http.ResponseWriter, req *http.Request) { 177 ctx, cancel := context.WithTimeout(req.Context(), deadline) 178 defer cancel() 179 if err := as.CheckDatabaseAccessible(ctx); err != nil { 180 w.WriteHeader(http.StatusServiceUnavailable) 181 w.Write([]byte(err.Error())) 182 return 183 } 184 w.Write([]byte("ok")) 185 } 186 }