diff --git a/core/objects.go b/core/objects.go index 46f313689ba..33f14d92d98 100644 --- a/core/objects.go +++ b/core/objects.go @@ -317,6 +317,11 @@ type Authorization struct { // as part of the authorization, the identifier we store in the database // can contain an asterisk. Wildcard bool `json:"wildcard,omitempty" db:"-"` + + // CertificateProfileName is the name of the profile associated with the + // order that first resulted in the creation of this authorization. Omitted + // from API responses. + CertificateProfileName string `json:"-"` } // FindChallengeByStringID will look for a challenge matching the given ID inside diff --git a/core/proto/core.pb.go b/core/proto/core.pb.go index 08605b14fa0..2e80de2c8e8 100644 --- a/core/proto/core.pb.go +++ b/core/proto/core.pb.go @@ -648,10 +648,11 @@ type Authorization struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` RegistrationID int64 `protobuf:"varint,3,opt,name=registrationID,proto3" json:"registrationID,omitempty"` // Fields specified by RFC 8555, Section 7.1.4 - DnsName string `protobuf:"bytes,2,opt,name=dnsName,proto3" json:"dnsName,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - Expires *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=expires,proto3" json:"expires,omitempty"` - Challenges []*Challenge `protobuf:"bytes,6,rep,name=challenges,proto3" json:"challenges,omitempty"` + DnsName string `protobuf:"bytes,2,opt,name=dnsName,proto3" json:"dnsName,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Expires *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=expires,proto3" json:"expires,omitempty"` + Challenges []*Challenge `protobuf:"bytes,6,rep,name=challenges,proto3" json:"challenges,omitempty"` + CertificateProfileName string `protobuf:"bytes,10,opt,name=certificateProfileName,proto3" json:"certificateProfileName,omitempty"` } func (x *Authorization) Reset() { @@ -728,6 +729,13 @@ func (x *Authorization) GetChallenges() []*Challenge { return nil } +func (x *Authorization) GetCertificateProfileName() string { + if x != nil { + return x.CertificateProfileName + } + return "" +} + type Order struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1033,7 +1041,7 @@ var file_core_proto_rawDesc = []byte{ 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, - 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0xf2, 0x01, 0x0a, 0x0d, + 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x22, 0xaa, 0x02, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, @@ -1047,49 +1055,53 @@ var file_core_proto_rawDesc = []byte{ 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, - 0x67, 0x65, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x73, 0x4a, 0x04, - 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, - 0x22, 0xd9, 0x03, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x78, - 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, - 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x76, 0x32, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x10, 0x76, 0x32, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0d, 0x20, + 0x67, 0x65, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x36, + 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x07, + 0x10, 0x08, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x22, 0xd9, 0x03, 0x0a, 0x05, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x65, 0x67, 0x61, 0x6e, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, - 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x22, 0x7a, 0x0a, 0x08, - 0x43, 0x52, 0x4c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x6f, - 0x6b, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x6c, + 0x65, 0x6d, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x12, 0x2a, 0x0a, 0x10, 0x76, 0x32, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x03, 0x52, 0x10, 0x76, 0x32, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x11, + 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, - 0x41, 0x74, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x12, 0x36, 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x65, 0x67, 0x61, + 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0f, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, + 0x6e, 0x67, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, + 0x08, 0x0a, 0x10, 0x0b, 0x22, 0x7a, 0x0a, 0x08, 0x43, 0x52, 0x4c, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, + 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, + 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, + 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/core/proto/core.proto b/core/proto/core.proto index 5411b44380b..0087a76a2cc 100644 --- a/core/proto/core.proto +++ b/core/proto/core.proto @@ -93,7 +93,7 @@ message Registration { } message Authorization { - // Next unused field number: 10 + // Next unused field number: 11 reserved 5, 7, 8; string id = 1; int64 registrationID = 3; @@ -102,6 +102,7 @@ message Authorization { string status = 4; google.protobuf.Timestamp expires = 9; repeated core.Challenge challenges = 6; + string certificateProfileName = 10; // We do not directly represent the "wildcard" field, instead inferring it // from the identifier value. } diff --git a/grpc/pb-marshalling.go b/grpc/pb-marshalling.go index 1ee482b8d9e..845d2e0888f 100644 --- a/grpc/pb-marshalling.go +++ b/grpc/pb-marshalling.go @@ -289,12 +289,13 @@ func AuthzToPB(authz core.Authorization) (*corepb.Authorization, error) { } return &corepb.Authorization{ - Id: authz.ID, - DnsName: authz.Identifier.Value, - RegistrationID: authz.RegistrationID, - Status: string(authz.Status), - Expires: expires, - Challenges: challs, + Id: authz.ID, + DnsName: authz.Identifier.Value, + RegistrationID: authz.RegistrationID, + Status: string(authz.Status), + Expires: expires, + Challenges: challs, + CertificateProfileName: authz.CertificateProfileName, }, nil } @@ -313,12 +314,13 @@ func PBToAuthz(pb *corepb.Authorization) (core.Authorization, error) { expires = &c } authz := core.Authorization{ - ID: pb.Id, - Identifier: identifier.NewDNS(pb.DnsName), - RegistrationID: pb.RegistrationID, - Status: core.AcmeStatus(pb.Status), - Expires: expires, - Challenges: challs, + ID: pb.Id, + Identifier: identifier.NewDNS(pb.DnsName), + RegistrationID: pb.RegistrationID, + Status: core.AcmeStatus(pb.Status), + Expires: expires, + Challenges: challs, + CertificateProfileName: pb.CertificateProfileName, } return authz, nil } diff --git a/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql b/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql deleted file mode 100644 index 9795a0a76d5..00000000000 --- a/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +migrate Up --- SQL in section 'Up' is executed when this migration is applied - -ALTER TABLE `authz2` ADD COLUMN `certificateProfileName` varchar(32) DEFAULT NULL; - --- +migrate Down --- SQL section 'Down' is executed when this migration is rolled back - -ALTER TABLE `authz2` DROP COLUMN `certificateProfileName`; diff --git a/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql b/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql new file mode 120000 index 00000000000..9c178cbb83a --- /dev/null +++ b/sa/db-next/boulder_sa/20250115000000_AuthzProfiles.sql @@ -0,0 +1 @@ +../../db/boulder_sa/20250115000000_AuthzProfiles.sql \ No newline at end of file diff --git a/sa/db/boulder_sa/20250115000000_AuthzProfiles.sql b/sa/db/boulder_sa/20250115000000_AuthzProfiles.sql new file mode 100644 index 00000000000..9795a0a76d5 --- /dev/null +++ b/sa/db/boulder_sa/20250115000000_AuthzProfiles.sql @@ -0,0 +1,9 @@ +-- +migrate Up +-- SQL in section 'Up' is executed when this migration is applied + +ALTER TABLE `authz2` ADD COLUMN `certificateProfileName` varchar(32) DEFAULT NULL; + +-- +migrate Down +-- SQL section 'Down' is executed when this migration is rolled back + +ALTER TABLE `authz2` DROP COLUMN `certificateProfileName`; diff --git a/sa/model.go b/sa/model.go index 909e0757f9f..3b68d5599c6 100644 --- a/sa/model.go +++ b/sa/model.go @@ -480,21 +480,24 @@ func statusUint(status core.AcmeStatus) uint8 { // authzFields is used in a variety of places in sa.go, and modifications to // it must be carried through to every use in sa.go -const authzFields = "id, identifierType, identifierValue, registrationID, status, expires, challenges, attempted, attemptedAt, token, validationError, validationRecord" +const authzFields = "id, identifierType, identifierValue, registrationID, certificateProfileName, status, expires, challenges, attempted, attemptedAt, token, validationError, validationRecord" +// authzModel represents one row in the authz2 table. The CertificateProfileName +// column is a pointer because the column is NULL-able. type authzModel struct { - ID int64 `db:"id"` - IdentifierType uint8 `db:"identifierType"` - IdentifierValue string `db:"identifierValue"` - RegistrationID int64 `db:"registrationID"` - Status uint8 `db:"status"` - Expires time.Time `db:"expires"` - Challenges uint8 `db:"challenges"` - Attempted *uint8 `db:"attempted"` - AttemptedAt *time.Time `db:"attemptedAt"` - Token []byte `db:"token"` - ValidationError []byte `db:"validationError"` - ValidationRecord []byte `db:"validationRecord"` + ID int64 `db:"id"` + IdentifierType uint8 `db:"identifierType"` + IdentifierValue string `db:"identifierValue"` + RegistrationID int64 `db:"registrationID"` + CertificateProfileName *string `db:"certificateProfileName"` + Status uint8 `db:"status"` + Expires time.Time `db:"expires"` + Challenges uint8 `db:"challenges"` + Attempted *uint8 `db:"attempted"` + AttemptedAt *time.Time `db:"attemptedAt"` + Token []byte `db:"token"` + ValidationError []byte `db:"validationError"` + ValidationRecord []byte `db:"validationRecord"` } // rehydrateHostPort mutates a validation record. If the URL in the validation @@ -627,7 +630,7 @@ func hasMultipleNonPendingChallenges(challenges []*corepb.Challenge) bool { // newAuthzReqToModel converts an sapb.NewAuthzRequest to the authzModel storage // representation. It hardcodes the status to "pending" because it should be // impossible to create an authz in any other state. -func newAuthzReqToModel(authz *sapb.NewAuthzRequest) (*authzModel, error) { +func newAuthzReqToModel(authz *sapb.NewAuthzRequest, profile string) (*authzModel, error) { am := &authzModel{ IdentifierType: identifierTypeToUint[authz.Identifier.Type], IdentifierValue: authz.Identifier.Value, @@ -636,6 +639,10 @@ func newAuthzReqToModel(authz *sapb.NewAuthzRequest) (*authzModel, error) { Expires: authz.Expires.AsTime(), } + if profile != "" { + am.CertificateProfileName = &profile + } + for _, challType := range authz.ChallengeTypes { // Set the challenge type bit in the bitmap am.Challenges |= 1 << challTypeToUint[challType] @@ -652,6 +659,8 @@ func newAuthzReqToModel(authz *sapb.NewAuthzRequest) (*authzModel, error) { // authzPBToModel converts a protobuf authorization representation to the // authzModel storage representation. +// Deprecated: this function is only used as part of test setup, do not +// introduce any new uses in production code. func authzPBToModel(authz *corepb.Authorization) (*authzModel, error) { am := &authzModel{ IdentifierType: identifierTypeToUint[string(identifier.TypeDNS)], @@ -660,6 +669,10 @@ func authzPBToModel(authz *corepb.Authorization) (*authzModel, error) { Status: statusToUint[core.AcmeStatus(authz.Status)], Expires: authz.Expires.AsTime(), } + if authz.CertificateProfileName != "" { + profile := authz.CertificateProfileName + am.CertificateProfileName = &profile + } if authz.Id != "" { // The v1 internal authorization objects use a string for the ID, the v2 // storage format uses a integer ID. In order to maintain compatibility we @@ -801,12 +814,18 @@ func modelToAuthzPB(am authzModel) (*corepb.Authorization, error) { return nil, fmt.Errorf("unrecognized identifier type encoding %d", am.IdentifierType) } + profile := "" + if am.CertificateProfileName != nil { + profile = *am.CertificateProfileName + } + pb := &corepb.Authorization{ - Id: fmt.Sprintf("%d", am.ID), - Status: string(uintToStatus[am.Status]), - DnsName: am.IdentifierValue, - RegistrationID: am.RegistrationID, - Expires: timestamppb.New(am.Expires), + Id: fmt.Sprintf("%d", am.ID), + Status: string(uintToStatus[am.Status]), + DnsName: am.IdentifierValue, + RegistrationID: am.RegistrationID, + Expires: timestamppb.New(am.Expires), + CertificateProfileName: profile, } // Populate authorization challenge array. We do this by iterating through // the challenge type bitmap and creating a challenge of each type if its diff --git a/sa/model_test.go b/sa/model_test.go index 0a4a97be398..2ea58e7638b 100644 --- a/sa/model_test.go +++ b/sa/model_test.go @@ -59,11 +59,12 @@ func TestAuthzModel(t *testing.T) { now := clk.Now() expires := now.Add(24 * time.Hour) authzPB := &corepb.Authorization{ - Id: "1", - DnsName: "example.com", - RegistrationID: 1, - Status: string(core.StatusValid), - Expires: timestamppb.New(expires), + Id: "1", + DnsName: "example.com", + RegistrationID: 1, + Status: string(core.StatusValid), + Expires: timestamppb.New(expires), + CertificateProfileName: "test", Challenges: []*corepb.Challenge{ { Type: string(core.ChallengeTypeHTTP01), @@ -101,6 +102,7 @@ func TestAuthzModel(t *testing.T) { authzPB.Challenges[0].Validationrecords[0].Hostname = "example.com" authzPB.Challenges[0].Validationrecords[0].Port = "443" test.AssertDeepEquals(t, authzPB.Challenges, authzPBOut.Challenges) + test.AssertEquals(t, authzPBOut.CertificateProfileName, authzPB.CertificateProfileName) now = clk.Now() expires = now.Add(24 * time.Hour) diff --git a/sa/sa.go b/sa/sa.go index 1523d42ab5f..b09e94eece8 100644 --- a/sa/sa.go +++ b/sa/sa.go @@ -521,7 +521,7 @@ func (ssa *SQLStorageAuthority) NewOrderAndAuthzs(ctx context.Context, req *sapb newAuthzIDs := make([]int64, 0) if features.Get().InsertAuthzsIndividually { for _, authz := range req.NewAuthzs { - am, err := newAuthzReqToModel(authz) + am, err := newAuthzReqToModel(authz, req.NewOrder.CertificateProfileName) if err != nil { return nil, err } @@ -538,7 +538,7 @@ func (ssa *SQLStorageAuthority) NewOrderAndAuthzs(ctx context.Context, req *sapb return nil, err } for _, authz := range req.NewAuthzs { - am, err := newAuthzReqToModel(authz) + am, err := newAuthzReqToModel(authz, req.NewOrder.CertificateProfileName) if err != nil { return nil, err } @@ -547,6 +547,7 @@ func (ssa *SQLStorageAuthority) NewOrderAndAuthzs(ctx context.Context, req *sapb am.IdentifierType, am.IdentifierValue, am.RegistrationID, + am.CertificateProfileName, statusToUint[core.StatusPending], am.Expires, am.Challenges, diff --git a/sa/sa_test.go b/sa/sa_test.go index 36f5d41ff2a..e63d40c430c 100644 --- a/sa/sa_test.go +++ b/sa/sa_test.go @@ -1043,6 +1043,55 @@ func TestNewOrderAndAuthzs_NewAuthzExpectedFields(t *testing.T) { test.AssertBoxedNil(t, am.ValidationRecord, "am.ValidationRecord should be nil") } +func TestNewOrderAndAuthzs_Profile(t *testing.T) { + sa, fc, cleanup := initSA(t) + defer cleanup() + + reg := createWorkingRegistration(t, sa) + expires := fc.Now().Add(time.Hour) + + // Create and order and authz while specifying a profile. + order, err := sa.NewOrderAndAuthzs(context.Background(), &sapb.NewOrderAndAuthzsRequest{ + NewOrder: &sapb.NewOrderRequest{ + RegistrationID: reg.Id, + Expires: timestamppb.New(expires), + DnsNames: []string{"example.com"}, + CertificateProfileName: "test", + }, + NewAuthzs: []*sapb.NewAuthzRequest{ + { + Identifier: &corepb.Identifier{Type: "dns", Value: "example.com"}, + RegistrationID: reg.Id, + Expires: timestamppb.New(expires), + ChallengeTypes: []string{string(core.ChallengeTypeHTTP01)}, + Token: core.NewToken(), + }, + }, + }) + if err != nil { + t.Fatalf("inserting order and authzs: %s", err) + } + + // Retrieve the order and check that the profile is correct. + gotOrder, err := sa.GetOrder(context.Background(), &sapb.OrderRequest{Id: order.Id}) + if err != nil { + t.Fatalf("retrieving inserted order: %s", err) + } + if gotOrder.CertificateProfileName != "test" { + t.Errorf("order.CertificateProfileName = %v, want %v", gotOrder.CertificateProfileName, "test") + } + + // Retrieve the authz and check that the profile is correct. + // Safely get the authz for the order we created above. + gotAuthz, err := sa.GetAuthorization2(context.Background(), &sapb.AuthorizationID2{Id: order.V2Authorizations[0]}) + if err != nil { + t.Fatalf("retrieving inserted authz: %s", err) + } + if gotAuthz.CertificateProfileName != "test" { + t.Errorf("authz.CertificateProfileName = %v, want %v", gotAuthz.CertificateProfileName, "test") + } +} + func BenchmarkNewOrderAndAuthzs(b *testing.B) { for _, flag := range []bool{false, true} { for _, numIdents := range []int{1, 2, 5, 10, 20, 50, 100} { @@ -1174,7 +1223,9 @@ func TestFinalizeOrder(t *testing.T) { test.AssertEquals(t, updatedOrder.Status, string(core.StatusValid)) } -func TestOrder(t *testing.T) { +// TestGetOrder tests that round-tripping a simple order through +// NewOrderAndAuthzs and GetOrder has the expected result. +func TestGetOrder(t *testing.T) { sa, fc, cleanup := initSA(t) defer cleanup() @@ -1230,7 +1281,9 @@ func TestOrder(t *testing.T) { test.AssertDeepEquals(t, storedOrder, expectedOrder) } -func TestOrderWithProfile(t *testing.T) { +// TestGetOrderWithProfile tests that round-tripping a simple order through +// NewOrderAndAuthzs and GetOrder has the expected result. +func TestGetOrderWithProfile(t *testing.T) { sa, fc, cleanup := initSA(t) defer cleanup()