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
Submit issued certificates to CT logs #454
Conversation
Note I want to make some changes to how the chain (for submission) is generated, this will really depend on how individual CAs issued leafs chain back up to their root. Basically every element of the chain should be included in the submission until the end of the chain or an element in the target logs root pool is encountered. This will require a bit of hackery, open to any suggestions. |
|
||
// SubmitToCT sends a request to submit a certifcate to CT logs | ||
func (pub PublisherAuthorityClient) SubmitToCT(cert *x509.Certificate) (err error) { | ||
_, err = pub.rpc.DispatchSync(MethodSubmitToCT, cert.Raw) |
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.
Does this really need to be designed to be synchronous?
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.
Not for the current implementation, in the future we will probably want either another external tool (or to integrate the functionality into one of the existing ones) that can scan the database for certificates that haven't been submitted to all configured logs and attempt to re-submit them. This tool would probably want it to be synchronous so that it can properly retrieve any error messages that are passed back.
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.
Actually, I think it should be asynchronous, and assume a durable queue. No responses. The publisher's job is then to chew through that queue at whatever rate it can.
We'll want the publisher to only ack a message off the queue though if it is successful or has an exception -- not if it crashes, etc.
I'd like to be able to trigger this code -- somehow -- on already-signed certificates. Maybe not on day 1, but be able to easily make a tool handle that can, for a given cert, publish it. Are we going to need to produce something that can, for a given cert, decide if it's been published yet and publish it? Or maybe we can mark the RPC queue as durable for that? I appreciate that this code uses a goroutine to avoid affecting issuance. (And maybe we should use the goroutine trick with OCSP actually -- I opened #458 to consider) |
I'm currently working on storing the SCTs returned from logs in the certificateStatus table, which will be needed for generating the x509v3 extensions we will need to append to OCSP responses. The lack of a SCT would then be an indicator that the certificate hasn't been published and needs to be. I do like the durable queue idea although since we will need to store the SCT for future operations we could run into a situation where the tool we run to check for unsubmitted certs would have to know which certs don't have an SCT due to failure (incl. RPC failure) and which certs still have |
So I've made the submission chain construction better, it would be nice to have an external tool that can take the full chain (from issuer cert to its root) and a collected root pool from configured CT logs (available via an endpoint) and create the shortest valid submission chain for the I've also added a new SQL table, I've come around to @jcjones way of thinking on sync vs async and durability of the queue. I still think we will need an external tool to scan the certificate database and check that SCT receipts for all configured CT logs are present (and submitted if not) but the overlap between this and certificates waiting un ACK'd in the RPC queue should be small enough that it doesn't matter (especially since this will probably only needed to be run if there are network issues, troubles for log server, etc, ). I'll rework the RPC stuff as suggested and add a tool to scan the database for certificates that don't have SCT receipts for all configured logs. Hopefully then we will be done on the feature front...! |
I've added the CT chain bundle generation tool, When using a chain with a root signed by something in the root pool the output looks something like this (using the LE website certificate as an example, with truncated output)
The failures for Using the actual LE issuance certs this currently will fail for all logs (presumably because it isn't cross signed yet) like this
|
LogID []byte `db:"logID",json:"rpcLogID"` | ||
// Timestamp (in ms since unix epoc) at which the SCT was issued | ||
Timestamp uint64 `db:"timestamp",json:"rpcTimestamp"` | ||
// For future extensions to the protocol |
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.
Is this used today? If not, remove it I think.
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 will be required to assemble the SCT we want to put in OCSP responses in the future (but yes not now).
Things that still need to be done
Things deferred for another changeset
|
97e43f3
to
0165646
Compare
}, | ||
|
||
"publisher": { | ||
"dbDriver": "sqlite3", |
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 rebase error, I guess
This branch has merge conflicts now, in addition to the above comments about pulling out the durable queue stuff. |
} | ||
|
||
func postJSON(client *http.Client, uri string, data []byte, respObj interface{}) (*http.Response, error) { | ||
if !strings.HasPrefix(uri, "http://") && !strings.HasPrefix(uri, "https://") { |
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 really don't like this auto-adding https:
prefix. Can you remove it and just require that uri
be a valid absolute URL?
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.
Whoops, thought I had done this in the last changeset.
@@ -246,6 +256,8 @@ func TestIssueCertificate(t *testing.T) { | |||
defer ctx.cleanUp() | |||
ca, err := NewCertificateAuthorityImpl(ctx.caDB, ctx.caConfig, ctx.fc, caCertFile) | |||
test.AssertNotError(t, err, "Failed to create CA") | |||
pub, _ := publisher.NewPublisherImpl(publisher.CTConfig{}) |
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 do we need real publishers rather than mocks here?
`sctVersion` tinyint(1) NOT NULL, | ||
`logID` varchar(255) NOT NULL, | ||
`timestamp` bigint(20) NOT NULL, | ||
`extensions` mediumblob, |
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.
blob for both of these
|
2 similar comments
|
|
69db771
to
b53f8bb
Compare
LGTM I am okay with this. The next thing to do is to implement backfilling per my email just now about our certificate numbering scheme. |
Adds a new service, Publisher, which exists to submit issued certificates to various Certificate Transparency logs. Once submitted the Publisher will also parse and store the returned SCT (Signed Certificate Timestamp) receipts that are used to prove inclusion in a specific log in the SA database. A SA migration adds the new SCT receipt table. The Publisher only exposes one method, SubmitToCT, which is called in a goroutine by ca.IssueCertificate as to not block any other issuance operations. This method will iterate through all of the configured logs attempting to submit the certificate, and any required intermediate certificates, to them. If a submission to a log fails it will be retried the pre-configured number of times and will either use a back-off set in a Retry-After header or a pre-configured back-off between submission attempts. This changeset is the first of a number of changes ending with serving SCT receipts in OCSP responses and purposefully leaves out the following pieces for follow-up PRs. * A fake CT server for integration testing * A external tool to search the database for certificates lacking a full set of SCT receipts * A method to construct X.509 v3 extensions containing receipts for the OCSP responder * Returned SCT signature verification (beyond just checking that the signature is of the correct type so we aren't just serving arbitrary binary blobs to clients) Resolves #95.
b53f8bb
to
ff6eca7
Compare
Submit issued certificates to CT logs
This PR adds a new service,
Publisher
, which exists to submit issued certificates to various Certificate Transparency logs. Once submitted thePublisher
will also parse and store the returned SCT (Signed Certificate Timestamp) receipts that are used to prove inclusion in a specific log in the SA database. A SA migration adds the new SCT receipt table.The
Publisher
only exposes one method,SubmitToCT
, which is called in a goroutine byca.IssueCertificate
as to not block any other issuance operations. This method will iterate through all of the configured logs attempting to submit the certificate, and any required intermediate certificates, to them. If a submission to a log fails it will be retried the pre-configured number of times and will either use a back-off set in aRetry-After
header or a pre-configured back-off between submission attempts.This changeset is the first of a number of changes ending with serving SCT receipts in OCSP responses and purposefully leaves out the following pieces for follow-up PRs.
Resolves #95.