github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/serve/sign.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 "encoding/json" 13 "fmt" 14 "net/http" 15 "strings" 16 17 "github.com/vchain-us/vcn/pkg/api" 18 "github.com/vchain-us/vcn/pkg/cmd/internal/types" 19 "github.com/vchain-us/vcn/pkg/extractor" 20 "github.com/vchain-us/vcn/pkg/meta" 21 ) 22 23 type handler struct { 24 lcHost string 25 lcPort string 26 lcCert string 27 lcSkipTlsVerify bool 28 lcNoTls bool 29 } 30 31 func (sh *handler) signHandler(state meta.Status) func(w http.ResponseWriter, r *http.Request) { 32 return func(w http.ResponseWriter, r *http.Request) { 33 s := state 34 k := make(map[string]bool) 35 for _, scheme := range extractor.Schemes() { 36 k[scheme] = true 37 } 38 if sh.lcHost != "" && sh.lcPort != "" { 39 // todo @Michele move getLcUser in handler sh constructor 40 lcUser, err := getLcUser(r, sh.lcHost, sh.lcPort, sh.lcCert, sh.lcSkipTlsVerify, sh.lcNoTls) 41 if err != nil { 42 writeError(w, http.StatusBadGateway, err) 43 return 44 } 45 lcSign(lcUser, s, k, w, r) 46 return 47 } 48 sign(s, k, w, r) 49 } 50 } 51 52 func sign(status meta.Status, kinds map[string]bool, w http.ResponseWriter, r *http.Request) { 53 user, passphrase, err := getCredential(r) 54 if err != nil { 55 writeError(w, http.StatusUnauthorized, err) 56 return 57 } 58 if user == nil { 59 writeError(w, http.StatusUnauthorized, fmt.Errorf("bad or missing credentials")) 60 return 61 } 62 63 keyin, _, offline, err := user.Secret() 64 if err != nil { 65 writeError(w, http.StatusConflict, err) 66 return 67 } 68 if offline { 69 writeError(w, http.StatusConflict, fmt.Errorf("offline secret is not yet supported")) 70 return 71 } 72 73 opts := []api.SignOption{ 74 api.SignWithKey(keyin, passphrase), 75 api.SignWithStatus(status), 76 } 77 78 if _, public := r.URL.Query()["public"]; public { 79 opts = append(opts, api.SignWithVisibility(meta.VisibilityPublic)) 80 } 81 82 decoder := json.NewDecoder(r.Body) 83 var artifact api.Artifact 84 err = decoder.Decode(&artifact) 85 86 if err != nil { 87 writeError(w, http.StatusBadRequest, err) 88 return 89 } 90 91 if artifact.Name == "" { 92 writeError(w, http.StatusBadRequest, fmt.Errorf("name cannot be empty")) 93 return 94 } 95 96 if !kinds[artifact.Kind] { 97 writeError(w, http.StatusBadRequest, fmt.Errorf(`"%s" is not a valid value for kind`, artifact.Kind)) 98 return 99 } 100 101 artifact.Hash = strings.ToLower(artifact.Hash) 102 103 verification, err := user.Sign( 104 artifact, 105 opts..., 106 ) 107 108 // todo(ameingast/leogr): remove reduntat event - need backend improvement 109 api.TrackPublisher(user, meta.VcnSignEvent) 110 api.TrackSign(user, artifact.Hash, artifact.Name, status) 111 112 if err != nil { 113 writeError(w, http.StatusBadRequest, err) 114 return 115 } 116 117 var ar *api.ArtifactResponse 118 if !verification.Unknown() { 119 ar, _ = api.LoadArtifact(user, artifact.Hash, verification.MetaHash()) 120 } 121 122 writeResult(w, http.StatusOK, types.NewResult(&artifact, ar, verification)) 123 }