Implement handling of returned certificates
This commit is contained in:
parent
73aad9d74e
commit
8c99fe2fab
1 changed files with 95 additions and 13 deletions
|
@ -100,12 +100,14 @@ WHERE crt = ''
|
|||
FROM emailcerts
|
||||
WHERE crt_name = ''
|
||||
AND csr_name != ''
|
||||
AND keytype = 'MS'
|
||||
AND codesign = 0
|
||||
AND warning < ?`
|
||||
sqlFindPersonalCodeSigningCertRequests = `SELECT id, csr_name, type, md, subject
|
||||
FROM emailcerts
|
||||
WHERE crt_name = ''
|
||||
AND csr_name != ''
|
||||
AND keytype = 'MS'
|
||||
AND codesign = 1
|
||||
AND warning < ?`
|
||||
sqlFindPersonalServerCertRequests = `SELECT id, csr_name, type, md, subject
|
||||
|
@ -117,12 +119,14 @@ WHERE crt_name = ''
|
|||
FROM orgemailcerts
|
||||
WHERE crt_name = ''
|
||||
AND csr_name != ''
|
||||
AND keytype = 'MS'
|
||||
AND codesign = 0
|
||||
AND warning < ?`
|
||||
sqlFindOrganizationalCodeSigningCertRequests = `SELECT id, csr_name, type, md, subject
|
||||
FROM orgemailcerts
|
||||
WHERE crt_name = ''
|
||||
AND csr_name != ''
|
||||
AND keytype = 'MS'
|
||||
AND codesign = 1
|
||||
AND warning < ?`
|
||||
sqlFindOrganizationalServerCertRequests = `SELECT id, csr_name, type, md, subject
|
||||
|
@ -155,7 +159,6 @@ SET crt_name=?,
|
|||
serial=?,
|
||||
expire=?
|
||||
WHERE id = ?`
|
||||
|
||||
sqlRecordFailedOpenPGP = `UPDATE gpg
|
||||
SET warning = warning + 1
|
||||
WHERE id = ?`
|
||||
|
@ -394,36 +397,54 @@ func (d *LegacyDB) Run(ctx context.Context) error { //nolint:gocognit,cyclop
|
|||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindPersonalClientCertRequests, respPersonalClientCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedPersonalClientCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindPersonalCodeSigningCertRequests, respPersonalCodeSigningCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedPersonalClientCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindPersonalServerCertRequests, respPersonalServerCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedPersonalServerCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindOrganizationalClientCertRequests, respOrganizationalClientCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedOrganizationalClientCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindOrganizationalCodeSigningCertRequests, respOrganizationalCodeSigningCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedOrganizationalClientCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.requestCerts(
|
||||
ctx, sqlFindOrganizationalServerCertRequests, respOrganizationalServerCertificate,
|
||||
func(ctx context.Context, rowID int) {
|
||||
d.recordFailure(ctx, sqlRecordFailedOrganizationalServerCertificate, rowID)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -527,7 +548,7 @@ func (d *LegacyDB) requestSignedOpenPGPKeys(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *LegacyDB) requestCerts(ctx context.Context, query string, rt responseType) error {
|
||||
func (d *LegacyDB) requestCerts(ctx context.Context, query string, rt responseType, recordFailureCallback func(ctx context.Context, rowID int)) error {
|
||||
issuerID, ok := d.issuerIDs[rt]
|
||||
if !ok {
|
||||
return fmt.Errorf("no known issuer id for type %s", rt)
|
||||
|
@ -634,6 +655,10 @@ func (d *LegacyDB) requestCerts(ctx context.Context, query string, rt responseTy
|
|||
"ids_with_issues": idsWithIssues,
|
||||
"rt": rt,
|
||||
}).Warn("some certificates failed")
|
||||
|
||||
for _, id := range idsWithIssues {
|
||||
recordFailureCallback(ctx, id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -783,9 +808,16 @@ func (d *LegacyDB) revokeOrganizationServerCerts(_ context.Context) error {
|
|||
}
|
||||
|
||||
func (d *LegacyDB) writeCertificate(prefix string, rowID int, signatureData []byte) (string, error) {
|
||||
crtFileName := path.Join("..", "crt", prefix, strconv.Itoa(rowID/1000), fmt.Sprintf("%s-%d.crt", prefix, rowID))
|
||||
crtDir := path.Join("..", "crt", prefix, strconv.Itoa(rowID/1000))
|
||||
|
||||
err := os.WriteFile(crtFileName, signatureData, 0o644) //nolint:gosec,gomnd
|
||||
err := os.MkdirAll(crtDir, 0o755)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not create directory: %w", err)
|
||||
}
|
||||
|
||||
crtFileName := path.Join(crtDir, fmt.Sprintf("%s-%d.crt", prefix, rowID))
|
||||
|
||||
err = os.WriteFile(crtFileName, signatureData, 0o644) //nolint:gosec,gomnd
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not write to file: %w", err)
|
||||
}
|
||||
|
@ -793,11 +825,45 @@ func (d *LegacyDB) writeCertificate(prefix string, rowID int, signatureData []by
|
|||
return crtFileName, nil
|
||||
}
|
||||
|
||||
func (d *LegacyDB) recordCertificate(_ context.Context, prefix, query string, rowID int, certBytes []byte) error {
|
||||
panic(fmt.Sprintf(
|
||||
"not implemented: record certificate to prefix %s with query %s for rowID %d (%d bytes)",
|
||||
prefix, query, rowID, len(certBytes),
|
||||
))
|
||||
type errUnexpectedRowCount struct {
|
||||
count int
|
||||
}
|
||||
|
||||
func (e errUnexpectedRowCount) Error() string {
|
||||
return fmt.Sprintf("unexpected row count %d", e.count)
|
||||
}
|
||||
|
||||
func (d *LegacyDB) recordCertificate(ctx context.Context, prefix, query string, rowID int, certBytes []byte) error {
|
||||
certificate, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse certificate for prefix %s id %d: %w", prefix, rowID, err)
|
||||
}
|
||||
|
||||
expiry := certificate.NotAfter
|
||||
serial := certificate.SerialNumber.Text(16) //nolint:gomnd
|
||||
|
||||
pemData := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
|
||||
|
||||
crtName, err := d.writeCertificate(prefix, rowID, pemData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write certificate data for prefix %s id %d: %w", prefix, rowID, err)
|
||||
}
|
||||
|
||||
res, err := d.db.ExecContext(ctx, query, crtName, serial, expiry, rowID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not update record for prefix %s id %d: %w", prefix, rowID, err)
|
||||
}
|
||||
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting number of affected rows: %w", err)
|
||||
}
|
||||
|
||||
if rows != 1 {
|
||||
return errUnexpectedRowCount{count: int(rows)}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *LegacyDB) recordPersonalClientRevoke(_ context.Context, rowID int, revokedAt time.Time) error {
|
||||
|
@ -912,13 +978,29 @@ func (d *LegacyDB) handleSignedCertificate(
|
|||
|
||||
switch pending.responseType {
|
||||
case respPersonalClientCertificate, respPersonalCodeSigningCertificate:
|
||||
err = d.recordCertificate(ctx, prefixPersonalClient, sqlRecordPersonalClientCert, pending.rowID, r.CertificateData)
|
||||
err = d.recordCertificate(
|
||||
ctx,
|
||||
prefixPersonalClient, sqlRecordPersonalClientCert,
|
||||
pending.rowID, r.CertificateData,
|
||||
)
|
||||
case respPersonalServerCertificate:
|
||||
err = d.recordCertificate(ctx, prefixPersonalServer, sqlRecordPersonalServerCert, pending.rowID, r.CertificateData)
|
||||
err = d.recordCertificate(
|
||||
ctx,
|
||||
prefixPersonalServer, sqlRecordPersonalServerCert,
|
||||
pending.rowID, r.CertificateData,
|
||||
)
|
||||
case respOrganizationalClientCertificate, respOrganizationalCodeSigningCertificate:
|
||||
err = d.recordCertificate(ctx, prefixOrganizationalClient, sqlRecordOrganizationalClientCert, pending.rowID, r.CertificateData)
|
||||
err = d.recordCertificate(
|
||||
ctx,
|
||||
prefixOrganizationalClient, sqlRecordOrganizationalClientCert,
|
||||
pending.rowID, r.CertificateData,
|
||||
)
|
||||
case respOrganizationalServerCertificate:
|
||||
err = d.recordCertificate(ctx, prefixOrganizationalServer, sqlRecordOrganizationalServerCert, pending.rowID, r.CertificateData)
|
||||
err = d.recordCertificate(
|
||||
ctx,
|
||||
prefixOrganizationalServer, sqlRecordOrganizationalServerCert,
|
||||
pending.rowID, r.CertificateData,
|
||||
)
|
||||
default:
|
||||
return fmt.Errorf("unexpected response type for pending request %s", announce.ID)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue