gitee.com/Mydawng/fabric-ca@v2.0.0-alpha.0.20201214145411-9ea68369cb61+incompatible/lib/identity.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 "encoding/json" 11 "fmt" 12 "net/http" 13 "strconv" 14 15 "github.com/cloudflare/cfssl/log" 16 "github.com/hyperledger/fabric-ca/internal/pkg/api" 17 "github.com/hyperledger/fabric-ca/internal/pkg/util" 18 "github.com/hyperledger/fabric-ca/lib/client/credential" 19 "github.com/hyperledger/fabric-ca/lib/client/credential/idemix" 20 "github.com/hyperledger/fabric-ca/lib/client/credential/x509" 21 "github.com/hyperledger/fabric/bccsp" 22 "github.com/pkg/errors" 23 ) 24 25 // Identity is fabric-ca's implementation of an identity 26 type Identity struct { 27 name string 28 client *Client 29 creds []credential.Credential 30 } 31 32 // NewIdentity is the constructor for identity 33 func NewIdentity(client *Client, name string, creds []credential.Credential) *Identity { 34 id := new(Identity) 35 id.name = name 36 id.client = client 37 id.creds = creds 38 return id 39 } 40 41 // GetName returns the identity name 42 func (i *Identity) GetName() string { 43 return i.name 44 } 45 46 // GetClient returns the client associated with this identity 47 func (i *Identity) GetClient() *Client { 48 return i.client 49 } 50 51 // GetIdemixCredential returns Idemix credential of this identity 52 func (i *Identity) GetIdemixCredential() credential.Credential { 53 for _, cred := range i.creds { 54 if cred.Type() == idemix.CredType { 55 return cred 56 } 57 } 58 return nil 59 } 60 61 // GetX509Credential returns X509 credential of this identity 62 func (i *Identity) GetX509Credential() credential.Credential { 63 for _, cred := range i.creds { 64 if cred.Type() == x509.CredType { 65 return cred 66 } 67 } 68 return nil 69 } 70 71 // GetECert returns the enrollment certificate signer for this identity 72 // Returns nil if the identity does not have a X509 credential 73 func (i *Identity) GetECert() *x509.Signer { 74 for _, cred := range i.creds { 75 if cred.Type() == x509.CredType { 76 v, _ := cred.Val() 77 if v != nil { 78 s, _ := v.(*x509.Signer) 79 return s 80 } 81 } 82 } 83 return nil 84 } 85 86 // Register registers a new identity 87 // @param req The registration request 88 func (i *Identity) Register(req *api.RegistrationRequest) (rr *api.RegistrationResponse, err error) { 89 log.Debugf("Register %+v", req) 90 if req.Name == "" { 91 return nil, errors.New("Register was called without a Name set") 92 } 93 94 reqBody, err := util.Marshal(req, "RegistrationRequest") 95 if err != nil { 96 return nil, err 97 } 98 99 // Send a post to the "register" endpoint with req as body 100 resp := &api.RegistrationResponse{} 101 err = i.Post("register", reqBody, resp, nil) 102 if err != nil { 103 return nil, err 104 } 105 106 log.Debug("The register request completed successfully") 107 return resp, nil 108 } 109 110 // RegisterAndEnroll registers and enrolls an identity and returns the identity 111 func (i *Identity) RegisterAndEnroll(req *api.RegistrationRequest) (*Identity, error) { 112 if i.client == nil { 113 return nil, errors.New("No client is associated with this identity") 114 } 115 rresp, err := i.Register(req) 116 if err != nil { 117 return nil, errors.WithMessage(err, fmt.Sprintf("Failed to register %s", req.Name)) 118 } 119 eresp, err := i.client.Enroll(&api.EnrollmentRequest{ 120 Name: req.Name, 121 Secret: rresp.Secret, 122 }) 123 if err != nil { 124 return nil, errors.WithMessage(err, fmt.Sprintf("Failed to enroll %s", req.Name)) 125 } 126 return eresp.Identity, nil 127 } 128 129 // Reenroll reenrolls an existing Identity and returns a new Identity 130 // @param req The reenrollment request 131 func (i *Identity) Reenroll(req *api.ReenrollmentRequest) (*EnrollmentResponse, error) { 132 log.Debugf("Reenrolling %s", util.StructToString(req)) 133 134 var ( 135 key bccsp.Key 136 csrPEM []byte 137 err error 138 ) 139 if req.CSR != nil && req.CSR.KeyRequest != nil { 140 if req.CSR.KeyRequest.ReuseKey { 141 val, err := i.GetX509Credential().Val() 142 if err != nil { 143 return nil, err 144 } 145 key = val.(*x509.Signer).Key() 146 csrPEM, key, err = i.client.GenCSRUsingKey(req.CSR, i.GetName(), key) 147 if err != nil { 148 return nil, err 149 } 150 } 151 } 152 153 if csrPEM == nil { 154 csrPEM, key, err = i.client.GenCSR(req.CSR, i.GetName()) 155 if err != nil { 156 return nil, err 157 } 158 } 159 160 reqNet := &api.ReenrollmentRequestNet{ 161 CAName: req.CAName, 162 AttrReqs: req.AttrReqs, 163 } 164 165 // Get the body of the request 166 if req.CSR != nil { 167 reqNet.SignRequest.Hosts = req.CSR.Hosts 168 } 169 reqNet.SignRequest.Request = string(csrPEM) 170 reqNet.SignRequest.Profile = req.Profile 171 reqNet.SignRequest.Label = req.Label 172 173 body, err := util.Marshal(reqNet, "SignRequest") 174 if err != nil { 175 return nil, err 176 } 177 var result api.EnrollmentResponseNet 178 err = i.Post("reenroll", body, &result, nil) 179 if err != nil { 180 return nil, err 181 } 182 return i.client.newEnrollmentResponse(&result, i.GetName(), key) 183 } 184 185 // Revoke the identity associated with 'id' 186 func (i *Identity) Revoke(req *api.RevocationRequest) (*api.RevocationResponse, error) { 187 log.Debugf("Entering identity.Revoke %+v", req) 188 reqBody, err := util.Marshal(req, "RevocationRequest") 189 if err != nil { 190 return nil, err 191 } 192 var result revocationResponseNet 193 err = i.Post("revoke", reqBody, &result, nil) 194 if err != nil { 195 return nil, err 196 } 197 log.Debugf("Successfully revoked certificates: %+v", req) 198 crl, err := util.B64Decode(result.CRL) 199 if err != nil { 200 return nil, err 201 } 202 return &api.RevocationResponse{RevokedCerts: result.RevokedCerts, CRL: crl}, nil 203 } 204 205 // RevokeSelf revokes the current identity and all certificates 206 func (i *Identity) RevokeSelf() (*api.RevocationResponse, error) { 207 name := i.GetName() 208 log.Debugf("RevokeSelf %s", name) 209 req := &api.RevocationRequest{ 210 Name: name, 211 } 212 return i.Revoke(req) 213 } 214 215 // GenCRL generates CRL 216 func (i *Identity) GenCRL(req *api.GenCRLRequest) (*api.GenCRLResponse, error) { 217 log.Debugf("Entering identity.GenCRL %+v", req) 218 reqBody, err := util.Marshal(req, "GenCRLRequest") 219 if err != nil { 220 return nil, err 221 } 222 var result genCRLResponseNet 223 err = i.Post("gencrl", reqBody, &result, nil) 224 if err != nil { 225 return nil, err 226 } 227 log.Debugf("Successfully generated CRL: %+v", req) 228 crl, err := util.B64Decode(result.CRL) 229 if err != nil { 230 return nil, err 231 } 232 return &api.GenCRLResponse{CRL: crl}, nil 233 } 234 235 // GetCRI gets Idemix credential revocation information (CRI) 236 func (i *Identity) GetCRI(req *api.GetCRIRequest) (*api.GetCRIResponse, error) { 237 log.Debugf("Entering identity.GetCRI %+v", req) 238 reqBody, err := util.Marshal(req, "GetCRIRequest") 239 if err != nil { 240 return nil, err 241 } 242 var result api.GetCRIResponse 243 err = i.Post("idemix/cri", reqBody, &result, nil) 244 if err != nil { 245 return nil, err 246 } 247 log.Debugf("Successfully generated CRI: %+v", req) 248 return &result, nil 249 } 250 251 // GetIdentity returns information about the requested identity 252 func (i *Identity) GetIdentity(id, caname string) (*api.GetIDResponse, error) { 253 log.Debugf("Entering identity.GetIdentity %s", id) 254 result := &api.GetIDResponse{} 255 err := i.Get(fmt.Sprintf("identities/%s", id), caname, result) 256 if err != nil { 257 return nil, err 258 } 259 260 log.Debugf("Successfully retrieved identity: %+v", result) 261 return result, nil 262 } 263 264 // GetAllIdentities returns all identities that the caller is authorized to see 265 func (i *Identity) GetAllIdentities(caname string, cb func(*json.Decoder) error) error { 266 log.Debugf("Entering identity.GetAllIdentities") 267 queryParam := make(map[string]string) 268 queryParam["ca"] = caname 269 err := i.GetStreamResponse("identities", queryParam, "result.identities", cb) 270 if err != nil { 271 return err 272 } 273 log.Debugf("Successfully retrieved identities") 274 return nil 275 } 276 277 // AddIdentity adds a new identity to the server 278 func (i *Identity) AddIdentity(req *api.AddIdentityRequest) (*api.IdentityResponse, error) { 279 log.Debugf("Entering identity.AddIdentity with request: %+v", req) 280 if req.ID == "" { 281 return nil, errors.New("Adding identity with no 'ID' set") 282 } 283 284 reqBody, err := util.Marshal(req, "addIdentity") 285 if err != nil { 286 return nil, err 287 } 288 289 // Send a post to the "identities" endpoint with req as body 290 result := &api.IdentityResponse{} 291 err = i.Post("identities", reqBody, result, nil) 292 if err != nil { 293 return nil, err 294 } 295 296 log.Debugf("Successfully added new identity '%s'", result.ID) 297 return result, nil 298 } 299 300 // ModifyIdentity modifies an existing identity on the server 301 func (i *Identity) ModifyIdentity(req *api.ModifyIdentityRequest) (*api.IdentityResponse, error) { 302 log.Debugf("Entering identity.ModifyIdentity with request: %+v", req) 303 if req.ID == "" { 304 return nil, errors.New("Name of identity to be modified not specified") 305 } 306 307 reqBody, err := util.Marshal(req, "modifyIdentity") 308 if err != nil { 309 return nil, err 310 } 311 312 // Send a put to the "identities" endpoint with req as body 313 result := &api.IdentityResponse{} 314 err = i.Put(fmt.Sprintf("identities/%s", req.ID), reqBody, nil, result) 315 if err != nil { 316 return nil, err 317 } 318 319 log.Debugf("Successfully modified identity '%s'", result.ID) 320 return result, nil 321 } 322 323 // RemoveIdentity removes a new identity from the server 324 func (i *Identity) RemoveIdentity(req *api.RemoveIdentityRequest) (*api.IdentityResponse, error) { 325 log.Debugf("Entering identity.RemoveIdentity with request: %+v", req) 326 id := req.ID 327 if id == "" { 328 return nil, errors.New("Name of the identity to removed is required") 329 } 330 331 // Send a delete to the "identities" endpoint id as a path parameter 332 result := &api.IdentityResponse{} 333 queryParam := make(map[string]string) 334 queryParam["force"] = strconv.FormatBool(req.Force) 335 queryParam["ca"] = req.CAName 336 err := i.Delete(fmt.Sprintf("identities/%s", id), result, queryParam) 337 if err != nil { 338 return nil, err 339 } 340 341 log.Debugf("Successfully removed identity: %s", id) 342 return result, nil 343 } 344 345 // GetAffiliation returns information about the requested affiliation 346 func (i *Identity) GetAffiliation(affiliation, caname string) (*api.AffiliationResponse, error) { 347 log.Debugf("Entering identity.GetAffiliation %+v", affiliation) 348 result := &api.AffiliationResponse{} 349 err := i.Get(fmt.Sprintf("affiliations/%s", affiliation), caname, result) 350 if err != nil { 351 return nil, err 352 } 353 log.Debugf("Successfully retrieved affiliation: %+v", result) 354 return result, nil 355 } 356 357 // GetAllAffiliations returns all affiliations that the caller is authorized to see 358 func (i *Identity) GetAllAffiliations(caname string) (*api.AffiliationResponse, error) { 359 log.Debugf("Entering identity.GetAllAffiliations") 360 result := &api.AffiliationResponse{} 361 err := i.Get("affiliations", caname, result) 362 if err != nil { 363 return nil, err 364 } 365 log.Debug("Successfully retrieved affiliations") 366 return result, nil 367 } 368 369 // AddAffiliation adds a new affiliation to the server 370 func (i *Identity) AddAffiliation(req *api.AddAffiliationRequest) (*api.AffiliationResponse, error) { 371 log.Debugf("Entering identity.AddAffiliation with request: %+v", req) 372 if req.Name == "" { 373 return nil, errors.New("Affiliation to add was not specified") 374 } 375 376 reqBody, err := util.Marshal(req, "addAffiliation") 377 if err != nil { 378 return nil, err 379 } 380 381 // Send a post to the "affiliations" endpoint with req as body 382 result := &api.AffiliationResponse{} 383 queryParam := make(map[string]string) 384 queryParam["force"] = strconv.FormatBool(req.Force) 385 err = i.Post("affiliations", reqBody, result, queryParam) 386 if err != nil { 387 return nil, err 388 } 389 390 log.Debugf("Successfully added new affiliation") 391 return result, nil 392 } 393 394 // ModifyAffiliation renames an existing affiliation on the server 395 func (i *Identity) ModifyAffiliation(req *api.ModifyAffiliationRequest) (*api.AffiliationResponse, error) { 396 log.Debugf("Entering identity.ModifyAffiliation with request: %+v", req) 397 modifyAff := req.Name 398 if modifyAff == "" { 399 return nil, errors.New("Affiliation to modify was not specified") 400 } 401 402 if req.NewName == "" { 403 return nil, errors.New("New affiliation not specified") 404 } 405 406 reqBody, err := util.Marshal(req, "modifyIdentity") 407 if err != nil { 408 return nil, err 409 } 410 411 // Send a put to the "affiliations" endpoint with req as body 412 result := &api.AffiliationResponse{} 413 queryParam := make(map[string]string) 414 queryParam["force"] = strconv.FormatBool(req.Force) 415 err = i.Put(fmt.Sprintf("affiliations/%s", modifyAff), reqBody, queryParam, result) 416 if err != nil { 417 return nil, err 418 } 419 420 log.Debugf("Successfully modified affiliation") 421 return result, nil 422 } 423 424 // RemoveAffiliation removes an existing affiliation from the server 425 func (i *Identity) RemoveAffiliation(req *api.RemoveAffiliationRequest) (*api.AffiliationResponse, error) { 426 log.Debugf("Entering identity.RemoveAffiliation with request: %+v", req) 427 removeAff := req.Name 428 if removeAff == "" { 429 return nil, errors.New("Affiliation to remove was not specified") 430 } 431 432 // Send a delete to the "affiliations" endpoint with the affiliation as a path parameter 433 result := &api.AffiliationResponse{} 434 queryParam := make(map[string]string) 435 queryParam["force"] = strconv.FormatBool(req.Force) 436 queryParam["ca"] = req.CAName 437 err := i.Delete(fmt.Sprintf("affiliations/%s", removeAff), result, queryParam) 438 if err != nil { 439 return nil, err 440 } 441 442 log.Debugf("Successfully removed affiliation") 443 return result, nil 444 } 445 446 // GetCertificates returns all certificates that the caller is authorized to see 447 func (i *Identity) GetCertificates(req *api.GetCertificatesRequest, cb func(*json.Decoder) error) error { 448 log.Debugf("Entering identity.GetCertificates, sending request: %+v", req) 449 450 queryParam := make(map[string]string) 451 queryParam["id"] = req.ID 452 queryParam["aki"] = req.AKI 453 queryParam["serial"] = req.Serial 454 queryParam["revoked_start"] = req.Revoked.StartTime 455 queryParam["revoked_end"] = req.Revoked.EndTime 456 queryParam["expired_start"] = req.Expired.StartTime 457 queryParam["expired_end"] = req.Expired.EndTime 458 queryParam["notrevoked"] = strconv.FormatBool(req.NotRevoked) 459 queryParam["notexpired"] = strconv.FormatBool(req.NotExpired) 460 queryParam["ca"] = req.CAName 461 err := i.GetStreamResponse("certificates", queryParam, "result.certs", cb) 462 if err != nil { 463 return err 464 } 465 466 log.Debugf("Successfully completed getting certificates request") 467 return nil 468 } 469 470 // Store writes my identity info to disk 471 func (i *Identity) Store() error { 472 if i.client == nil { 473 return errors.New("An identity with no client may not be stored") 474 } 475 for _, cred := range i.creds { 476 err := cred.Store() 477 if err != nil { 478 return err 479 } 480 } 481 return nil 482 } 483 484 // Get sends a get request to an endpoint 485 func (i *Identity) Get(endpoint, caname string, result interface{}) error { 486 req, err := i.client.newGet(endpoint) 487 if err != nil { 488 return err 489 } 490 if caname != "" { 491 addQueryParm(req, "ca", caname) 492 } 493 err = i.addTokenAuthHdr(req, nil) 494 if err != nil { 495 return err 496 } 497 return i.client.SendReq(req, result) 498 } 499 500 // GetStreamResponse sends a request to an endpoint and streams the response 501 func (i *Identity) GetStreamResponse(endpoint string, queryParam map[string]string, stream string, cb func(*json.Decoder) error) error { 502 req, err := i.client.newGet(endpoint) 503 if err != nil { 504 return err 505 } 506 if queryParam != nil { 507 for key, value := range queryParam { 508 if value != "" { 509 addQueryParm(req, key, value) 510 } 511 } 512 } 513 err = i.addTokenAuthHdr(req, nil) 514 if err != nil { 515 return err 516 } 517 return i.client.StreamResponse(req, stream, cb) 518 } 519 520 // Put sends a put request to an endpoint 521 func (i *Identity) Put(endpoint string, reqBody []byte, queryParam map[string]string, result interface{}) error { 522 req, err := i.client.newPut(endpoint, reqBody) 523 if err != nil { 524 return err 525 } 526 if queryParam != nil { 527 for key, value := range queryParam { 528 addQueryParm(req, key, value) 529 } 530 } 531 err = i.addTokenAuthHdr(req, reqBody) 532 if err != nil { 533 return err 534 } 535 return i.client.SendReq(req, result) 536 } 537 538 // Delete sends a delete request to an endpoint 539 func (i *Identity) Delete(endpoint string, result interface{}, queryParam map[string]string) error { 540 req, err := i.client.newDelete(endpoint) 541 if err != nil { 542 return err 543 } 544 if queryParam != nil { 545 for key, value := range queryParam { 546 addQueryParm(req, key, value) 547 } 548 } 549 err = i.addTokenAuthHdr(req, nil) 550 if err != nil { 551 return err 552 } 553 return i.client.SendReq(req, result) 554 } 555 556 // Post sends arbitrary request body (reqBody) to an endpoint. 557 // This adds an authorization header which contains the signature 558 // of this identity over the body and non-signature part of the authorization header. 559 // The return value is the body of the response. 560 func (i *Identity) Post(endpoint string, reqBody []byte, result interface{}, queryParam map[string]string) error { 561 req, err := i.client.newPost(endpoint, reqBody) 562 if err != nil { 563 return err 564 } 565 if queryParam != nil { 566 for key, value := range queryParam { 567 addQueryParm(req, key, value) 568 } 569 } 570 err = i.addTokenAuthHdr(req, reqBody) 571 if err != nil { 572 return err 573 } 574 return i.client.SendReq(req, result) 575 } 576 577 func (i *Identity) addTokenAuthHdr(req *http.Request, body []byte) error { 578 log.Debug("Adding token-based authorization header") 579 var token string 580 var err error 581 for _, cred := range i.creds { 582 token, err = cred.CreateToken(req, body) 583 if err != nil { 584 return errors.WithMessage(err, "Failed to add token authorization header") 585 } 586 break 587 } 588 req.Header.Set("authorization", token) 589 return nil 590 }