github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/serve/serve.go (about) 1 /* 2 * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved. 3 * This software is released under GPL3. 4 * The full license information can be found under: 5 * https://www.gnu.org/licenses/gpl-3.0.en.html 6 * 7 */ 8 9 package serve 10 11 import ( 12 "fmt" 13 "github.com/spf13/viper" 14 "net/http" 15 16 "github.com/gorilla/handlers" 17 "github.com/gorilla/mux" 18 "github.com/spf13/cobra" 19 "github.com/vchain-us/vcn/internal/logs" 20 "github.com/vchain-us/vcn/pkg/meta" 21 ) 22 23 // NewCommand returns the cobra command for `vcn serve` 24 func NewCommand() *cobra.Command { 25 cmd := &cobra.Command{ 26 Use: "serve", 27 Short: "Start a local API server", 28 Long: `Start a local API server 29 30 In Codenotary Cloud mode api key is required. Provide it using x-notarization-lc-api-key header on each request. 31 32 Environment variables: 33 VCN_USER= 34 VCN_PASSWORD= 35 VCN_NOTARIZATION_PASSWORD= 36 VCN_NOTARIZATION_PASSWORD_EMPTY= 37 VCN_OTP= 38 VCN_OTP_EMPTY= 39 VCN_LC_HOST= 40 VCN_LC_PORT= 41 VCN_LC_CERT= 42 VCN_LC_SKIP_TLS_VERIFY=false 43 VCN_LC_NO_TLS=false 44 `, 45 PreRunE: func(cmd *cobra.Command, args []string) error { 46 return viper.BindPFlags(cmd.Flags()) 47 }, 48 RunE: func(cmd *cobra.Command, args []string) error { 49 cmd.SilenceUsage = true 50 return runServe(cmd) 51 }, 52 Args: cobra.NoArgs, 53 } 54 cmd.Flags().String("host", "", "host address") 55 cmd.Flags().String("port", "8080", "port") 56 cmd.Flags().String("tls-cert-file", "", "TLS certificate file") 57 cmd.Flags().String("tls-key-file", "", "TLS key file") 58 59 cmd.Flags().String("lc-host", "", meta.VcnLcHostFlagDesc) 60 cmd.Flags().String("lc-port", "443", meta.VcnLcPortFlagDesc) 61 cmd.Flags().String("lc-cert", "", meta.VcnLcCertPathDesc) 62 cmd.Flags().Bool("lc-skip-tls-verify", false, meta.VcnLcSkipTlsVerifyDesc) 63 cmd.Flags().Bool("lc-no-tls", false, meta.VcnLcNoTlsDesc) 64 65 return cmd 66 } 67 68 func runServe(cmd *cobra.Command) error { 69 70 host, err := cmd.Flags().GetString("host") 71 if err != nil { 72 return nil 73 } 74 port, err := cmd.Flags().GetString("port") 75 if err != nil { 76 return nil 77 } 78 addr := host + ":" + port 79 80 certFile, _ := cmd.Flags().GetString("tls-cert-file") 81 keyFile, _ := cmd.Flags().GetString("tls-key-file") 82 if certFile != "" && keyFile == "" { 83 return fmt.Errorf("--tls-key-file is missing") 84 } 85 if certFile == "" && keyFile != "" { 86 return fmt.Errorf("--tls-cert-file is missing") 87 } 88 89 lcHost := viper.GetString("lc-host") 90 lcPort := viper.GetString("lc-port") 91 lcCert := viper.GetString("lc-cert") 92 skipTlsVerify := viper.GetBool("lc-skip-tls-verify") 93 noTls := viper.GetBool("lc-no-tls") 94 95 sh := handler{ 96 lcHost: lcHost, 97 lcPort: lcPort, 98 lcCert: lcCert, 99 lcSkipTlsVerify: skipTlsVerify, 100 lcNoTls: noTls, 101 } 102 103 router := mux.NewRouter().StrictSlash(true) 104 router.HandleFunc("/", index) 105 router.HandleFunc("/notarize", sh.signHandler(meta.StatusTrusted)).Methods("POST") 106 router.HandleFunc("/untrust", sh.signHandler(meta.StatusUntrusted)).Methods("POST") 107 router.HandleFunc("/unsupport", sh.signHandler(meta.StatusUnsupported)).Methods("POST") 108 router.HandleFunc("/authenticate/{hash}", sh.verify).Methods("GET") 109 router.HandleFunc("/inspect/{hash}", sh.inspectHandler).Methods("GET") 110 111 logs.LOG.Infof("Log level: %s", logs.LOG.GetLevel().String()) 112 logs.LOG.Infof("Stage: %s", meta.StageEnvironment().String()) 113 114 handler := handlers.CORS( 115 handlers.AllowedOrigins([]string{"*"}), 116 handlers.AllowedMethods([]string{"POST", "GET", "OPTIONS"}), 117 handlers.AllowedHeaders([]string{"content-type", "authorization", "x-notarization-password", "x-notarization-password-empty"}), 118 )(router) 119 120 if certFile != "" && keyFile != "" { 121 logs.LOG.Infof("Listening on %s (TLS)", addr) 122 return http.ListenAndServeTLS(addr, certFile, keyFile, handler) 123 } 124 125 logs.LOG.Infof("Listening on %s", addr) 126 return http.ListenAndServe(addr, handler) 127 } 128 129 func index(w http.ResponseWriter, r *http.Request) { 130 // can be used for healthcheck 131 writeResponse(w, http.StatusOK, []byte("OK")) 132 }