github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/lib/servercertificates.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lib 8 9 import ( 10 "fmt" 11 "os" 12 13 log "gitee.com/zhaochuninhefei/zcgolog/zclog" 14 http "github.com/hxx258456/ccgo/gmhttp" 15 "github.com/hxx258456/fabric-ca-gm/internal/pkg/util" 16 "github.com/hxx258456/fabric-ca-gm/lib/caerrors" 17 "github.com/hxx258456/fabric-ca-gm/lib/server/certificaterequest" 18 cadbuser "github.com/hxx258456/fabric-ca-gm/lib/server/user" 19 "github.com/pkg/errors" 20 ) 21 22 type certPEM struct { 23 PEM string `db:"pem"` 24 } 25 26 func newCertificateEndpoint(s *Server) *serverEndpoint { 27 return &serverEndpoint{ 28 Path: "certificates", 29 Methods: []string{"GET", "DELETE"}, 30 Handler: certificatesHandler, 31 Server: s, 32 successRC: 200, 33 } 34 } 35 36 func certificatesHandler(ctx *serverRequestContextImpl) (interface{}, error) { 37 // Process Request 38 err := processCertificateRequest(ctx) 39 if err != nil { 40 return nil, err 41 } 42 return nil, nil 43 } 44 45 // processCertificateRequest will process the certificate request 46 func processCertificateRequest(ctx ServerRequestContext) error { 47 log.Debug("Processing certificate request") 48 var err error 49 50 // Authenticate 51 _, err = ctx.TokenAuthentication() 52 if err != nil { 53 return err 54 } 55 56 // Perform authority checks to make sure that caller has the correct 57 // set of attributes to manage certificates 58 err = authChecks(ctx) 59 if err != nil { 60 return err 61 } 62 63 method := ctx.GetReq().Method 64 switch method { 65 case "GET": 66 return processGetCertificateRequest(ctx) 67 case "DELETE": 68 return errors.New("DELETE Not Implemented") 69 default: 70 return errors.Errorf("Invalid request: %s", method) 71 } 72 } 73 74 // authChecks verifies that the caller has either attribute "hf.Registrar.Roles" 75 // or "hf.Revoker" with a value of true 76 func authChecks(ctx ServerRequestContext) error { 77 log.Debug("Performing attribute authorization checks for certificates endpoint") 78 79 caller, err := ctx.GetCaller() 80 if err != nil { 81 return err 82 } 83 84 _, err = caller.GetAttribute("hf.Registrar.Roles") 85 if err != nil { 86 err = ctx.HasRole("hf.Revoker") 87 if err != nil { 88 return caerrors.NewAuthorizationErr(caerrors.ErrAuthorizationFailure, "Caller does not posses either hf.Registrar.Roles or hf.Revoker attribute") 89 } 90 } 91 92 return nil 93 } 94 95 func processGetCertificateRequest(ctx ServerRequestContext) error { 96 log.Debug("Processing GET certificate request") 97 var err error 98 99 req, err := certificaterequest.NewCertificateRequest(ctx) 100 if err != nil { 101 return caerrors.NewHTTPErr(400, caerrors.ErrGettingCert, "Invalid Request: %s", err) 102 } 103 104 // Execute DB query and stream response 105 err = getCertificates(ctx, req) 106 if err != nil { 107 return err 108 } 109 110 return nil 111 } 112 113 // getCertificates executes the DB query and streams the results to client 114 func getCertificates(ctx ServerRequestContext, req *certificaterequest.Impl) error { 115 w := ctx.GetResp() 116 flusher, _ := w.(http.Flusher) 117 118 caller, err := ctx.GetCaller() 119 if err != nil { 120 return err 121 } 122 123 // Execute DB query 124 rows, err := ctx.GetCertificates(req, cadbuser.GetAffiliation(caller)) 125 if err != nil { 126 return err 127 } 128 defer rows.Close() 129 130 // Get the number of certificates to return back to client in a chunk based on the environment variable 131 // If environment variable not set, default to 100 certificates 132 numCerts, err := ctx.ChunksToDeliver(os.Getenv("FABRIC_CA_SERVER_MAX_CERTS_PER_CHUNK")) 133 if err != nil { 134 return err 135 } 136 log.Debugf("Number of certs to be delivered in each chunk: %d", numCerts) 137 138 w.Write([]byte(`{"certs":[`)) 139 140 rowNumber := 0 141 for rows.Next() { 142 rowNumber++ 143 var cert certPEM 144 err := rows.StructScan(&cert) 145 if err != nil { 146 return caerrors.NewHTTPErr(500, caerrors.ErrGettingCert, "Failed to get read row: %s", err) 147 } 148 149 if rowNumber > 1 { 150 w.Write([]byte(",")) 151 } 152 153 resp, err := util.Marshal(cert, "certificate") 154 if err != nil { 155 return caerrors.NewHTTPErr(500, caerrors.ErrGettingCert, "Failed to marshal certificate: %s", err) 156 } 157 w.Write(resp) 158 159 // If hit the number of identities requested then flush 160 if rowNumber%numCerts == 0 { 161 flusher.Flush() // Trigger "chunked" encoding and send a chunk... 162 } 163 } 164 165 log.Debug("Number of certificates found: ", rowNumber) 166 167 // Close the JSON object 168 caname := ctx.GetQueryParm("ca") 169 w.Write([]byte(fmt.Sprintf("], \"caname\":\"%s\"}", caname))) 170 flusher.Flush() 171 172 return nil 173 }