github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/lib/ca.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 "bytes" 11 "encoding/pem" 12 "fmt" 13 "io/ioutil" 14 "os" 15 "path" 16 "path/filepath" 17 "strconv" 18 "sync" 19 "time" 20 21 "gitee.com/zhaochuninhefei/zcgolog/zclog" 22 "github.com/hxx258456/ccgo/sm2" 23 "github.com/hxx258456/ccgo/x509" 24 "github.com/hxx258456/cfssl-gm/certdb" 25 "github.com/hxx258456/cfssl-gm/config" 26 cfcsr "github.com/hxx258456/cfssl-gm/csr" 27 "github.com/hxx258456/cfssl-gm/initca" 28 "github.com/hxx258456/cfssl-gm/signer" 29 cflocalsigner "github.com/hxx258456/cfssl-gm/signer/local" 30 "github.com/hxx258456/fabric-ca-gm/internal/pkg/api" 31 "github.com/hxx258456/fabric-ca-gm/internal/pkg/util" 32 "github.com/hxx258456/fabric-ca-gm/lib/attr" 33 "github.com/hxx258456/fabric-ca-gm/lib/attrmgr" 34 "github.com/hxx258456/fabric-ca-gm/lib/caerrors" 35 "github.com/hxx258456/fabric-ca-gm/lib/metadata" 36 "github.com/hxx258456/fabric-ca-gm/lib/server/db" 37 cadbfactory "github.com/hxx258456/fabric-ca-gm/lib/server/db/factory" 38 "github.com/hxx258456/fabric-ca-gm/lib/server/db/mysql" 39 "github.com/hxx258456/fabric-ca-gm/lib/server/db/postgres" 40 "github.com/hxx258456/fabric-ca-gm/lib/server/db/sqlite" 41 dbutil "github.com/hxx258456/fabric-ca-gm/lib/server/db/util" 42 idemix "github.com/hxx258456/fabric-ca-gm/lib/server/idemix" 43 "github.com/hxx258456/fabric-ca-gm/lib/server/ldap" 44 cadbuser "github.com/hxx258456/fabric-ca-gm/lib/server/user" 45 "github.com/hxx258456/fabric-ca-gm/lib/tls" 46 "github.com/hxx258456/fabric-gm/bccsp" 47 "github.com/pkg/errors" 48 ) 49 50 const ( 51 defaultDatabaseType = "sqlite3" 52 // CAChainParentFirstEnvVar is the name of the environment variable that needs to be set 53 // for server to return CA chain in parent-first order 54 CAChainParentFirstEnvVar = "CA_CHAIN_PARENT_FIRST" 55 ) 56 57 var ( 58 // Default root CA certificate expiration is 15 years (in hours). 改为100年 59 // defaultRootCACertificateExpiration = "131400h" 60 defaultRootCACertificateExpiration = "876000h" 61 // Default intermediate CA certificate expiration is 5 years (in hours). 改为80年 62 // defaultIntermediateCACertificateExpiration = parseDuration("43800h") 63 defaultIntermediateCACertificateExpiration = parseDuration("700800h") 64 // Default issued certificate expiration is 1 year (in hours). 改为50年 65 // defaultIssuedCertificateExpiration = parseDuration("8760h") 66 defaultIssuedCertificateExpiration = parseDuration("438000h") 67 ) 68 69 // CA represents a certificate authority which signs, issues and revokes certificates 70 type CA struct { 71 // The home directory for the CA 72 HomeDir string 73 // The CA's configuration 74 Config *CAConfig 75 // The file path of the config file 76 ConfigFilePath string 77 // The database handle used to store certificates and optionally 78 // the user registry information, unless LDAP it enabled for the 79 // user registry function. 80 db db.FabricCADB 81 // The crypto service provider (BCCSP) 82 csp bccsp.BCCSP 83 // The certificate DB accessor 84 certDBAccessor *CertDBAccessor 85 // The user registry 86 registry cadbuser.Registry 87 // The signer used for enrollment 88 enrollSigner signer.Signer 89 // Idemix issuer 90 issuer idemix.Issuer 91 // The options to use in verifying a signature in token-based authentication 92 verifyOptions *x509.VerifyOptions 93 // The attribute manager 94 attrMgr *attrmgr.Mgr 95 // The server hosting this CA 96 server *Server 97 // DB levels 98 levels *dbutil.Levels 99 // CA mutex 100 mutex sync.Mutex 101 } 102 103 const ( 104 certificateError = "Invalid certificate in file" 105 ) 106 107 // newCA creates a new CA with the specified 108 // home directory, parent server URL, and config 109 func newCA(caFile string, config *CAConfig, server *Server, renew bool) (*CA, error) { 110 ca := new(CA) 111 ca.ConfigFilePath = caFile 112 err := initCA(ca, filepath.Dir(caFile), config, server, renew) 113 if err != nil { 114 err2 := ca.closeDB() 115 if err2 != nil { 116 zclog.Errorf("Close DB failed: %s", err2) 117 } 118 return nil, err 119 } 120 return ca, nil 121 } 122 123 // initCA will initialize the passed in pointer to a CA struct 124 func initCA(ca *CA, homeDir string, config *CAConfig, server *Server, renew bool) error { 125 ca.HomeDir = homeDir 126 ca.Config = config 127 ca.server = server 128 129 err := ca.init(renew) 130 if err != nil { 131 return err 132 } 133 zclog.Debug("Initializing Idemix issuer...") 134 ca.issuer = idemix.NewIssuer(ca.Config.CA.Name, ca.HomeDir, 135 &ca.Config.Idemix, ca.csp, idemix.NewLib()) 136 err = ca.issuer.Init(renew, ca.db, ca.levels) 137 if err != nil { 138 return errors.WithMessage(err, fmt.Sprintf("Failed to initialize Idemix issuer for CA '%s'", err.Error())) 139 } 140 return nil 141 } 142 143 // Init initializes an instance of a CA 144 func (ca *CA) init(renew bool) (err error) { 145 zclog.Debugf("Init CA with home %s and config %+v", ca.HomeDir, *ca.Config) 146 147 // Initialize the config, setting defaults, etc 148 // zclog.Info("===== ca.Config.CSP.ProviderName = ", ca.Config.CSP.ProviderName) 149 SetProviderName(ca.Config.CSP.ProviderName) 150 err = ca.initConfig() 151 if err != nil { 152 return err 153 } 154 155 // Initialize the crypto layer (BCCSP) for this CA 156 ca.csp, err = util.InitBCCSP(&ca.Config.CSP, "", ca.HomeDir) 157 if err != nil { 158 return err 159 } 160 161 // Initialize key materials 162 err = ca.initKeyMaterial(renew) 163 if err != nil { 164 return err 165 } 166 167 // Initialize the database 168 err = ca.initDB(ca.server.dbMetrics) 169 if err != nil { 170 zclog.Error("Error occurred initializing database: ", err) 171 // Return if a server configuration error encountered (e.g. Invalid max enrollment for a bootstrap user) 172 if caerrors.IsFatalError(err) { 173 return err 174 } 175 } 176 // Initialize the enrollment signer 177 err = ca.initEnrollmentSigner() 178 if err != nil { 179 return err 180 } 181 // Create the attribute manager 182 ca.attrMgr = attrmgr.New() 183 zclog.Debug("CA initialization successful") 184 // Successful initialization 185 return nil 186 } 187 188 // Initialize the CA's key material 189 // 初始化 CA 的密钥材料 190 func (ca *CA) initKeyMaterial(renew bool) error { 191 zclog.Debug("===== Initialize key material") 192 193 // Make the path names absolute in the config 194 err := ca.makeFileNamesAbsolute() 195 if err != nil { 196 return err 197 } 198 199 keyFile := ca.Config.CA.Keyfile 200 certFile := ca.Config.CA.Certfile 201 202 // If we aren't renewing and the key and cert files exist, do nothing 203 if !renew { 204 // If they both exist, the CA was already initialized 205 keyFileExists := util.FileExists(keyFile) 206 certFileExists := util.FileExists(certFile) 207 if keyFileExists && certFileExists { 208 zclog.Info("The CA key and certificate files already exist") 209 zclog.Infof("Key file location: %s", keyFile) 210 zclog.Infof("Certificate file location: %s", certFile) 211 err = ca.validateCertAndKey(certFile, keyFile) 212 if err != nil { 213 return errors.WithMessage(err, "Validation of certificate and key failed") 214 } 215 // Load CN from existing enrollment information and set CSR accordingly 216 // CN needs to be set, having a multi CA setup requires a unique CN and can't 217 // be left blank 218 ca.Config.CSR.CN, err = ca.loadCNFromEnrollmentInfo(certFile) 219 if err != nil { 220 return err 221 } 222 return nil 223 } 224 225 // If key file does not exist but certFile does, key file is probably 226 // stored by BCCSP, so check for that now. 227 if certFileExists { 228 _, _, _, err = util.GetSignerFromCertFile(certFile, ca.csp) 229 if err != nil { 230 return errors.WithMessage(err, fmt.Sprintf("Failed to find private key for certificate in '%s'", certFile)) 231 } 232 // Yes, it is stored by BCCSP 233 zclog.Info("The CA key and certificate already exist") 234 zclog.Infof("The key is stored by BCCSP provider '%s'", ca.Config.CSP.ProviderName) 235 zclog.Infof("The certificate is at: %s", certFile) 236 // Load CN from existing enrollment information and set CSR accordingly 237 // CN needs to be set, having a multi CA setup requires a unique CN and can't 238 // be left blank 239 ca.Config.CSR.CN, err = ca.loadCNFromEnrollmentInfo(certFile) 240 if err != nil { 241 return errors.WithMessage(err, fmt.Sprintf("Failed to get CN for certificate in '%s'", certFile)) 242 } 243 return nil 244 } 245 zclog.Warn(caerrors.NewServerError(caerrors.ErrCACertFileNotFound, "The specified CA certificate file %s does not exist", certFile)) 246 } 247 248 // 获取CA根证书 249 cert, err := ca.getCACert() 250 if err != nil { 251 return err 252 } 253 // Store the certificate to file 254 err = writeFile(certFile, cert, 0644) 255 if err != nil { 256 return errors.Wrap(err, "Failed to store certificate") 257 } 258 zclog.Infof("===== The CA key and certificate were generated for CA %s", ca.Config.CA.Name) 259 zclog.Infof("===== The key was stored by BCCSP provider '%s'", ca.Config.CSP.ProviderName) 260 zclog.Infof("===== The certificate is at: %s", certFile) 261 262 return nil 263 } 264 265 // Get the CA certificate for this CA 266 func (ca *CA) getCACert() (cert []byte, err error) { 267 if ca.Config.Intermediate.ParentServer.URL != "" { 268 // This is an intermediate CA, so call the parent fabric-ca-server 269 // to get the cert 270 zclog.Debugf("===== CA配置有父证书 parent server URL is %s", util.GetMaskedURL(ca.Config.Intermediate.ParentServer.URL)) 271 clientCfg := ca.Config.Client 272 if clientCfg == nil { 273 clientCfg = &ClientConfig{} 274 } 275 // Copy over the intermediate configuration into client configuration 276 clientCfg.TLS = ca.Config.Intermediate.TLS 277 clientCfg.Enrollment = ca.Config.Intermediate.Enrollment 278 clientCfg.CAName = ca.Config.Intermediate.ParentServer.CAName 279 clientCfg.CSP = ca.Config.CSP 280 clientCfg.CSR = ca.Config.CSR 281 clientCfg.CSP = ca.Config.CSP 282 if ca.Config.CSR.CN != "" { 283 return nil, errors.Errorf("CN '%s' cannot be specified for an intermediate CA. Remove CN from CSR section for enrollment of intermediate CA to be successful", ca.Config.CSR.CN) 284 } 285 if clientCfg.Enrollment.Profile == "" { 286 clientCfg.Enrollment.Profile = "ca" 287 } 288 if clientCfg.Enrollment.CSR == nil { 289 clientCfg.Enrollment.CSR = &api.CSRInfo{} 290 } 291 if clientCfg.Enrollment.CSR.CA == nil { 292 clientCfg.Enrollment.CSR.CA = &cfcsr.CAConfig{PathLength: 0, PathLenZero: true} 293 } 294 zclog.Debugf("Intermediate enrollment request: %+v, CSR: %+v, CA: %+v", 295 clientCfg.Enrollment, clientCfg.Enrollment.CSR, clientCfg.Enrollment.CSR.CA) 296 var resp *EnrollmentResponse 297 resp, err = clientCfg.Enroll(ca.Config.Intermediate.ParentServer.URL, ca.HomeDir) 298 if err != nil { 299 return nil, err 300 } 301 // Set the CN for an intermediate server to be the ID used to enroll with root CA 302 ca.Config.CSR.CN = resp.Identity.GetName() 303 ecert := resp.Identity.GetECert() 304 if ecert == nil { 305 return nil, errors.New("No enrollment certificate returned by parent server") 306 } 307 cert = ecert.Cert() 308 // Store the chain file as the concatenation of the parent's chain plus the cert. 309 chainPath := ca.Config.CA.Chainfile 310 chain, err := ca.concatChain(resp.CAInfo.CAChain, cert) 311 if err != nil { 312 return nil, err 313 } 314 err = os.MkdirAll(path.Dir(chainPath), 0755) 315 if err != nil { 316 return nil, errors.Wrap(err, "Failed to create intermediate chain file directory") 317 } 318 err = util.WriteFile(chainPath, chain, 0644) 319 if err != nil { 320 return nil, errors.WithMessage(err, "Failed to create intermediate chain file") 321 } 322 zclog.Debugf("Stored intermediate certificate chain at %s", chainPath) 323 } else { 324 zclog.Debug("===== CA没有配置父证书 需要生成自签名的CA根证书") 325 // This is a root CA, so create a CSR (Certificate Signing Request) 326 if ca.Config.CSR.CN == "" { 327 ca.Config.CSR.CN = "fabric-ca-server" 328 } 329 csr := &ca.Config.CSR 330 if csr.CA == nil { 331 csr.CA = &cfcsr.CAConfig{} 332 } 333 if csr.CA.Expiry == "" { 334 csr.CA.Expiry = defaultRootCACertificateExpiration 335 } 336 337 if (csr.KeyRequest == nil) || (csr.KeyRequest.Algo == "" && csr.KeyRequest.Size == 0) { 338 // TODO 目前强制使用国密 339 // if IsGMConfig() { 340 // csr.KeyRequest = GetGMKeyRequest(ca.Config) 341 // } else { 342 // csr.KeyRequest = GetKeyRequest(ca.Config) 343 // } 344 csr.KeyRequest = GetGMKeyRequest(ca.Config) 345 } 346 req := cfcsr.CertificateRequest{ 347 CN: csr.CN, 348 Names: csr.Names, 349 Hosts: csr.Hosts, 350 KeyRequest: &cfcsr.KeyRequest{A: csr.KeyRequest.Algo, S: csr.KeyRequest.Size}, 351 CA: csr.CA, 352 SerialNumber: csr.SerialNumber, 353 } 354 zclog.Debugf("Root CA certificate request: %+v", req) 355 // Generate the key/signer 356 _, cspSigner, err := util.BCCSPKeyRequestGenerate(&req, ca.csp) 357 if err != nil { 358 return nil, err 359 } 360 // 生成自签名的CA根证书 361 cert, _, err = initca.NewFromSigner(&req, cspSigner) 362 if err != nil { 363 return nil, errors.WithMessage(err, "Failed to create new CA certificate") 364 } 365 } 366 return cert, nil 367 } 368 369 // Return a certificate chain which is the concatenation of chain and cert 370 func (ca *CA) concatChain(chain []byte, cert []byte) ([]byte, error) { 371 result := make([]byte, len(chain)+len(cert)) 372 parentFirst, ok := os.LookupEnv(CAChainParentFirstEnvVar) 373 parentFirstBool := false 374 // If CA_CHAIN_PARENT_FIRST env variable is set then get the boolean 375 // value 376 if ok { 377 var err error 378 parentFirstBool, err = strconv.ParseBool(parentFirst) 379 if err != nil { 380 return nil, errors.Wrapf(err, "failed to parse the environment variable '%s'", CAChainParentFirstEnvVar) 381 } 382 } 383 if parentFirstBool { 384 copy(result[:len(chain)], chain) 385 copy(result[len(chain):], cert) 386 } else { 387 copy(result[:len(cert)], cert) 388 copy(result[len(cert):], chain) 389 } 390 return result, nil 391 } 392 393 // Get the certificate chain for the CA 394 func (ca *CA) getCAChain() (chain []byte, err error) { 395 if ca.Config == nil { 396 return nil, errors.New("The server has no configuration") 397 } 398 certAuth := &ca.Config.CA 399 // If the chain file exists, we always return the chain from here 400 if util.FileExists(certAuth.Chainfile) { 401 return util.ReadFile(certAuth.Chainfile) 402 } 403 // Otherwise, if this is a root CA, we always return the contents of the CACertfile 404 if ca.Config.Intermediate.ParentServer.URL == "" { 405 return util.ReadFile(certAuth.Certfile) 406 } 407 // If this is an intermediate CA but the ca.Chainfile doesn't exist, 408 // it is an error. It should have been created during intermediate CA enrollment. 409 return nil, errors.Errorf("Chain file does not exist at %s", certAuth.Chainfile) 410 } 411 412 // Initialize the configuration for the CA setting any defaults and making filenames absolute 413 func (ca *CA) initConfig() (err error) { 414 // Init home directory if not set 415 if ca.HomeDir == "" { 416 ca.HomeDir, err = os.Getwd() 417 if err != nil { 418 return errors.Wrap(err, "Failed to initialize CA's home directory") 419 } 420 } 421 zclog.Debugf("CA Home Directory: %s", ca.HomeDir) 422 // Init config if not set 423 if ca.Config == nil { 424 ca.Config = new(CAConfig) 425 ca.Config.Registry.MaxEnrollments = -1 426 } 427 // Set config defaults 428 cfg := ca.Config 429 if cfg.Version == "" { 430 cfg.Version = "0" 431 } 432 if cfg.CA.Certfile == "" { 433 cfg.CA.Certfile = "ca-cert.pem" 434 } 435 if cfg.CA.Keyfile == "" { 436 cfg.CA.Keyfile = "ca-key.pem" 437 } 438 if cfg.CA.Chainfile == "" { 439 cfg.CA.Chainfile = "ca-chain.pem" 440 } 441 if cfg.CSR.CA == nil { 442 cfg.CSR.CA = &cfcsr.CAConfig{} 443 } 444 if cfg.CSR.CA.Expiry == "" { 445 cfg.CSR.CA.Expiry = defaultRootCACertificateExpiration 446 } 447 if cfg.Signing == nil { 448 cfg.Signing = &config.Signing{} 449 } 450 cs := cfg.Signing 451 if cs.Profiles == nil { 452 cs.Profiles = make(map[string]*config.SigningProfile) 453 } 454 caProfile := cs.Profiles["ca"] 455 initSigningProfile(&caProfile, 456 defaultIntermediateCACertificateExpiration, 457 true) 458 cs.Profiles["ca"] = caProfile 459 initSigningProfile( 460 &cs.Default, 461 defaultIssuedCertificateExpiration, 462 false) 463 tlsProfile := cs.Profiles["tls"] 464 initSigningProfile(&tlsProfile, 465 defaultIssuedCertificateExpiration, 466 false) 467 cs.Profiles["tls"] = tlsProfile 468 err = ca.checkConfigLevels() 469 if err != nil { 470 return err 471 } 472 // Set log level if debug is true 473 // if ca.server != nil && ca.server.Config != nil && ca.server.Config.Debug { 474 // log.Level = log.LevelDebug 475 // } 476 ca.normalizeStringSlices() 477 478 return nil 479 } 480 481 // 获取国密证书的检查配置 482 func getVerifyOptions(ca *CA) (*x509.VerifyOptions, error) { 483 chain, err := ca.getCAChain() 484 if err != nil { 485 return nil, err 486 } 487 block, rest := pem.Decode(chain) 488 if block == nil { 489 return nil, errors.New("No root certificate was found") 490 } 491 rootCert, err := x509.ParseCertificate(block.Bytes) 492 if err != nil { 493 return nil, errors.Errorf("Failed to parse root certificate: %s", err) 494 } 495 rootPool := x509.NewCertPool() 496 rootPool.AddCert(rootCert) 497 var intPool *x509.CertPool 498 if len(rest) > 0 { 499 intPool = x509.NewCertPool() 500 if !intPool.AppendCertsFromPEM(rest) { 501 return nil, errors.New("Failed to add intermediate PEM certificates") 502 } 503 } 504 return &x509.VerifyOptions{ 505 Roots: rootPool, 506 Intermediates: intPool, 507 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, 508 }, nil 509 } 510 511 // 检查目标证书cert是否是由ca签署的。 512 // VerifyCertificate verifies that 'cert' was issued by this CA 513 // Return nil if successful; otherwise, return an error. 514 // 'forceTime' if false, certificate expiry times will be checked based 515 // on the current time. 516 // if true, it will force the time to be used to check for expiry to be 30 seconds 517 // after the certificate start time. (this is to support reenrollIgnoreCertExpiry) 518 func (ca *CA) VerifyCertificate(cert *x509.Certificate, forceTime bool) error { 519 // zclog.Debugf("===== Certicate Dates: NotAfter = %s NotBefore = %s \n", cert.NotAfter.Format(time.RFC3339), cert.NotBefore.Format(time.RFC3339)) 520 // 从CA配置获取检查参数 521 opts, err := getVerifyOptions(ca) 522 // opts, err := ca.getVerifyOptions() 523 if err != nil { 524 return errors.WithMessage(err, "Failed to get verify options") 525 } 526 // force check time to be 30 seconds after certificate start time to ensure expiry doesn't get flagged 527 // this is one of the checks that is made on the certificate in Verify() 528 if forceTime { 529 opts.CurrentTime = cert.NotBefore.Add(time.Duration(time.Second * 30)) 530 } 531 // 尝试从ca的根证书构建cert的信任链,成功则说明cert是由ca直接或间接签署的。 532 // 目前应该都是直接签署的。即证书信任链长度只有2。 533 _, err = cert.Verify(*opts) 534 if err != nil { 535 return errors.WithMessage(err, "Failed to verify certificate") 536 } 537 return nil 538 } 539 540 // Get the options to verify 541 func (ca *CA) getVerifyOptions() (*x509.VerifyOptions, error) { 542 if ca.verifyOptions != nil { 543 return ca.verifyOptions, nil 544 } 545 chain, err := ca.getCAChain() 546 if err != nil { 547 return nil, err 548 } 549 var intPool *x509.CertPool 550 var rootPool *x509.CertPool 551 552 for len(chain) > 0 { 553 var block *pem.Block 554 block, chain = pem.Decode(chain) 555 if block == nil { 556 break 557 } 558 if block.Type != "CERTIFICATE" { 559 continue 560 } 561 562 cert, err := x509.ParseCertificate(block.Bytes) 563 if err != nil { 564 return nil, errors.Wrap(err, "Failed to parse CA chain certificate") 565 } 566 567 if !cert.IsCA { 568 return nil, errors.New("A certificate in the CA chain is not a CA certificate") 569 } 570 571 // If authority key id is not present or if it is present and equal to subject key id, 572 // then it is a root certificate 573 if len(cert.AuthorityKeyId) == 0 || bytes.Equal(cert.AuthorityKeyId, cert.SubjectKeyId) { 574 if rootPool == nil { 575 rootPool = x509.NewCertPool() 576 } 577 rootPool.AddCert(cert) 578 } else { 579 if intPool == nil { 580 intPool = x509.NewCertPool() 581 } 582 intPool.AddCert(cert) 583 } 584 } 585 586 ca.verifyOptions = &x509.VerifyOptions{ 587 Roots: rootPool, 588 Intermediates: intPool, 589 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, 590 } 591 return ca.verifyOptions, nil 592 } 593 594 // Initialize the database for the CA 595 func (ca *CA) initDB(metrics *db.Metrics) error { 596 zclog.Debug("Initializing DB") 597 598 // If DB is initialized, don't need to proceed further 599 if ca.db != nil && ca.db.IsInitialized() { 600 return nil 601 } 602 603 ca.mutex.Lock() 604 defer ca.mutex.Unlock() 605 606 // After obtaining a lock, check again to see if DB got initialized by another process 607 if ca.db != nil && ca.db.IsInitialized() { 608 return nil 609 } 610 611 dbCfg := &ca.Config.DB 612 dbError := false 613 var err error 614 615 if dbCfg.Type == "" || dbCfg.Type == defaultDatabaseType { 616 617 dbCfg.Type = defaultDatabaseType 618 619 if dbCfg.Datasource == "" { 620 dbCfg.Datasource = "fabric-ca-server.db" 621 } 622 623 dbCfg.Datasource, err = util.MakeFileAbs(dbCfg.Datasource, ca.HomeDir) 624 if err != nil { 625 return err 626 } 627 } 628 629 // Strip out user:pass from datasource for logging 630 ds := dbCfg.Datasource 631 ds = dbutil.MaskDBCred(ds) 632 633 zclog.Debugf("Initializing '%s' database at '%s'", dbCfg.Type, ds) 634 caDB, err := cadbfactory.New( 635 dbCfg.Type, 636 dbCfg.Datasource, 637 ca.Config.CA.Name, 638 &dbCfg.TLS, 639 ca.csp, 640 metrics, 641 ) 642 if err != nil { 643 return err 644 } 645 err = caDB.Connect() 646 if err != nil { 647 return err 648 } 649 sqlxdb, err := caDB.Create() 650 if err != nil { 651 return err 652 } 653 654 sqlxdb.Metrics = metrics 655 656 ca.db = sqlxdb 657 // Set the certificate DB accessor 658 ca.certDBAccessor = NewCertDBAccessor(ca.db, ca.levels.Certificate) 659 660 // If DB initialization fails and we need to reinitialize DB, need to make sure to set the DB accessor for the signer 661 if ca.enrollSigner != nil { 662 ca.enrollSigner.SetDBAccessor(ca.certDBAccessor) 663 } 664 665 // Initialize user registry to either use DB or LDAP 666 err = ca.initUserRegistry() 667 if err != nil { 668 return err 669 } 670 671 err = ca.checkDBLevels() 672 if err != nil { 673 return err 674 } 675 676 // Migrate the database 677 curLevels, err := db.CurrentDBLevels(ca.db) 678 if err != nil { 679 return errors.Wrap(err, "Failed to current ca levels") 680 } 681 migrator, err := getMigrator(ca.db.DriverName(), ca.db.BeginTx(), curLevels, ca.server.levels) 682 if err != nil { 683 return errors.Wrap(err, "Failed to get migrator") 684 } 685 err = db.Migrate(migrator, curLevels, ca.server.levels) 686 if err != nil { 687 return errors.Wrap(err, "Failed to migrate database") 688 } 689 690 // If not using LDAP, migrate database if needed to latest version and load the users and affiliations table 691 if !ca.Config.LDAP.Enabled { 692 err = ca.loadUsersTable() 693 if err != nil { 694 zclog.Error(err) 695 dbError = true 696 if caerrors.IsFatalError(err) { 697 return err 698 } 699 } 700 701 err = ca.loadAffiliationsTable() 702 if err != nil { 703 zclog.Error(err) 704 dbError = true 705 } 706 } 707 708 if dbError { 709 return errors.Errorf("Failed to initialize %s database at %s ", dbCfg.Type, ds) 710 } 711 712 ca.db.SetDBInitialized(true) 713 zclog.Infof("Initialized %s database at %s", dbCfg.Type, ds) 714 715 return nil 716 } 717 718 // Close CA's DB 719 func (ca *CA) closeDB() error { 720 if ca.db != nil { 721 err := ca.db.Close() 722 ca.db = nil 723 if err != nil { 724 return errors.Wrapf(err, "Failed to close CA database, where CA home directory is '%s'", ca.HomeDir) 725 } 726 } 727 return nil 728 } 729 730 // Initialize the user registry interface 731 func (ca *CA) initUserRegistry() error { 732 zclog.Debug("Initializing identity registry") 733 var err error 734 ldapCfg := &ca.Config.LDAP 735 736 if ldapCfg.Enabled { 737 // Use LDAP for the user registry 738 ca.registry, err = ldap.NewClient(ldapCfg, ca.server.csp) 739 zclog.Debugf("Initialized LDAP identity registry; err=%s", err) 740 if err == nil { 741 zclog.Info("Successfully initialized LDAP client") 742 } else { 743 zclog.Warnf("Failed to initialize LDAP client; err=%s", err) 744 } 745 return err 746 } 747 748 // Use the DB for the user registry 749 ca.registry = NewDBAccessor(ca.db) 750 zclog.Debug("Initialized DB identity registry") 751 return nil 752 } 753 754 // Initialize the enrollment signer 755 func (ca *CA) initEnrollmentSigner() (err error) { 756 zclog.Debug("Initializing enrollment signer") 757 c := ca.Config 758 759 // If there is a config, use its signing policy. Otherwise create a default policy. 760 var policy *config.Signing 761 if c.Signing != nil { 762 policy = c.Signing 763 } else { 764 policy = &config.Signing{ 765 Profiles: map[string]*config.SigningProfile{}, 766 Default: config.DefaultConfig(), 767 } 768 policy.Default.CAConstraint.IsCA = true 769 } 770 771 // Make sure the policy reflects the new remote 772 parentServerURL := ca.Config.Intermediate.ParentServer.URL 773 if parentServerURL != "" { 774 err = policy.OverrideRemotes(parentServerURL) 775 if err != nil { 776 return errors.Wrap(err, "Failed initializing enrollment signer") 777 } 778 } 779 780 ca.enrollSigner, err = util.BccspBackedSigner(c.CA.Certfile, c.CA.Keyfile, policy, ca.csp) 781 if err != nil { 782 return err 783 } 784 ca.enrollSigner.SetDBAccessor(ca.certDBAccessor) 785 786 // Successful enrollment 787 return nil 788 } 789 790 // loadUsersTable adds the configured users to the table if not already found 791 func (ca *CA) loadUsersTable() error { 792 zclog.Debug("Loading identity table") 793 registry := &ca.Config.Registry 794 for _, id := range registry.Identities { 795 zclog.Debugf("Loading identity '%s'", id.Name) 796 err := ca.addIdentity(&id, false) 797 if err != nil { 798 return errors.WithMessage(err, "Failed to load identity table") 799 } 800 } 801 zclog.Debug("Successfully loaded identity table") 802 return nil 803 } 804 805 // loadAffiliationsTable adds the configured affiliations to the table 806 func (ca *CA) loadAffiliationsTable() error { 807 zclog.Debug("Loading affiliations table") 808 err := ca.loadAffiliationsTableR(ca.Config.Affiliations, "") 809 if err != nil { 810 return errors.WithMessage(err, "Failed to load affiliations table") 811 } 812 zclog.Debug("Successfully loaded affiliations table") 813 return nil 814 } 815 816 // Recursive function to load the affiliations table hierarchy 817 func (ca *CA) loadAffiliationsTableR(val interface{}, parentPath string) (err error) { 818 var path string 819 if val == nil { 820 return nil 821 } 822 switch val := val.(type) { 823 case string: 824 path = affiliationPath(val, parentPath) 825 err = ca.addAffiliation(path, parentPath) 826 if err != nil { 827 return err 828 } 829 case []string: 830 for _, ele := range val { 831 err = ca.loadAffiliationsTableR(ele, parentPath) 832 if err != nil { 833 return err 834 } 835 } 836 case []interface{}: 837 for _, ele := range val { 838 err = ca.loadAffiliationsTableR(ele, parentPath) 839 if err != nil { 840 return err 841 } 842 } 843 default: 844 for name, ele := range val.(map[string]interface{}) { 845 path = affiliationPath(name, parentPath) 846 err = ca.addAffiliation(path, parentPath) 847 if err != nil { 848 return err 849 } 850 err = ca.loadAffiliationsTableR(ele, path) 851 if err != nil { 852 return err 853 } 854 } 855 } 856 return nil 857 } 858 859 // Add an identity to the registry 860 func (ca *CA) addIdentity(id *CAConfigIdentity, errIfFound bool) error { 861 var err error 862 user, _ := ca.registry.GetUser(id.Name, nil) 863 if user != nil { 864 if errIfFound { 865 return errors.Errorf("Identity '%s' is already registered", id.Name) 866 } 867 zclog.Debugf("Identity '%s' already registered, loaded identity", user.GetName()) 868 return nil 869 } 870 871 id.MaxEnrollments, err = getMaxEnrollments(id.MaxEnrollments, ca.Config.Registry.MaxEnrollments) 872 if err != nil { 873 return caerrors.NewFatalError(caerrors.ErrConfig, "Configuration Error: %s", err) 874 } 875 876 attrs, err := attr.ConvertAttrs(id.Attrs) 877 878 if err != nil { 879 return err 880 } 881 882 rec := cadbuser.Info{ 883 Name: id.Name, 884 Pass: id.Pass, 885 Type: id.Type, 886 Affiliation: id.Affiliation, 887 Attributes: attrs, 888 MaxEnrollments: id.MaxEnrollments, 889 Level: ca.levels.Identity, 890 } 891 err = ca.registry.InsertUser(&rec) 892 if err != nil { 893 return errors.WithMessage(err, fmt.Sprintf("Failed to insert identity '%s'", id.Name)) 894 } 895 zclog.Debugf("Registered identity: %+v", id) 896 return nil 897 } 898 899 func (ca *CA) addAffiliation(path, parentPath string) error { 900 return ca.registry.InsertAffiliation(path, parentPath, ca.levels.Affiliation) 901 } 902 903 // CertDBAccessor returns the certificate DB accessor for CA 904 func (ca *CA) CertDBAccessor() *CertDBAccessor { 905 return ca.certDBAccessor 906 } 907 908 // DBAccessor returns the registry DB accessor for server 909 func (ca *CA) DBAccessor() cadbuser.Registry { 910 return ca.registry 911 } 912 913 // GetDB returns pointer to database 914 func (ca *CA) GetDB() db.FabricCADB { 915 return ca.db 916 } 917 918 // GetCertificate returns a single certificate matching serial and aki, if multiple certificates 919 // found for serial and aki an error is returned 920 func (ca *CA) GetCertificate(serial, aki string) (*certdb.CertificateRecord, error) { 921 certs, err := ca.CertDBAccessor().GetCertificate(serial, aki) 922 if err != nil { 923 return nil, err 924 } 925 if len(certs) == 0 { 926 return nil, caerrors.NewAuthenticationErr(caerrors.ErrCertNotFound, "Certificate not found with AKI '%s' and serial '%s'", aki, serial) 927 } 928 if len(certs) > 1 { 929 return nil, caerrors.NewAuthenticationErr(caerrors.ErrCertNotFound, "Multiple certificates found, when only should exist with AKI '%s' and serial '%s' combination", aki, serial) 930 } 931 return &certs[0], nil 932 } 933 934 // Make all file names in the CA config absolute 935 func (ca *CA) makeFileNamesAbsolute() error { 936 zclog.Debug("Making CA filenames absolute") 937 938 fields := []*string{ 939 &ca.Config.CA.Certfile, 940 &ca.Config.CA.Keyfile, 941 &ca.Config.CA.Chainfile, 942 } 943 err := util.MakeFileNamesAbsolute(fields, ca.HomeDir) 944 if err != nil { 945 return err 946 } 947 err = tls.AbsTLSClient(&ca.Config.DB.TLS, ca.HomeDir) 948 if err != nil { 949 return err 950 } 951 err = tls.AbsTLSClient(&ca.Config.LDAP.TLS, ca.HomeDir) 952 if err != nil { 953 return err 954 } 955 return nil 956 } 957 958 // Convert all comma separated strings to string arrays 959 func (ca *CA) normalizeStringSlices() { 960 fields := []*[]string{ 961 &ca.Config.CSR.Hosts, 962 &ca.Config.DB.TLS.CertFiles, 963 &ca.Config.LDAP.TLS.CertFiles, 964 } 965 for _, namePtr := range fields { 966 norm := util.NormalizeStringSlice(*namePtr) 967 *namePtr = norm 968 } 969 } 970 971 // userHasAttribute returns nil error and the value of the attribute 972 // if the user has the attribute, or an appropriate error if the user 973 // does not have this attribute. 974 func (ca *CA) userHasAttribute(username, attrname string) (string, error) { 975 val, err := ca.getUserAttrValue(username, attrname) 976 if err != nil { 977 return "", err 978 } 979 if val == "" { 980 return "", errors.Errorf("Identity '%s' does not have attribute '%s'", username, attrname) 981 } 982 return val, nil 983 } 984 985 // attributeIsTrue returns nil if the attribute has 986 // one of the following values: "1", "t", "T", "true", "TRUE", "True"; 987 // otherwise it will return an error 988 func (ca *CA) attributeIsTrue(username, attrname string) error { 989 val, err := ca.userHasAttribute(username, attrname) 990 if err != nil { 991 return err 992 } 993 val2, err := strconv.ParseBool(val) 994 if err != nil { 995 return errors.Wrapf(err, "Invalid value for attribute '%s' of identity '%s'", attrname, username) 996 } 997 if val2 { 998 return nil 999 } 1000 return errors.Errorf("Attribute '%s' is not set to true for identity '%s'", attrname, username) 1001 } 1002 1003 // getUserAttrValue returns a user's value for an attribute 1004 func (ca *CA) getUserAttrValue(username, attrname string) (string, error) { 1005 zclog.Debugf("getUserAttrValue identity=%s, attr=%s", username, attrname) 1006 userFromCaDB, err := ca.registry.GetUser(username, []string{attrname}) 1007 if err != nil { 1008 return "", err 1009 } 1010 attrval, err := userFromCaDB.GetAttribute(attrname) 1011 if err != nil { 1012 return "", errors.WithMessage(err, fmt.Sprintf("Failed to get attribute '%s' for user '%s'", attrname, userFromCaDB.GetName())) 1013 } 1014 zclog.Debugf("getUserAttrValue identity=%s, name=%s, value=%s", username, attrname, attrval) 1015 return attrval.Value, nil 1016 } 1017 1018 // getUserAffiliation returns a user's affiliation 1019 func (ca *CA) getUserAffiliation(username string) (string, error) { 1020 zclog.Debugf("getUserAffiliation identity=%s", username) 1021 user, err := ca.registry.GetUser(username, nil) 1022 if err != nil { 1023 return "", err 1024 } 1025 aff := cadbuser.GetAffiliation(user) 1026 zclog.Debugf("getUserAffiliation identity=%s, aff=%s", username, aff) 1027 return aff, nil 1028 } 1029 1030 // fillCAInfo fills the CA info structure appropriately 1031 func (ca *CA) fillCAInfo(info *api.CAInfoResponseNet) error { 1032 caChain, err := ca.getCAChain() 1033 if err != nil { 1034 return err 1035 } 1036 info.CAName = ca.Config.CA.Name 1037 info.CAChain = util.B64Encode(caChain) 1038 1039 ipkBytes, err := ca.issuer.IssuerPublicKey() 1040 if err != nil { 1041 return err 1042 } 1043 rpkBytes, err := ca.issuer.RevocationPublicKey() 1044 if err != nil { 1045 return err 1046 } 1047 info.IssuerPublicKey = util.B64Encode(ipkBytes) 1048 info.IssuerRevocationPublicKey = util.B64Encode(rpkBytes) 1049 return nil 1050 } 1051 1052 // Performs checks on the provided CA cert to make sure it's valid 1053 func (ca *CA) validateCertAndKey(certFile string, keyFile string) error { 1054 zclog.Debug("Validating the CA certificate and key") 1055 var err error 1056 var certPEM []byte 1057 1058 certPEM, err = ioutil.ReadFile(certFile) 1059 if err != nil { 1060 return errors.Wrapf(err, certificateError+" '%s'", certFile) 1061 } 1062 1063 cert, err := util.GetX509CertificateFromPEM(certPEM) 1064 if err != nil { 1065 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1066 } 1067 1068 if err = validateDates(cert); err != nil { 1069 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1070 } 1071 if err = validateUsage(cert, ca.Config.CA.Name); err != nil { 1072 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1073 } 1074 if err = validateIsCA(cert); err != nil { 1075 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1076 } 1077 if err = validateKeyType(cert); err != nil { 1078 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1079 } 1080 if err = validateKeySize(cert); err != nil { 1081 return errors.WithMessage(err, fmt.Sprintf(certificateError+" '%s'", certFile)) 1082 } 1083 if err = validateMatchingKeys(cert, keyFile); err != nil { 1084 return errors.WithMessage(err, fmt.Sprintf("Invalid certificate and/or key in files '%s' and '%s'", certFile, keyFile)) 1085 } 1086 zclog.Debug("Validation of CA certificate and key successful") 1087 1088 return nil 1089 } 1090 1091 // Returns expiration of the CA certificate 1092 func (ca *CA) getCACertExpiry() (time.Time, time.Time, error) { 1093 var notAfter time.Time 1094 var notBefore time.Time 1095 signer, ok := ca.enrollSigner.(*cflocalsigner.Signer) 1096 if ok { 1097 cacert, err := signer.Certificate("", "ca") 1098 if err != nil { 1099 zclog.Errorf("Failed to get CA certificate for CA %s: %s", ca.Config.CA.Name, err) 1100 return notBefore, notAfter, err 1101 } else if cacert != nil { 1102 notAfter = cacert.NotAfter 1103 notBefore = cacert.NotBefore 1104 } 1105 } else { 1106 zclog.Errorf("Not expected condition as the enrollSigner can only be cfssl/signer/local/Signer") 1107 return notBefore, notAfter, errors.New("Unexpected error while getting CA certificate expiration") 1108 } 1109 return notBefore, notAfter, nil 1110 } 1111 1112 func canSignCRL(cert *x509.Certificate) bool { 1113 return cert.KeyUsage&x509.KeyUsageCRLSign != 0 1114 } 1115 1116 func validateDates(cert *x509.Certificate) error { 1117 zclog.Debug("Check CA certificate for valid dates") 1118 1119 notAfter := cert.NotAfter 1120 currentTime := time.Now().UTC() 1121 1122 if currentTime.After(notAfter) { 1123 return errors.New("Certificate provided has expired") 1124 } 1125 1126 notBefore := cert.NotBefore 1127 if currentTime.Before(notBefore) { 1128 return errors.New("Certificate provided not valid until later date") 1129 } 1130 1131 return nil 1132 } 1133 1134 func validateUsage(cert *x509.Certificate, caName string) error { 1135 zclog.Debug("Check CA certificate for valid usages") 1136 1137 if cert.KeyUsage == 0 { 1138 return errors.New("No usage specified for certificate") 1139 } 1140 1141 if cert.KeyUsage&x509.KeyUsageCertSign == 0 { 1142 return errors.New("The 'cert sign' key usage is required") 1143 } 1144 1145 if !canSignCRL(cert) { 1146 zclog.Warnf("The CA certificate for the CA '%s' does not have 'crl sign' key usage, so the CA will not be able generate a CRL", caName) 1147 } 1148 return nil 1149 } 1150 1151 func validateIsCA(cert *x509.Certificate) error { 1152 zclog.Debug("Check CA certificate for valid IsCA value") 1153 1154 if !cert.IsCA { 1155 return errors.New("Certificate not configured to be used for CA") 1156 } 1157 1158 return nil 1159 } 1160 1161 // 国密改造后只支持sm2 1162 func validateKeyType(cert *x509.Certificate) error { 1163 zclog.Debug("Check that key type is supported") 1164 1165 switch cert.PublicKey.(type) { 1166 case *sm2.PublicKey: 1167 return nil 1168 default: 1169 return errors.New("Unsupported key type: not sm2") 1170 } 1171 } 1172 1173 func validateKeySize(cert *x509.Certificate) error { 1174 zclog.Debug("Check that key size is of appropriate length") 1175 1176 switch cert.PublicKey.(type) { 1177 // case *rsa.PublicKey: 1178 // size := cert.PublicKey.(*rsa.PublicKey).N.BitLen() 1179 // if size < 2048 { 1180 // return errors.New("Key size is less than 2048 bits") 1181 // } 1182 case *sm2.PublicKey: 1183 size := cert.PublicKey.(*sm2.PublicKey).Params().N.BitLen() 1184 if size != 256 { 1185 return errors.New("Key size must be 256 bits") 1186 } 1187 } 1188 1189 return nil 1190 } 1191 1192 // 国密对应后只支持sm2 1193 func validateMatchingKeys(cert *x509.Certificate, keyFile string) error { 1194 zclog.Debug("Check that public key and private key match") 1195 1196 keyPEM, err := ioutil.ReadFile(keyFile) 1197 if err != nil { 1198 return err 1199 } 1200 1201 pubKey := cert.PublicKey 1202 switch pubKey := pubKey.(type) { 1203 // TODO 添加sm2分支 1204 case *sm2.PublicKey: 1205 privKey, err := util.GetSM2PrivateKey(keyPEM) 1206 if err != nil { 1207 return err 1208 } 1209 if pubKey.X.Cmp(privKey.X) != 0 || pubKey.Y.Cmp(privKey.Y) != 0 { 1210 return errors.New("sm2 private key does not match public key") 1211 } 1212 // case *rsa.PublicKey: 1213 // privKey, err := util.GetRSAPrivateKey(keyPEM) 1214 // if err != nil { 1215 // return err 1216 // } 1217 1218 // if privKey.PublicKey.N.Cmp(pubKey.N) != 0 { 1219 // return errors.New("Public key and private key do not match") 1220 // } 1221 // case *ecdsa.PublicKey: 1222 // // pub, _ := cert.PublicKey.(*ecdsa.PublicKey) 1223 // // TODO 这里的分支可能不需要了 1224 // switch pubKey.Curve { 1225 // case sm2.P256Sm2(): 1226 // privKey, err := util.GetSM2PrivateKey(keyPEM) 1227 // if err != nil { 1228 // return err 1229 // } 1230 // if pubKey.X.Cmp(privKey.X) != 0 || pubKey.Y.Cmp(privKey.Y) != 0 { 1231 // return errors.New("sm2 private key does not match public key") 1232 // } 1233 // default: 1234 // privKey, err := util.GetECPrivateKey(keyPEM) 1235 // if err != nil { 1236 // return err 1237 // } 1238 1239 // if privKey.PublicKey.X.Cmp(pubKey.X) != 0 { 1240 // return errors.New("Public key and private key do not match") 1241 // } 1242 // } 1243 default: 1244 return errors.New("Unsupported public key") 1245 } 1246 1247 return nil 1248 } 1249 1250 // Load CN from existing enrollment information 1251 func (ca *CA) loadCNFromEnrollmentInfo(certFile string) (string, error) { 1252 zclog.Debug("Loading CN from existing enrollment information") 1253 cert, err := util.ReadFile(certFile) 1254 if err != nil { 1255 zclog.Debugf("No cert found at %s", certFile) 1256 return "", err 1257 } 1258 name, err := util.GetEnrollmentIDFromPEM(cert) 1259 if err != nil { 1260 return "", err 1261 } 1262 return name, nil 1263 } 1264 1265 // This function returns an error if the version specified in the configuration file is greater than the server version 1266 func (ca *CA) checkConfigLevels() error { 1267 var err error 1268 serverVersion := metadata.GetVersion() 1269 configVersion := ca.Config.Version 1270 zclog.Debugf("Checking configuration file version '%+v' against server version: '%+v'", configVersion, serverVersion) 1271 // Check configuration file version against server version to make sure that newer configuration file is not being used with server 1272 cmp, err := metadata.CmpVersion(configVersion, serverVersion) 1273 if err != nil { 1274 return errors.WithMessage(err, "Failed to compare version") 1275 } 1276 if cmp == -1 { 1277 return errors.Errorf("Configuration file version '%s' is higher than server version '%s'", configVersion, serverVersion) 1278 } 1279 cfg, err := metadata.GetLevels(ca.Config.Version) 1280 if err != nil { 1281 return err 1282 } 1283 ca.levels = cfg 1284 return nil 1285 } 1286 1287 func (ca *CA) checkDBLevels() error { 1288 // Check database table levels against server levels to make sure that a database levels are compatible with server 1289 levels, err := db.CurrentDBLevels(ca.db) 1290 if err != nil { 1291 return err 1292 } 1293 sl, err := metadata.GetLevels(metadata.GetVersion()) 1294 if err != nil { 1295 return err 1296 } 1297 zclog.Debugf("Checking database levels '%+v' against server levels '%+v'", levels, sl) 1298 if (levels.Identity > sl.Identity) || (levels.Affiliation > sl.Affiliation) || (levels.Certificate > sl.Certificate) || 1299 (levels.Credential > sl.Credential) || (levels.Nonce > sl.Nonce) || (levels.RAInfo > sl.RAInfo) { 1300 return caerrors.NewFatalError(caerrors.ErrDBLevel, "The version of the database is newer than the server version. Upgrade your server.") 1301 } 1302 return nil 1303 } 1304 1305 func writeFile(file string, buf []byte, perm os.FileMode) error { 1306 err := os.MkdirAll(filepath.Dir(file), 0755) 1307 if err != nil { 1308 return err 1309 } 1310 return ioutil.WriteFile(file, buf, perm) 1311 } 1312 1313 func affiliationPath(name, parent string) string { 1314 if parent == "" { 1315 return name 1316 } 1317 return fmt.Sprintf("%s.%s", parent, name) 1318 } 1319 1320 func parseDuration(str string) time.Duration { 1321 d, err := time.ParseDuration(str) 1322 if err != nil { 1323 panic(err) 1324 } 1325 return d 1326 } 1327 1328 func initSigningProfile(spp **config.SigningProfile, expiry time.Duration, isCA bool) { 1329 sp := *spp 1330 if sp == nil { 1331 sp = &config.SigningProfile{CAConstraint: config.CAConstraint{IsCA: isCA}} 1332 *spp = sp 1333 } 1334 if sp.Usage == nil { 1335 sp.Usage = []string{"cert sign", "crl sign"} 1336 } 1337 if sp.Expiry == 0 { 1338 sp.Expiry = expiry 1339 } 1340 if sp.ExtensionWhitelist == nil { 1341 sp.ExtensionWhitelist = map[string]bool{} 1342 } 1343 // This is set so that all profiles permit an attribute extension in CFSSL 1344 sp.ExtensionWhitelist[attrmgr.AttrOIDString] = true 1345 } 1346 1347 func getMigrator(driverName string, tx db.FabricCATx, curLevels, srvLevels *dbutil.Levels) (db.Migrator, error) { 1348 var migrator db.Migrator 1349 switch driverName { 1350 case "sqlite3": 1351 migrator = sqlite.NewMigrator(tx, curLevels, srvLevels) 1352 case "mysql": 1353 migrator = mysql.NewMigrator(tx, curLevels, srvLevels) 1354 case "postgres": 1355 migrator = postgres.NewMigrator(tx, curLevels, srvLevels) 1356 default: 1357 return nil, errors.Errorf("Unsupported database type: %s", driverName) 1358 } 1359 return migrator, nil 1360 }