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