github.com/hyperledger/fabric-ca@v2.0.0-alpha.0.20201120210307-7b4f34729db1+incompatible/lib/serverrequestcontext.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 "crypto/x509" 11 "encoding/hex" 12 "encoding/json" 13 "fmt" 14 "io/ioutil" 15 "net/http" 16 "strconv" 17 "strings" 18 19 "github.com/cloudflare/cfssl/config" 20 "github.com/cloudflare/cfssl/log" 21 "github.com/cloudflare/cfssl/revoke" 22 "github.com/cloudflare/cfssl/signer" 23 gmux "github.com/gorilla/mux" 24 "github.com/hyperledger/fabric-ca/internal/pkg/api" 25 "github.com/hyperledger/fabric-ca/internal/pkg/util" 26 "github.com/hyperledger/fabric-ca/lib/attr" 27 "github.com/hyperledger/fabric-ca/lib/attrmgr" 28 "github.com/hyperledger/fabric-ca/lib/caerrors" 29 cr "github.com/hyperledger/fabric-ca/lib/server/certificaterequest" 30 "github.com/hyperledger/fabric-ca/lib/server/idemix" 31 "github.com/hyperledger/fabric-ca/lib/server/user" 32 "github.com/jmoiron/sqlx" 33 "github.com/pkg/errors" 34 ) 35 36 // ServerRequestContext defines the functionality of a server request context object 37 type ServerRequestContext interface { 38 BasicAuthentication() (string, error) 39 TokenAuthentication() (string, error) 40 GetCaller() (user.User, error) 41 HasRole(role string) error 42 ChunksToDeliver(string) (int, error) 43 GetReq() *http.Request 44 GetQueryParm(name string) string 45 GetBoolQueryParm(name string) (bool, error) 46 GetResp() http.ResponseWriter 47 GetCertificates(cr.CertificateRequest, string) (*sqlx.Rows, error) 48 IsLDAPEnabled() bool 49 ReadBody(interface{}) error 50 ContainsAffiliation(string) error 51 CanActOnType(string) error 52 } 53 54 // serverRequestContextImpl represents an HTTP request/response context in the server 55 type serverRequestContextImpl struct { 56 req *http.Request 57 resp http.ResponseWriter 58 endpoint *serverEndpoint 59 ca *CA 60 enrollmentID string 61 enrollmentCert *x509.Certificate 62 ui user.User 63 caller user.User 64 body struct { 65 read bool // true after body is read 66 buf []byte // the body itself 67 err error // any error from reading the body 68 } 69 callerRoles map[string]bool 70 } 71 72 const ( 73 registrarRole = "hf.Registrar.Roles" 74 ) 75 76 // newServerRequestContext is the constructor for a serverRequestContextImpl 77 func newServerRequestContext(r *http.Request, w http.ResponseWriter, se *serverEndpoint) *serverRequestContextImpl { 78 return &serverRequestContextImpl{ 79 req: r, 80 resp: w, 81 endpoint: se, 82 } 83 } 84 85 // BasicAuthentication authenticates the caller's username and password 86 // found in the authorization header and returns the username 87 func (ctx *serverRequestContextImpl) BasicAuthentication() (string, error) { 88 r := ctx.req 89 // Get the authorization header 90 authHdr := r.Header.Get("authorization") 91 if authHdr == "" { 92 return "", caerrors.NewHTTPErr(401, caerrors.ErrNoAuthHdr, "No authorization header") 93 } 94 // Extract the username and password from the header 95 username, password, ok := r.BasicAuth() 96 if !ok { 97 return "", caerrors.NewAuthenticationErr(caerrors.ErrNoUserPass, "No user/pass in authorization header") 98 } 99 // Get the CA that is targeted by this request 100 ca, err := ctx.GetCA() 101 if err != nil { 102 return "", err 103 } 104 // Error if max enrollments is disabled for this CA 105 log.Debugf("ca.Config: %+v", ca.Config) 106 caMaxEnrollments := ca.Config.Registry.MaxEnrollments 107 if caMaxEnrollments == 0 { 108 return "", caerrors.NewAuthenticationErr(caerrors.ErrEnrollDisabled, "Enroll is disabled") 109 } 110 // Get the user info object for this user 111 ctx.ui, err = ca.registry.GetUser(username, nil) 112 if err != nil { 113 return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidUser, "Failed to get user: %s", err) 114 } 115 116 attempts := ctx.ui.GetFailedLoginAttempts() 117 allowedAttempts := ca.Config.Cfg.Identities.PasswordAttempts 118 if allowedAttempts > 0 { 119 if attempts == ca.Config.Cfg.Identities.PasswordAttempts { 120 msg := fmt.Sprintf("Incorrect password entered %d times, max incorrect password limit of %d reached", attempts, ca.Config.Cfg.Identities.PasswordAttempts) 121 log.Errorf(msg) 122 return "", caerrors.NewHTTPErr(401, caerrors.ErrPasswordAttempts, msg) 123 } 124 } 125 126 // Check the user's password and max enrollments if supported by registry 127 err = ctx.ui.Login(password, caMaxEnrollments) 128 if err != nil { 129 return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidPass, "Login failure: %s", err) 130 } 131 // Store the enrollment ID associated with this server request context 132 ctx.enrollmentID = username 133 ctx.caller, err = ctx.GetCaller() 134 if err != nil { 135 return "", err 136 } 137 // Return the username 138 return username, nil 139 } 140 141 // TokenAuthentication authenticates the caller by token 142 // in the authorization header. 143 // Returns the enrollment ID or error. 144 func (ctx *serverRequestContextImpl) TokenAuthentication() (string, error) { 145 r := ctx.req 146 // Get the authorization header 147 authHdr := r.Header.Get("authorization") 148 if authHdr == "" { 149 return "", caerrors.NewHTTPErr(401, caerrors.ErrNoAuthHdr, "No authorization header") 150 } 151 // Get the CA 152 ca, err := ctx.GetCA() 153 if err != nil { 154 return "", err 155 } 156 // Get the request body 157 body, err := ctx.ReadBodyBytes() 158 if err != nil { 159 return "", err 160 } 161 if idemix.IsToken(authHdr) { 162 return ctx.verifyIdemixToken(authHdr, r.Method, r.URL.RequestURI(), body) 163 } 164 return ctx.verifyX509Token(ca, authHdr, r.Method, r.URL.RequestURI(), body) 165 } 166 167 func (ctx *serverRequestContextImpl) verifyIdemixToken(authHdr, method, uri string, body []byte) (string, error) { 168 log.Debug("Caller is using Idemix credential") 169 var err error 170 171 ctx.enrollmentID, err = ctx.ca.issuer.VerifyToken(authHdr, method, uri, body) 172 if err != nil { 173 return "", err 174 } 175 176 caller, err := ctx.GetCaller() 177 if err != nil { 178 return "", err 179 } 180 181 if caller.IsRevoked() { 182 return "", caerrors.NewAuthorizationErr(caerrors.ErrRevokedID, "Enrollment ID is revoked, unable to process request") 183 } 184 185 return ctx.enrollmentID, nil 186 } 187 188 func (ctx *serverRequestContextImpl) verifyX509Token(ca *CA, authHdr, method, uri string, body []byte) (string, error) { 189 log.Debug("Caller is using a x509 certificate") 190 // Verify the token; the signature is over the header and body 191 cert, err2 := util.VerifyToken(ca.csp, authHdr, method, uri, body, ca.server.Config.CompMode1_3) 192 if err2 != nil { 193 return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidToken, "Invalid token in authorization header: %s", err2) 194 } 195 // Make sure the caller's cert was issued by this CA 196 err2 = ca.VerifyCertificate(cert) 197 if err2 != nil { 198 return "", caerrors.NewAuthenticationErr(caerrors.ErrUntrustedCertificate, "Untrusted certificate: %s", err2) 199 } 200 id := util.GetEnrollmentIDFromX509Certificate(cert) 201 log.Debugf("Checking for revocation/expiration of certificate owned by '%s'", id) 202 203 // VerifyCertificate ensures that the certificate passed in hasn't 204 // expired and checks the CRL for the server. 205 expired, checked := revoke.VerifyCertificate(cert) 206 if !checked { 207 return "", caerrors.NewHTTPErr(401, caerrors.ErrCertRevokeCheckFailure, "Failed while checking for revocation") 208 } 209 if expired { 210 return "", caerrors.NewAuthenticationErr(caerrors.ErrCertExpired, 211 "The certificate in the authorization header is a revoked or expired certificate") 212 } 213 aki := hex.EncodeToString(cert.AuthorityKeyId) 214 serial := util.GetSerialAsHex(cert.SerialNumber) 215 aki = strings.ToLower(strings.TrimLeft(aki, "0")) 216 serial = strings.ToLower(strings.TrimLeft(serial, "0")) 217 218 certificate, err := ca.GetCertificate(serial, aki) 219 if err != nil { 220 return "", err 221 } 222 if certificate.Status == "revoked" { 223 return "", caerrors.NewAuthenticationErr(caerrors.ErrCertRevoked, "The certificate in the authorization header is a revoked certificate") 224 } 225 226 ctx.enrollmentID = id 227 ctx.enrollmentCert = cert 228 ctx.caller, err = ctx.GetCaller() 229 if err != nil { 230 return "", err 231 } 232 log.Debugf("Successful token authentication of '%s'", id) 233 return id, nil 234 } 235 236 // GetECert returns the enrollment certificate of the caller, assuming 237 // token authentication was successful. 238 func (ctx *serverRequestContextImpl) GetECert() *x509.Certificate { 239 return ctx.enrollmentCert 240 } 241 242 // GetCA returns the CA to which this request is targeted and checks to make sure the database has been initialized 243 func (ctx *serverRequestContextImpl) GetCA() (*CA, error) { 244 _, err := ctx.getCA() 245 if err != nil { 246 return nil, errors.WithMessage(err, "Failed to get CA instance") 247 } 248 if ctx.ca.db == nil || !ctx.ca.db.IsInitialized() { 249 err := ctx.ca.initDB(ctx.ca.server.dbMetrics) 250 if err != nil { 251 return nil, errors.WithMessage(err, fmt.Sprintf("%s handler failed to initialize DB", strings.TrimLeft(ctx.req.URL.String(), "/"))) 252 } 253 err = ctx.ca.issuer.Init(false, ctx.ca.db, ctx.ca.levels) 254 if err != nil { 255 return nil, nil 256 } 257 } 258 return ctx.ca, nil 259 } 260 261 // GetCA returns the CA to which this request is targeted 262 func (ctx *serverRequestContextImpl) getCA() (*CA, error) { 263 if ctx.ca == nil { 264 // Get the CA name 265 name, err := ctx.getCAName() 266 if err != nil { 267 return nil, err 268 } 269 // Get the CA by its name 270 ctx.ca, err = ctx.endpoint.Server.GetCA(name) 271 if err != nil { 272 return nil, err 273 } 274 } 275 return ctx.ca, nil 276 } 277 278 // GetAttrExtension returns an attribute extension to place into a signing request 279 func (ctx *serverRequestContextImpl) GetAttrExtension(attrReqs []*api.AttributeRequest, profile string) (*signer.Extension, error) { 280 ca, err := ctx.GetCA() 281 if err != nil { 282 return nil, err 283 } 284 ui, err := ca.registry.GetUser(ctx.enrollmentID, nil) 285 if err != nil { 286 return nil, err 287 } 288 allAttrs, err := ui.GetAttributes(nil) 289 if err != nil { 290 return nil, err 291 } 292 if attrReqs == nil { 293 attrReqs = getDefaultAttrReqs(allAttrs) 294 if attrReqs == nil { 295 // No attributes are being requested, so we are done 296 return nil, nil 297 } 298 } 299 attrs, err := ca.attrMgr.ProcessAttributeRequests( 300 convertAttrReqs(attrReqs), 301 convertAttrs(allAttrs), 302 ) 303 if err != nil { 304 return nil, err 305 } 306 if attrs != nil { 307 buf, err := json.Marshal(attrs) 308 if err != nil { 309 errors.Wrap(err, "Failed to marshal attributes") 310 } 311 ext := &signer.Extension{ 312 ID: config.OID(attrmgr.AttrOID), 313 Critical: false, 314 Value: hex.EncodeToString(buf), 315 } 316 log.Debugf("Attribute extension being added to certificate is: %+v", ext) 317 return ext, nil 318 } 319 return nil, nil 320 } 321 322 // caNameReqBody is a sparse request body to unmarshal only the CA name 323 type caNameReqBody struct { 324 CAName string `json:"caname,omitempty"` 325 } 326 327 // getCAName returns the targeted CA name for this request 328 func (ctx *serverRequestContextImpl) getCAName() (string, error) { 329 // Check the query parameters first 330 ca := ctx.req.URL.Query().Get("ca") 331 if ca != "" { 332 return ca, nil 333 } 334 // Next, check the request body, if there is one 335 var body caNameReqBody 336 _, err := ctx.TryReadBody(&body) 337 if err != nil { 338 return "", err 339 } 340 if body.CAName != "" { 341 return body.CAName, nil 342 } 343 // No CA name in the request body either, so use the default CA name 344 return ctx.endpoint.Server.CA.Config.CA.Name, nil 345 } 346 347 // ReadBody reads the request body and JSON unmarshals into 'body' 348 func (ctx *serverRequestContextImpl) ReadBody(body interface{}) error { 349 empty, err := ctx.TryReadBody(body) 350 if err != nil { 351 return err 352 } 353 if empty { 354 return caerrors.NewHTTPErr(400, caerrors.ErrEmptyReqBody, "Empty request body") 355 } 356 return nil 357 } 358 359 // TryReadBody reads the request body into 'body' if not empty 360 func (ctx *serverRequestContextImpl) TryReadBody(body interface{}) (bool, error) { 361 buf, err := ctx.ReadBodyBytes() 362 if err != nil { 363 return false, err 364 } 365 empty := len(buf) == 0 366 if !empty { 367 err = json.Unmarshal(buf, body) 368 if err != nil { 369 return true, caerrors.NewHTTPErr(400, caerrors.ErrBadReqBody, "Invalid request body: %s; body=%s", 370 err, string(buf)) 371 } 372 } 373 return empty, nil 374 } 375 376 // ReadBodyBytes reads the request body and returns bytes 377 func (ctx *serverRequestContextImpl) ReadBodyBytes() ([]byte, error) { 378 if !ctx.body.read { 379 r := ctx.req 380 buf, err := ioutil.ReadAll(r.Body) 381 ctx.body.buf = buf 382 ctx.body.err = err 383 ctx.body.read = true 384 } 385 err := ctx.body.err 386 if err != nil { 387 return nil, caerrors.NewHTTPErr(500, caerrors.ErrReadingReqBody, "Failed reading request body: %s", err) 388 } 389 return ctx.body.buf, nil 390 } 391 392 func (ctx *serverRequestContextImpl) GetUser(userName string) (user.User, error) { 393 ca, err := ctx.getCA() 394 if err != nil { 395 return nil, err 396 } 397 registry := ca.registry 398 399 user, err := registry.GetUser(userName, nil) 400 if err != nil { 401 return nil, err 402 } 403 404 err = ctx.CanManageUser(user) 405 if err != nil { 406 return nil, err 407 } 408 409 return user, nil 410 } 411 412 // CanManageUser determines if the caller has the right type and affiliation to act on on a user 413 func (ctx *serverRequestContextImpl) CanManageUser(user user.User) error { 414 userAff := strings.Join(user.GetAffiliationPath(), ".") 415 err := ctx.ContainsAffiliation(userAff) 416 if err != nil { 417 return err 418 } 419 420 userType := user.GetType() 421 err = ctx.CanActOnType(userType) 422 if err != nil { 423 return err 424 } 425 426 return nil 427 } 428 429 // CanModifyUser determines if the modifications to the user are allowed 430 func (ctx *serverRequestContextImpl) CanModifyUser(req *api.ModifyIdentityRequest, checkAff bool, checkType bool, checkAttrs bool, userToModify user.User) error { 431 if checkAff { 432 reqAff := req.Affiliation 433 log.Debugf("Checking if caller is authorized to change affiliation to '%s'", reqAff) 434 err := ctx.ContainsAffiliation(reqAff) 435 if err != nil { 436 return err 437 } 438 } 439 440 if checkType { 441 reqType := req.Type 442 log.Debugf("Checking if caller is authorized to change type to '%s'", reqType) 443 err := ctx.CanActOnType(reqType) 444 if err != nil { 445 return err 446 } 447 } 448 449 if checkAttrs { 450 reqAttrs := req.Attributes 451 log.Debugf("Checking if caller is authorized to change attributes to %+v", reqAttrs) 452 err := attr.CanRegisterRequestedAttributes(reqAttrs, userToModify, ctx.caller) 453 if err != nil { 454 return caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "Failed to register attributes: %s", err) 455 } 456 } 457 458 return nil 459 } 460 461 // GetCaller gets the user who is making this server request 462 func (ctx *serverRequestContextImpl) GetCaller() (user.User, error) { 463 if ctx.caller != nil { 464 return ctx.caller, nil 465 } 466 467 var err error 468 id := ctx.enrollmentID 469 if id == "" { 470 return nil, caerrors.NewAuthenticationErr(caerrors.ErrCallerIsNotAuthenticated, "Caller is not authenticated") 471 } 472 ca, err := ctx.GetCA() 473 if err != nil { 474 return nil, err 475 } 476 // Get the user info object for this user 477 ctx.caller, err = ca.registry.GetUser(id, nil) 478 if err != nil { 479 return nil, caerrors.NewAuthenticationErr(caerrors.ErrGettingUser, "Failed to get user") 480 } 481 return ctx.caller, nil 482 } 483 484 // ContainsAffiliation returns an error if the requested affiliation does not contain the caller's affiliation 485 func (ctx *serverRequestContextImpl) ContainsAffiliation(affiliation string) error { 486 validAffiliation, err := ctx.containsAffiliation(affiliation) 487 if err != nil { 488 return errors.WithMessage(err, "Failed to validate if caller has authority to act on affiliation") 489 } 490 if !validAffiliation { 491 return caerrors.NewAuthorizationErr(caerrors.ErrCallerNotAffiliated, "Caller does not have authority to act on affiliation '%s'", affiliation) 492 } 493 return nil 494 } 495 496 // containsAffiliation returns true if the requested affiliation contains the caller's affiliation 497 func (ctx *serverRequestContextImpl) containsAffiliation(affiliation string) (bool, error) { 498 caller, err := ctx.GetCaller() 499 if err != nil { 500 return false, err 501 } 502 503 callerAffiliationPath := user.GetAffiliation(caller) 504 log.Debugf("Checking to see if affiliation '%s' contains caller's affiliation '%s'", affiliation, callerAffiliationPath) 505 506 // If the caller has root affiliation return "true" 507 if callerAffiliationPath == "" { 508 log.Debug("Caller has root affiliation") 509 return true, nil 510 } 511 512 if affiliation == callerAffiliationPath { 513 return true, nil 514 } 515 516 callerAffiliationPath = callerAffiliationPath + "." 517 if strings.HasPrefix(affiliation, callerAffiliationPath) { 518 return true, nil 519 } 520 521 return false, nil 522 } 523 524 // IsRegistrar returns an error if the caller is not a registrar 525 func (ctx *serverRequestContextImpl) IsRegistrar() error { 526 _, isRegistrar, err := ctx.isRegistrar() 527 if err != nil { 528 return err 529 } 530 if !isRegistrar { 531 return caerrors.NewAuthorizationErr(caerrors.ErrMissingRegAttr, "Caller is not a registrar") 532 } 533 534 return nil 535 } 536 537 // isRegistrar returns back true if the caller is a registrar along with the types the registrar is allowed to register 538 func (ctx *serverRequestContextImpl) isRegistrar() (string, bool, error) { 539 caller, err := ctx.GetCaller() 540 if err != nil { 541 return "", false, err 542 } 543 544 log.Debugf("Checking to see if caller '%s' is a registrar", caller.GetName()) 545 546 rolesStr, err := caller.GetAttribute("hf.Registrar.Roles") 547 if err != nil { 548 return "", false, caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "'%s' is not a registrar", caller.GetName()) 549 } 550 551 // Has some value for attribute 'hf.Registrar.Roles' then user is a registrar 552 if rolesStr.Value != "" { 553 return rolesStr.Value, true, nil 554 } 555 556 return "", false, nil 557 } 558 559 // CanActOnType returns true if the caller has the proper authority to take action on specific type 560 func (ctx *serverRequestContextImpl) CanActOnType(userType string) error { 561 canAct, err := ctx.canActOnType(userType) 562 if err != nil { 563 return errors.WithMessage(err, "Failed to verify if user can act on type") 564 } 565 if !canAct { 566 return caerrors.NewAuthorizationErr(caerrors.ErrCallerNotAffiliated, "Registrar does not have authority to act on type '%s'", userType) 567 } 568 return nil 569 } 570 571 func (ctx *serverRequestContextImpl) canActOnType(requestedType string) (bool, error) { 572 caller, err := ctx.GetCaller() 573 if err != nil { 574 return false, err 575 } 576 577 log.Debugf("Checking to see if caller '%s' can act on type '%s'", caller.GetName(), requestedType) 578 579 typesStr, isRegistrar, err := ctx.isRegistrar() 580 if err != nil { 581 return false, err 582 } 583 if !isRegistrar { 584 return false, caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "'%s' is not allowed to manage users", caller.GetName()) 585 } 586 587 if util.ListContains(typesStr, "*") { 588 return true, nil 589 } 590 591 var types []string 592 if typesStr != "" { 593 types = strings.Split(typesStr, ",") 594 } else { 595 types = make([]string, 0) 596 } 597 if requestedType == "" { 598 requestedType = "client" 599 } 600 if !util.StrContained(requestedType, types) { 601 log.Debugf("Caller with types '%s' is not authorized to act on '%s'", types, requestedType) 602 return false, nil 603 } 604 605 return true, nil 606 } 607 608 // HasRole returns an error if the caller does not have the attribute or the value is false for a boolean attribute 609 func (ctx *serverRequestContextImpl) HasRole(role string) error { 610 hasRole, err := ctx.hasRole(role) 611 if err != nil { 612 return err 613 } 614 if !hasRole { 615 return caerrors.NewAuthorizationErr(caerrors.ErrMissingRole, "Caller has a value of 'false' for attribute/role '%s'", role) 616 } 617 return nil 618 } 619 620 // HasRole returns true if the caller has the attribute and value of the attribute is true 621 func (ctx *serverRequestContextImpl) hasRole(role string) (bool, error) { 622 if ctx.callerRoles == nil { 623 ctx.callerRoles = make(map[string]bool) 624 } 625 626 roleStatus, hasRole := ctx.callerRoles[role] 627 if hasRole { 628 return roleStatus, nil 629 } 630 631 caller, err := ctx.GetCaller() 632 if err != nil { 633 return false, err 634 } 635 636 roleAttr, err := caller.GetAttribute(role) 637 if err != nil { 638 return false, caerrors.NewAuthorizationErr(caerrors.ErrInvokerMissAttr, "Invoker does not have following role'%s': '%s'", role, err) 639 } 640 roleStatus, err = strconv.ParseBool(roleAttr.Value) 641 if err != nil { 642 return false, caerrors.NewHTTPErr(400, caerrors.ErrInvalidBool, "Failed to get boolean value of '%s': '%s'", role, err) 643 } 644 ctx.callerRoles[role] = roleStatus 645 646 return ctx.callerRoles[role], nil 647 } 648 649 // GetVar returns the parameter path variable from the URL 650 func (ctx *serverRequestContextImpl) GetVar(name string) (string, error) { 651 vars := gmux.Vars(ctx.req) 652 if vars == nil { 653 return "", caerrors.NewHTTPErr(500, caerrors.ErrHTTPRequest, "Failed to correctly handle HTTP request") 654 } 655 value := vars[name] 656 return value, nil 657 } 658 659 // GetBoolQueryParm returns query parameter from the URL 660 func (ctx *serverRequestContextImpl) GetBoolQueryParm(name string) (bool, error) { 661 var err error 662 663 value := false 664 param := ctx.req.URL.Query().Get(name) 665 if param != "" { 666 value, err = strconv.ParseBool(strings.ToLower(param)) 667 if err != nil { 668 return false, caerrors.NewHTTPErr(400, caerrors.ErrUpdateConfigRemoveAff, "Failed to correctly parse value of '%s' query parameter: %s", name, err) 669 } 670 } 671 672 return value, nil 673 } 674 675 // GetQueryParm returns the value of query param based on name 676 func (ctx *serverRequestContextImpl) GetQueryParm(name string) string { 677 return ctx.req.URL.Query().Get(name) 678 } 679 680 // GetReq returns the http.Request 681 func (ctx *serverRequestContextImpl) GetReq() *http.Request { 682 return ctx.req 683 } 684 685 // GetResp returns the http.ResponseWriter 686 func (ctx *serverRequestContextImpl) GetResp() http.ResponseWriter { 687 return ctx.resp 688 } 689 690 // GetCertificates executes the DB query to get back certificates based on the filters passed in 691 func (ctx *serverRequestContextImpl) GetCertificates(req cr.CertificateRequest, callerAff string) (*sqlx.Rows, error) { 692 return ctx.ca.certDBAccessor.GetCertificates(req, callerAff) 693 } 694 695 // ChunksToDeliver returns the number of chunks to deliver per flush 696 func (ctx *serverRequestContextImpl) ChunksToDeliver(envVar string) (int, error) { 697 var chunkSize int 698 var err error 699 700 if envVar == "" { 701 chunkSize = 100 702 } else { 703 chunkSize, err = strconv.Atoi(envVar) 704 if err != nil { 705 return 0, caerrors.NewHTTPErr(500, caerrors.ErrParsingIntEnvVar, "Incorrect format specified for environment variable '%s', an integer value is required: %s", envVar, err) 706 } 707 } 708 return chunkSize, nil 709 } 710 711 // Registry returns the registry for the ca 712 func (ctx *serverRequestContextImpl) GetRegistry() user.Registry { 713 return ctx.ca.registry 714 } 715 716 func (ctx *serverRequestContextImpl) GetCAConfig() *CAConfig { 717 return ctx.ca.Config 718 } 719 720 func (ctx *serverRequestContextImpl) IsLDAPEnabled() bool { 721 return ctx.ca.Config.LDAP.Enabled 722 } 723 724 func convertAttrReqs(attrReqs []*api.AttributeRequest) []attrmgr.AttributeRequest { 725 rtn := make([]attrmgr.AttributeRequest, len(attrReqs)) 726 for i := range attrReqs { 727 rtn[i] = attrmgr.AttributeRequest(attrReqs[i]) 728 } 729 return rtn 730 } 731 732 func convertAttrs(attrs []api.Attribute) []attrmgr.Attribute { 733 rtn := make([]attrmgr.Attribute, len(attrs)) 734 for i := range attrs { 735 rtn[i] = attrmgr.Attribute(&attrs[i]) 736 } 737 return rtn 738 } 739 740 // Return attribute requests for attributes which should by default be added to an ECert 741 func getDefaultAttrReqs(attrs []api.Attribute) []*api.AttributeRequest { 742 count := 0 743 for _, attr := range attrs { 744 if attr.ECert { 745 count++ 746 } 747 } 748 if count == 0 { 749 return nil 750 } 751 reqs := make([]*api.AttributeRequest, count) 752 count = 0 753 for _, attr := range attrs { 754 if attr.ECert { 755 reqs[count] = &api.AttributeRequest{Name: attr.Name} 756 count++ 757 } 758 } 759 return reqs 760 }