-
-
Notifications
You must be signed in to change notification settings - Fork 628
Simplify IssueCertificate into straight-line code #8424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
e400019
to
95946c2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very nice improvement!
Result struct { | ||
Precertificate string `json:",omitempty"` | ||
Certificate string `json:",omitempty"` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why change the structure of the log event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this Result sub-struct, the only two ways to actually log Precertificate or a Certificate are:
ca.log.AuditObject(issuanceEvent{
Requester: 1,
Result: struct{Precertificate string, Certificate string}{Certificate: cert}
})
or
event := issuanceEvent{
Requester: 1,
...
}
event.Result.Certificate = cert
ca.log.AuditObject(event)
The first is clearly ugly and confusing, and far too much boilerplate. The second creates local event
variables that shouldn't need to exist, and assigns into a field of an already-created struct, which is a pattern we try to avoid.
Historically we've been doing the latter because we've been modifying the issuanceEvent that was logged prior to issuance in order to log it again after issuance. I really didn't like that, and wanted to inline our audit event logging.
The most obvious alternative change would be
type issuanceEventResult struct {
Precertificate string
Certificate string
}
type issuanceEvent struct {
Requester int64
...
Result issuanceEventResult
}
but I didn't see any particular reason to keep the Result
sub-struct around either, so I went with the simpler structure.
ca/ca.go
Outdated
// lintCertMatchesPrecert verifies that the contents of the linting final cert | ||
// exactly match the contents of the precert, with the exception of the poison | ||
// extension, SCT extension, and signature. It also ignores the AKID, since the | ||
// linting issuer has a different key and Go auto-generates the AKID extension | ||
// from the issuer itself. We use the linting final cert so this function can | ||
// run before we issue the actual final cert: if we've changed issuers, swapped | ||
// profiles, or there's a bug in RequestFromPrecertificate, this function is | ||
// positioned to catch it. | ||
func lintCertMatchesPrecert(precertDER []byte, lintCertDER []byte) error { | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, this check is already performed inside issuer.Prepare
. If the issuance request has a precert, Prepare
generates a linting certificate, then checks precert.Correspond
between the precert and the linting certificate:
Lines 398 to 403 in 30197ca
if len(req.precertDER) > 0 { | |
err = precert.Correspond(req.precertDER, lintCertBytes) | |
if err != nil { | |
return nil, nil, fmt.Errorf("precert does not correspond to linted final cert: %w", err) | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I KNEW I'd seen this code somewhere before. I thought it was in the certificate-transparency-go library and couldn't find it there. I'd completely forgotten that you'd written it for us in //precert/corr.go.
Thanks for the pointer, I'll remove this stub.
95946c2
to
8934226
Compare
The issuePrecertificate, issuePrecertificateInner, and issueCertificateForPrecertificate helpers were originally necessary because the RA made two separate gRPC calls to the CA, before and after acquiring SCTs. Now, the CA handles acquiring SCTs itself, and there's only one gRPC entrypoint: ca.IssueCertficate. This means that the layers of abstraction represented by those old helpers are no longer necessary, and we can significantly simplify the CA's core logic.
Inline the contents of issuePrecertificate, issuePrecertificateInner, and issueCertificateForPrecertificate directly into IssueCertificate. Remove the sa.GetCertificate check, because it is now impossible for the final-certificate issuance code to have been reached except by progressing through the precert issuance code. Remove the need to derive an issuer and a profile from the precert, because we are still holding onto the exact same issuer and profile that were used to issue the precert.
Delete the unit tests which were only testing the underlying issuePrecertificate and issueCertificateForPrecertificate helpers. As of #8422, those tests were redundant. Move some helpers which were shared by the old and new tests to new homes closer to their now-sole callers.
Part of #8390
Warning
Do not merge before #8422