// Finalize signs a certificate if the necessary conditions for Order completion
// have been met.
Finalize signs a certificate if the necessary conditions for Order completion
have been met.
// Finalize signs a certificate if the necessary conditions for Order completion // have been met .
func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateRequest, auth CertificateAuthority, p Provisioner) error {
	if err := o.UpdateStatus(ctx, db); err != nil {
		return err
	}
	switch o.Status {
	case StatusInvalid:
		return NewError(ErrorOrderNotReadyType, "order %s has been abandoned", o.ID)
	case StatusValid:
		return nil
	case StatusPending:
		return NewError(ErrorOrderNotReadyType, "order %s is not ready", o.ID)
	case StatusReady:
		break
	default:
		return NewErrorISE("unexpected status %s for order %s", o.Status, o.ID)
	}
	if csr.Subject.CommonName != "" {
		csr.DNSNames = append(csr.DNSNames, csr.Subject.CommonName)
	}
	csr.DNSNames = uniqueSortedLowerNames(csr.DNSNames)
	orderNames := make([]string, len(o.Identifiers))
	for i, n := range o.Identifiers {
		orderNames[i] = n.Value
	}
	orderNames = uniqueSortedLowerNames(orderNames)
	 Note that with certificate templates we are not going to check for the
	 absence of other SANs as they will only be set if the templates allows
	 them.
	if len(csr.DNSNames) != len(orderNames) {
		return NewError(ErrorBadCSRType, "CSR names do not match identifiers exactly: "+
			"CSR names = %v, Order names = %v", csr.DNSNames, orderNames)
	}
	sans := make([]x509util.SubjectAlternativeName, len(csr.DNSNames))
	for i := range csr.DNSNames {
		if csr.DNSNames[i] != orderNames[i] {
			return NewError(ErrorBadCSRType, "CSR names do not match identifiers exactly: "+
				"CSR names = %v, Order names = %v", csr.DNSNames, orderNames)
		}
		sans[i] = x509util.SubjectAlternativeName{
			Type:  x509util.DNSType,
			Value: csr.DNSNames[i],
		}
	}
	 Get authorizations from the ACME provisioner.
	ctx = provisioner.NewContextWithMethod(ctx, provisioner.SignMethod)
	signOps, err := p.AuthorizeSign(ctx, "")
	if err != nil {
		return WrapErrorISE(err, "error retrieving authorization options from ACME provisioner")
	}
	 Template data
	data := x509util.NewTemplateData()
	data.SetCommonName(csr.Subject.CommonName)
	data.Set(x509util.SANsKey, sans)
	templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data)
	if err != nil {
		return WrapErrorISE(err, "error creating template options from ACME provisioner")
	}
	signOps = append(signOps, templateOptions)
	 Sign a new certificate.
	certChain, err := auth.Sign(csr, provisioner.SignOptions{
		NotBefore: provisioner.NewTimeDuration(o.NotBefore),
		NotAfter:  provisioner.NewTimeDuration(o.NotAfter),
	}, signOps...)
	if err != nil {
		return WrapErrorISE(err, "error signing certificate for order %s", o.ID)
	}
	cert := &Certificate{
		AccountID:     o.AccountID,
		OrderID:       o.ID,
		Leaf:          certChain[0],
		Intermediates: certChain[1:],
	}
	if err := db.CreateCertificate(ctx, cert); err != nil {
		return WrapErrorISE(err, "error creating certificate for order %s", o.ID)
	}
	o.CertificateID = cert.ID
	o.Status = StatusValid
	if err = db.UpdateOrder(ctx, o); err != nil {
		return WrapErrorISE(err, "error updating order %s", o.ID)
	}
	return nil
}
func ( o * Order ) Finalize ( ctx context . Context , db DB , csr * x509 . CertificateRequest , auth CertificateAuthority , p Provisioner ) error { if err := o . UpdateStatus ( ctx , db ) ; err != nil { return err } switch o . Status { case StatusInvalid : return NewError ( ErrorOrderNotReadyType , " " , o . ID ) case StatusValid : return nil case StatusPending : return NewError ( ErrorOrderNotReadyType , " " , o . ID ) case StatusReady : break default : return NewErrorISE ( " " , o . Status , o . ID ) } if csr . Subject . CommonName != " " { csr . DNSNames = append ( csr . DNSNames , csr . Subject . CommonName ) } csr . DNSNames = uniqueSortedLowerNames ( csr . DNSNames ) orderNames := make ( [ ] string , len ( o . Identifiers ) ) for i , n := range o . Identifiers { orderNames [ i ] = n . Value } orderNames = uniqueSortedLowerNames ( orderNames ) if len ( csr . DNSNames ) != len ( orderNames ) { return NewError ( ErrorBadCSRType , " " + " " , csr . DNSNames , orderNames ) } sans := make ( [ ] x509util . SubjectAlternativeName , len ( csr . DNSNames ) ) for i := range csr . DNSNames { if csr . DNSNames [ i ] != orderNames [ i ] { return NewError ( ErrorBadCSRType , " " + " " , csr . DNSNames , orderNames ) } sans [ i ] = x509util . SubjectAlternativeName { Type : x509util . DNSType , Value : csr . DNSNames [ i ] , } } ctx = provisioner . NewContextWithMethod ( ctx , provisioner . SignMethod ) signOps , err := p . AuthorizeSign ( ctx , " " ) if err != nil { return WrapErrorISE ( err , " " ) } data := x509util . NewTemplateData ( ) data . SetCommonName ( csr . Subject . CommonName ) data . Set ( x509util . SANsKey , sans ) templateOptions , err := provisioner . TemplateOptions ( p . GetOptions ( ) , data ) if err != nil { return WrapErrorISE ( err , " " ) } signOps = append ( signOps , templateOptions ) certChain , err := auth . Sign ( csr , provisioner . SignOptions { NotBefore : provisioner . NewTimeDuration ( o . NotBefore ) , NotAfter : provisioner . NewTimeDuration ( o . NotAfter ) , } , signOps ... ) if err != nil { return WrapErrorISE ( err , " " , o . ID ) } cert := & Certificate { AccountID : o . AccountID , OrderID : o . ID , Leaf : certChain [ 0 ] , Intermediates : certChain [ 1 : ] , } if err := db . CreateCertificate ( ctx , cert ) ; err != nil { return WrapErrorISE ( err , " " , o . ID ) } o . CertificateID = cert . ID o . Status = StatusValid if err = db . UpdateOrder ( ctx , o ) ; err != nil { return WrapErrorISE ( err , " " , o . ID ) } return nil }
Finalize signs a certificate if the necessary conditions for Order completion
have been met.
Finalize signs a certificate if the necessary conditions for Order completion have been met .
// RFC8555: The CSR MUST indicate the exact same set of requested // identifiers as the initial newOrder request. Identifiers of type "dns" // MUST appear either in the commonName portion of the requested subject // name or in an extensionRequest attribute [RFC2985] requesting a // subjectAltName extension, or both. // Validate identifier names against CSR alternative names. // // Note that with certificate templates we are not going to check for the // absence of other SANs as they will only be set if the templates allows // them. // Get authorizations from the ACME provisioner. // Template data // Sign a new certificate.