github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/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/cmd" 43 "github.com/google/trillian/cmd/createtree/keys" 44 "github.com/google/trillian/crypto/keyspb" 45 "github.com/google/trillian/crypto/sigpb" 46 "google.golang.org/grpc" 47 ) 48 49 var ( 50 adminServerAddr = flag.String("admin_server", "", "Address of the gRPC Trillian Admin Server (host:port)") 51 rpcDeadline = flag.Duration("rpc_deadline", time.Second*10, "Deadline for RPC requests") 52 53 treeState = flag.String("tree_state", trillian.TreeState_ACTIVE.String(), "State of the new tree") 54 treeType = flag.String("tree_type", trillian.TreeType_LOG.String(), "Type of the new tree") 55 hashStrategy = flag.String("hash_strategy", trillian.HashStrategy_RFC6962_SHA256.String(), "Hash strategy (aka preimage protection) of the new tree") 56 hashAlgorithm = flag.String("hash_algorithm", sigpb.DigitallySigned_SHA256.String(), "Hash algorithm of the new tree") 57 signatureAlgorithm = flag.String("signature_algorithm", sigpb.DigitallySigned_ECDSA.String(), "Signature algorithm of the new tree") 58 displayName = flag.String("display_name", "", "Display name of the new tree") 59 description = flag.String("description", "", "Description of the new tree") 60 maxRootDuration = flag.Duration("max_root_duration", 0, "Interval after which a new signed root is produced despite no submissions; zero means never") 61 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.") 62 63 configFile = flag.String("config", "", "Config file containing flags, file contents can be overridden by command line flags") 64 65 errAdminAddrNotSet = errors.New("empty --admin_server, please provide the Admin server host:port") 66 ) 67 68 // TODO(Martin2112): Pass everything needed into this and don't refer to flags. 69 func createTree(ctx context.Context) (*trillian.Tree, error) { 70 if *adminServerAddr == "" { 71 return nil, errAdminAddrNotSet 72 } 73 74 req, err := newRequest() 75 if err != nil { 76 return nil, err 77 } 78 79 conn, err := grpc.Dial(*adminServerAddr, grpc.WithInsecure()) 80 if err != nil { 81 return nil, fmt.Errorf("failed to dial %v: %v", *adminServerAddr, err) 82 } 83 defer conn.Close() 84 85 adminClient := trillian.NewTrillianAdminClient(conn) 86 mapClient := trillian.NewTrillianMapClient(conn) 87 logClient := trillian.NewTrillianLogClient(conn) 88 89 return client.CreateAndInitTree(ctx, req, adminClient, mapClient, logClient) 90 } 91 92 func newRequest() (*trillian.CreateTreeRequest, error) { 93 ts, ok := trillian.TreeState_value[*treeState] 94 if !ok { 95 return nil, fmt.Errorf("unknown TreeState: %v", *treeState) 96 } 97 98 tt, ok := trillian.TreeType_value[*treeType] 99 if !ok { 100 return nil, fmt.Errorf("unknown TreeType: %v", *treeType) 101 } 102 103 hs, ok := trillian.HashStrategy_value[*hashStrategy] 104 if !ok { 105 return nil, fmt.Errorf("unknown HashStrategy: %v", *hashStrategy) 106 } 107 108 ha, ok := sigpb.DigitallySigned_HashAlgorithm_value[*hashAlgorithm] 109 if !ok { 110 return nil, fmt.Errorf("unknown HashAlgorithm: %v", *hashAlgorithm) 111 } 112 113 sa, ok := sigpb.DigitallySigned_SignatureAlgorithm_value[*signatureAlgorithm] 114 if !ok { 115 return nil, fmt.Errorf("unknown SignatureAlgorithm: %v", *signatureAlgorithm) 116 } 117 118 ctr := &trillian.CreateTreeRequest{Tree: &trillian.Tree{ 119 TreeState: trillian.TreeState(ts), 120 TreeType: trillian.TreeType(tt), 121 HashStrategy: trillian.HashStrategy(hs), 122 HashAlgorithm: sigpb.DigitallySigned_HashAlgorithm(ha), 123 SignatureAlgorithm: sigpb.DigitallySigned_SignatureAlgorithm(sa), 124 DisplayName: *displayName, 125 Description: *description, 126 MaxRootDuration: ptypes.DurationProto(*maxRootDuration), 127 }} 128 glog.Infof("Creating tree %+v", ctr.Tree) 129 130 if *privateKeyFormat != "" { 131 pk, err := keys.New(*privateKeyFormat) 132 if err != nil { 133 return nil, err 134 } 135 ctr.Tree.PrivateKey = pk 136 } else { 137 ctr.KeySpec = &keyspb.Specification{} 138 139 switch sigpb.DigitallySigned_SignatureAlgorithm(sa) { 140 case sigpb.DigitallySigned_ECDSA: 141 ctr.KeySpec.Params = &keyspb.Specification_EcdsaParams{ 142 EcdsaParams: &keyspb.Specification_ECDSA{}, 143 } 144 case sigpb.DigitallySigned_RSA: 145 ctr.KeySpec.Params = &keyspb.Specification_RsaParams{ 146 RsaParams: &keyspb.Specification_RSA{}, 147 } 148 default: 149 return nil, fmt.Errorf("unsupported signature algorithm: %v", sa) 150 } 151 } 152 153 return ctr, nil 154 } 155 156 func main() { 157 flag.Parse() 158 defer glog.Flush() 159 160 if *configFile != "" { 161 if err := cmd.ParseFlagFile(*configFile); err != nil { 162 glog.Exitf("Failed to load flags from config file %q: %s", *configFile, err) 163 } 164 } 165 166 ctx, cancel := context.WithTimeout(context.Background(), *rpcDeadline) 167 defer cancel() 168 tree, err := createTree(ctx) 169 if err != nil { 170 glog.Exitf("Failed to create tree: %v", err) 171 } 172 173 // DO NOT change the output format, scripts are meant to depend on it. 174 // If you really want to change it, provide an output_format flag and 175 // keep the default as-is. 176 fmt.Println(tree.TreeId) 177 }