github.com/bartle-stripe/trillian@v1.2.1/cmd/createtree/main.go (about) 1 // Copyright 2017 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 // Package main contains the implementation and entry point for the createtree 16 // command. 17 // 18 // Example usage: 19 // $ ./createtree --admin_server=host:port 20 // 21 // The command outputs the tree ID of the created tree to stdout, or an error to 22 // stderr in case of failure. The output is minimal to allow for easy usage in 23 // automated scripts. 24 // 25 // Several flags are provided to configure the create tree, most of which try to 26 // assume reasonable defaults. Multiple types of private keys may be supported; 27 // one has only to set the appropriate --private_key_format value and supply the 28 // corresponding flags for the chosen key type. 29 package main 30 31 import ( 32 "context" 33 "errors" 34 "flag" 35 "fmt" 36 "time" 37 38 "github.com/golang/glog" 39 "github.com/golang/protobuf/ptypes" 40 "github.com/google/trillian" 41 "github.com/google/trillian/client" 42 "github.com/google/trillian/client/rpcflags" 43 "github.com/google/trillian/cmd" 44 "github.com/google/trillian/cmd/createtree/keys" 45 "github.com/google/trillian/crypto/keyspb" 46 "github.com/google/trillian/crypto/sigpb" 47 "google.golang.org/grpc" 48 ) 49 50 var ( 51 adminServerAddr = flag.String("admin_server", "", "Address of the gRPC Trillian Admin Server (host:port)") 52 rpcDeadline = flag.Duration("rpc_deadline", time.Second*10, "Deadline for RPC requests") 53 54 treeState = flag.String("tree_state", trillian.TreeState_ACTIVE.String(), "State of the new tree") 55 treeType = flag.String("tree_type", trillian.TreeType_LOG.String(), "Type of the new tree") 56 hashStrategy = flag.String("hash_strategy", trillian.HashStrategy_RFC6962_SHA256.String(), "Hash strategy (aka preimage protection) of the new tree") 57 hashAlgorithm = flag.String("hash_algorithm", sigpb.DigitallySigned_SHA256.String(), "Hash algorithm of the new tree") 58 signatureAlgorithm = flag.String("signature_algorithm", sigpb.DigitallySigned_ECDSA.String(), "Signature algorithm of the new tree") 59 displayName = flag.String("display_name", "", "Display name of the new tree") 60 description = flag.String("description", "", "Description of the new tree") 61 maxRootDuration = flag.Duration("max_root_duration", 0, "Interval after which a new signed root is produced despite no submissions; zero means never") 62 privateKeyFormat = flag.String("private_key_format", "", "Type of protobuf message to send the key as (PrivateKey, PEMKeyFile, or PKCS11ConfigFile). If empty, a key will be generated for you by Trillian.") 63 64 configFile = flag.String("config", "", "Config file containing flags, file contents can be overridden by command line flags") 65 66 errAdminAddrNotSet = errors.New("empty --admin_server, please provide the Admin server host:port") 67 ) 68 69 // TODO(Martin2112): Pass everything needed into this and don't refer to flags. 70 func createTree(ctx context.Context) (*trillian.Tree, error) { 71 if *adminServerAddr == "" { 72 return nil, errAdminAddrNotSet 73 } 74 75 req, err := newRequest() 76 if err != nil { 77 return nil, err 78 } 79 80 dialOpts, err := rpcflags.NewClientDialOptionsFromFlags() 81 if err != nil { 82 return nil, fmt.Errorf("failed to determine dial options: %v", err) 83 } 84 85 conn, err := grpc.Dial(*adminServerAddr, dialOpts...) 86 if err != nil { 87 return nil, fmt.Errorf("failed to dial %v: %v", *adminServerAddr, err) 88 } 89 defer conn.Close() 90 91 adminClient := trillian.NewTrillianAdminClient(conn) 92 mapClient := trillian.NewTrillianMapClient(conn) 93 logClient := trillian.NewTrillianLogClient(conn) 94 95 return client.CreateAndInitTree(ctx, req, adminClient, mapClient, logClient) 96 } 97 98 func newRequest() (*trillian.CreateTreeRequest, error) { 99 ts, ok := trillian.TreeState_value[*treeState] 100 if !ok { 101 return nil, fmt.Errorf("unknown TreeState: %v", *treeState) 102 } 103 104 tt, ok := trillian.TreeType_value[*treeType] 105 if !ok { 106 return nil, fmt.Errorf("unknown TreeType: %v", *treeType) 107 } 108 109 hs, ok := trillian.HashStrategy_value[*hashStrategy] 110 if !ok { 111 return nil, fmt.Errorf("unknown HashStrategy: %v", *hashStrategy) 112 } 113 114 ha, ok := sigpb.DigitallySigned_HashAlgorithm_value[*hashAlgorithm] 115 if !ok { 116 return nil, fmt.Errorf("unknown HashAlgorithm: %v", *hashAlgorithm) 117 } 118 119 sa, ok := sigpb.DigitallySigned_SignatureAlgorithm_value[*signatureAlgorithm] 120 if !ok { 121 return nil, fmt.Errorf("unknown SignatureAlgorithm: %v", *signatureAlgorithm) 122 } 123 124 ctr := &trillian.CreateTreeRequest{Tree: &trillian.Tree{ 125 TreeState: trillian.TreeState(ts), 126 TreeType: trillian.TreeType(tt), 127 HashStrategy: trillian.HashStrategy(hs), 128 HashAlgorithm: sigpb.DigitallySigned_HashAlgorithm(ha), 129 SignatureAlgorithm: sigpb.DigitallySigned_SignatureAlgorithm(sa), 130 DisplayName: *displayName, 131 Description: *description, 132 MaxRootDuration: ptypes.DurationProto(*maxRootDuration), 133 }} 134 glog.Infof("Creating tree %+v", ctr.Tree) 135 136 if *privateKeyFormat != "" { 137 pk, err := keys.New(*privateKeyFormat) 138 if err != nil { 139 return nil, err 140 } 141 ctr.Tree.PrivateKey = pk 142 } else { 143 ctr.KeySpec = &keyspb.Specification{} 144 145 switch sigpb.DigitallySigned_SignatureAlgorithm(sa) { 146 case sigpb.DigitallySigned_ECDSA: 147 ctr.KeySpec.Params = &keyspb.Specification_EcdsaParams{ 148 EcdsaParams: &keyspb.Specification_ECDSA{}, 149 } 150 case sigpb.DigitallySigned_RSA: 151 ctr.KeySpec.Params = &keyspb.Specification_RsaParams{ 152 RsaParams: &keyspb.Specification_RSA{}, 153 } 154 default: 155 return nil, fmt.Errorf("unsupported signature algorithm: %v", sa) 156 } 157 } 158 159 return ctr, nil 160 } 161 162 func main() { 163 flag.Parse() 164 defer glog.Flush() 165 166 if *configFile != "" { 167 if err := cmd.ParseFlagFile(*configFile); err != nil { 168 glog.Exitf("Failed to load flags from config file %q: %s", *configFile, err) 169 } 170 } 171 172 ctx, cancel := context.WithTimeout(context.Background(), *rpcDeadline) 173 defer cancel() 174 tree, err := createTree(ctx) 175 if err != nil { 176 glog.Exitf("Failed to create tree: %v", err) 177 } 178 179 // DO NOT change the output format, scripts are meant to depend on it. 180 // If you really want to change it, provide an output_format flag and 181 // keep the default as-is. 182 fmt.Println(tree.TreeId) 183 }