github.com/ldc1995/fabric-ca@v2.0.0-alpha.0.20200422214819-8d49c278c386+incompatible/lib/serverregister.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 "net/url" 12 13 "github.com/cloudflare/cfssl/log" 14 "github.com/hyperledger/fabric-ca/api" 15 "github.com/hyperledger/fabric-ca/lib/attr" 16 "github.com/hyperledger/fabric-ca/lib/caerrors" 17 "github.com/hyperledger/fabric-ca/lib/server/user" 18 "github.com/hyperledger/fabric-ca/util" 19 20 "github.com/pkg/errors" 21 ) 22 23 func newRegisterEndpoint(s *Server) *serverEndpoint { 24 return &serverEndpoint{ 25 Path: "register", 26 Methods: []string{"POST"}, 27 Handler: registerHandler, 28 Server: s, 29 successRC: 201, 30 } 31 } 32 33 // Handle a register request 34 func registerHandler(ctx *serverRequestContextImpl) (interface{}, error) { 35 ca, err := ctx.GetCA() 36 if err != nil { 37 return nil, err 38 } 39 return register(ctx, ca) 40 } 41 42 func register(ctx ServerRequestContext, ca *CA) (interface{}, error) { 43 // Read request body 44 var req api.RegistrationRequestNet 45 err := ctx.ReadBody(&req) 46 if err != nil { 47 return nil, err 48 } 49 // Authenticate 50 callerID, err := ctx.TokenAuthentication() 51 if err != nil { 52 return nil, err 53 } 54 log.Debugf("Received registration request from %s: %v", callerID, &req) 55 if ctx.IsLDAPEnabled() { 56 return nil, caerrors.NewHTTPErr(403, caerrors.ErrInvalidLDAPAction, "Registration is not supported when using LDAP") 57 } 58 // Register User 59 secret, err := registerUser(&req.RegistrationRequest, callerID, ca, ctx) 60 if err != nil { 61 return nil, err 62 } 63 // Return response 64 resp := &api.RegistrationResponseNet{ 65 RegistrationResponse: api.RegistrationResponse{Secret: secret}, 66 } 67 return resp, nil 68 } 69 70 // RegisterUser will register a user and return the secret 71 func registerUser(req *api.RegistrationRequest, registrar string, ca *CA, ctx ServerRequestContext) (string, error) { 72 var err error 73 var registrarUser user.User 74 75 registrarUser, err = ctx.GetCaller() 76 if err != nil { 77 return "", err 78 } 79 80 normalizeRegistrationRequest(req, registrarUser) 81 82 // Check the permissions of member named 'registrar' to perform this registration 83 err = canRegister(registrarUser, req, ca, ctx) 84 if err != nil { 85 log.Debugf("Registrar is not allowed to register user '%s': %s", req.Name, err) 86 return "", caerrors.NewAuthorizationErr(caerrors.ErrRegistrarRegAuth, "Registration of '%s' failed", req.Name) 87 } 88 89 secret, err := registerUserID(req, ca) 90 if err != nil { 91 return "", errors.WithMessagef(err, "Registration of '%s' failed", req.Name) 92 } 93 // Set the location header to the URI of the identity that was created by the registration request 94 ctx.GetResp().Header().Set("Location", fmt.Sprintf("%sidentities/%s", apiPathPrefix, url.PathEscape(req.Name))) 95 return secret, nil 96 } 97 98 func normalizeRegistrationRequest(req *api.RegistrationRequest, registrar user.User) { 99 if req.Affiliation == "" { 100 registrarAff := user.GetAffiliation(registrar) 101 log.Debugf("No affiliation provided in registration request, will default to using registrar's affiliation of '%s'", registrarAff) 102 req.Affiliation = registrarAff 103 } else if req.Affiliation == "." { 104 // Affiliation request of '.' signifies request for root affiliation 105 req.Affiliation = "" 106 } 107 108 if req.Type == "" { 109 req.Type = registrar.GetType() 110 } 111 } 112 113 func validateAffiliation(req *api.RegistrationRequest, ca *CA, ctx ServerRequestContext) error { 114 affiliation := req.Affiliation 115 log.Debugf("Validating affiliation: %s", affiliation) 116 err := ctx.ContainsAffiliation(affiliation) 117 if err != nil { 118 return err 119 } 120 121 // If requested affiliation is for root then don't need to do lookup in affiliation's table 122 if affiliation == "" { 123 return nil 124 } 125 126 _, err = ca.registry.GetAffiliation(affiliation) 127 if err != nil { 128 return caerrors.NewHTTPErr(404, caerrors.ErrGettingAffiliation, "Failed getting affiliation '%s': %s", affiliation, err) 129 } 130 131 return nil 132 } 133 134 // registerUserID registers a new user and its enrollmentID, role and state 135 func registerUserID(req *api.RegistrationRequest, ca *CA) (string, error) { 136 log.Debugf("Registering user id: %s\n", req.Name) 137 var err error 138 139 if req.Secret == "" { 140 req.Secret = util.RandomString(12) 141 } 142 143 req.MaxEnrollments, err = getMaxEnrollments(req.MaxEnrollments, ca.Config.Registry.MaxEnrollments) 144 if err != nil { 145 return "", err 146 } 147 148 // Add attributes containing the enrollment ID, type, and affiliation if not 149 // already defined 150 addAttributeToRequest(attr.EnrollmentID, req.Name, &req.Attributes) 151 addAttributeToRequest(attr.Type, req.Type, &req.Attributes) 152 addAttributeToRequest(attr.Affiliation, req.Affiliation, &req.Attributes) 153 154 insert := user.Info{ 155 Name: req.Name, 156 Pass: req.Secret, 157 Type: req.Type, 158 Affiliation: req.Affiliation, 159 Attributes: req.Attributes, 160 MaxEnrollments: req.MaxEnrollments, 161 Level: ca.server.levels.Identity, 162 } 163 164 registry := ca.registry 165 166 _, err = registry.GetUser(req.Name, nil) 167 if err == nil { 168 return "", caerrors.NewHTTPErr(409, caerrors.ErrDupIdentityReg, "Identity '%s' is already registered", req.Name) 169 } 170 171 err = registry.InsertUser(&insert) 172 if err != nil { 173 return "", err 174 } 175 176 return req.Secret, nil 177 } 178 179 func canRegister(registrar user.User, req *api.RegistrationRequest, ca *CA, ctx ServerRequestContext) error { 180 log.Debugf("canRegister - Check to see if user '%s' can register", registrar.GetName()) 181 182 err := ctx.CanActOnType(req.Type) 183 if err != nil { 184 return err 185 } 186 // Check that the affiliation requested is of the appropriate level 187 err = validateAffiliation(req, ca, ctx) 188 if err != nil { 189 return errors.WithMessagef(err, "Registration of '%s' failed in affiliation validation", req.Name) 190 } 191 192 err = attr.CanRegisterRequestedAttributes(req.Attributes, nil, registrar) 193 if err != nil { 194 return caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "Failed to register attribute: %s", err) 195 } 196 197 return nil 198 } 199 200 // Add an attribute to the registration request if not already found. 201 func addAttributeToRequest(name, value string, attributes *[]api.Attribute) { 202 *attributes = append(*attributes, api.Attribute{Name: name, Value: value, ECert: true}) 203 }