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  }