@@ -25,6 +25,7 @@ import (
25
25
"github.com/letsencrypt/boulder/features"
26
26
bgrpc "github.com/letsencrypt/boulder/grpc"
27
27
blog "github.com/letsencrypt/boulder/log"
28
+ "github.com/letsencrypt/boulder/probs"
28
29
"github.com/letsencrypt/boulder/revocation"
29
30
sapb "github.com/letsencrypt/boulder/sa/proto"
30
31
"github.com/letsencrypt/boulder/unpause"
@@ -947,6 +948,11 @@ func (ssa *SQLStorageAuthority) FinalizeAuthorization2(ctx context.Context, req
947
948
if req .Status != string (core .StatusValid ) && req .Status != string (core .StatusInvalid ) {
948
949
return nil , berrors .InternalServerError ("authorization must have status valid or invalid" )
949
950
}
951
+
952
+ if features .Get ().WriteNewOrderSchema && looksLikeRandomID (req .Id , ssa .clk .Now ()) {
953
+ return ssa .finalizeAuthorization (ctx , req )
954
+ }
955
+
950
956
query := `UPDATE authz2 SET
951
957
status = :status,
952
958
attempted = :attempted,
@@ -1022,6 +1028,107 @@ func (ssa *SQLStorageAuthority) FinalizeAuthorization2(ctx context.Context, req
1022
1028
return & emptypb.Empty {}, nil
1023
1029
}
1024
1030
1031
+ // finalizeAuthorization inserts a new validation record into the validations
1032
+ // table, and then updates the identified authorizations row to point to the
1033
+ // newly-inserted validation.
1034
+ func (ssa * SQLStorageAuthority ) finalizeAuthorization (ctx context.Context , req * sapb.FinalizeAuthorizationRequest ) (* emptypb.Empty , error ) {
1035
+ // Convert the validation records and error to a json blob for storage in
1036
+ // the validations table.
1037
+ type recordJSON struct {
1038
+ Records []core.ValidationRecord
1039
+ Err * probs.ProblemDetails
1040
+ }
1041
+
1042
+ var records []core.ValidationRecord
1043
+ for _ , recPB := range req .ValidationRecords {
1044
+ rec , err := bgrpc .PBToValidationRecord (recPB )
1045
+ if err != nil {
1046
+ return nil , err
1047
+ }
1048
+ records = append (records , rec )
1049
+ }
1050
+
1051
+ var verr * probs.ProblemDetails
1052
+ if req .ValidationError != nil {
1053
+ verrShadow , err := bgrpc .PBToProblemDetails (req .ValidationError )
1054
+ if err != nil {
1055
+ return nil , err
1056
+ }
1057
+ verr = verrShadow
1058
+ }
1059
+
1060
+ record , err := json .Marshal (recordJSON {Records : records , Err : verr })
1061
+ if err != nil {
1062
+ return nil , fmt .Errorf ("failed to convert validation record to json: %w" , err )
1063
+ }
1064
+
1065
+ id , err := newRandomID (ssa .clk .Now ())
1066
+ if err != nil {
1067
+ return nil , err
1068
+ }
1069
+
1070
+ vm := validationsModel {
1071
+ ID : id ,
1072
+ Challenge : challTypeToUint [req .Attempted ],
1073
+ AttemptedAt : req .AttemptedAt .AsTime (),
1074
+ Status : statusUint (core .AcmeStatus (req .Status )),
1075
+ Record : record ,
1076
+ }
1077
+
1078
+ _ , overallError := db .WithTransaction (ctx , ssa .dbMap , func (tx db.Executor ) (interface {}, error ) {
1079
+ // Read the authz row to get its current status and list of validation IDs.
1080
+ var authz authorizationsModel
1081
+ err := tx .SelectOne (ctx , & authz , "SELECT status, validationIDs FROM authorizations WHERE id = ?" , req .Id )
1082
+ if err != nil {
1083
+ return nil , fmt .Errorf ("retrieving authz: %w" , err )
1084
+ }
1085
+
1086
+ if authz .Status != statusUint (core .StatusPending ) {
1087
+ return nil , fmt .Errorf ("cannot finalize authz with status %q" , uintToStatus [authz .Status ])
1088
+ }
1089
+
1090
+ // Insert the validation record.
1091
+ err = tx .Insert (ctx , vm )
1092
+ if err != nil {
1093
+ return nil , fmt .Errorf ("inserting new validation: %w" , err )
1094
+ }
1095
+
1096
+ // Update the authz row.
1097
+ res , err := tx .ExecContext (
1098
+ ctx , "UPDATE authorizations SET validationIDs = ? WHERE id = ? AND validationIDs = ?" ,
1099
+ append (authz .ValidationIDs [:], vm .ID ), req .Id , authz .ValidationIDs )
1100
+ if err != nil {
1101
+ return nil , fmt .Errorf ("updating authz: %w" , err )
1102
+ }
1103
+ rows , err := res .RowsAffected ()
1104
+ if err != nil {
1105
+ return nil , err
1106
+ }
1107
+ if rows != 1 {
1108
+ return nil , fmt .Errorf ("unexpected number of rows affected (%d)" , rows )
1109
+ }
1110
+
1111
+ // Delete the orderFQDNSet row for the order now that it has been finalized.
1112
+ // We use this table for order reuse and should not reuse a finalized order.
1113
+ err = deleteOrderFQDNSet (ctx , tx , req .Id )
1114
+ if err != nil {
1115
+ return nil , err
1116
+ }
1117
+
1118
+ err = setReplacementOrderFinalized (ctx , tx , req .Id )
1119
+ if err != nil {
1120
+ return nil , err
1121
+ }
1122
+
1123
+ return nil , nil
1124
+ })
1125
+ if overallError != nil {
1126
+ return nil , overallError
1127
+ }
1128
+
1129
+ return & emptypb.Empty {}, nil
1130
+ }
1131
+
1025
1132
// addRevokedCertificate is a helper used by both RevokeCertificate and
1026
1133
// UpdateRevokedCertificate. It inserts a new row into the revokedCertificates
1027
1134
// table based on the contents of the input request. The second argument must be
0 commit comments