Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7eae03a
Add UpdateRevokedCertificate method to SA
aarongable Feb 23, 2022
add2bef
Update autogenerated protobuf files
aarongable Feb 23, 2022
5b32cba
Add test and fix things caught by test
aarongable Feb 23, 2022
19b9d7a
Fix mock
aarongable Feb 23, 2022
6ec5edc
Refactor how RA handles revocation requests
aarongable Feb 24, 2022
f8ff7fb
Fix existing tests
aarongable Feb 25, 2022
e59a838
Filter admin revocation reasons
aarongable Feb 25, 2022
12e1a0b
Merge `BySubscriber` and `ByController`
aarongable Feb 28, 2022
87b284a
Add tests for new SA method
aarongable Feb 28, 2022
5b0860e
Merge branch main into ra-block-already-revoked
aarongable Feb 28, 2022
a7165f7
Add tests for new RA methods
aarongable Mar 1, 2022
956ee35
Handle akamai purge failures differently
aarongable Mar 4, 2022
8ed4ce5
Comment updates
aarongable Mar 4, 2022
444cdd8
Use sentinel error
aarongable Mar 4, 2022
45db767
Rename update method
aarongable Mar 4, 2022
2df83c8
Fix lint
aarongable Mar 4, 2022
19c58d5
Address comments
aarongable Mar 8, 2022
5fed19e
Return better errors
aarongable Mar 8, 2022
38be46d
Fix bug revealed by WFE tests
aarongable Mar 9, 2022
432dc2d
Put policy changes behind a feature flag
aarongable Mar 9, 2022
8a33b7a
Update unit tests to cover feature flag
aarongable Mar 9, 2022
c8e1c8c
Ensure logged err is correct
aarongable Mar 10, 2022
ee2dd41
Restore
aarongable Mar 10, 2022
18793d4
Add 'applicant' to Method comment
aarongable Mar 10, 2022
d2720b3
Use new RA methods from WFE revocation path
aarongable Mar 8, 2022
a01948d
Better use of errors
aarongable Mar 8, 2022
90459df
Update python integration tests
aarongable Mar 9, 2022
3dd6124
Fix go integration tests
aarongable Mar 9, 2022
03466a4
Grant sa_ro read on serials
aarongable Mar 9, 2022
3650815
Merge branch main into wfe-new-revocation
aarongable Mar 14, 2022
c37c766
Update python integration tests
aarongable Mar 16, 2022
628aa3e
Fix bugs found by python integration tests
aarongable Mar 16, 2022
b1d7814
Run both kinds of go integration tests
aarongable Mar 16, 2022
301cdc4
Move re-revocation behind a separate flag
aarongable Mar 16, 2022
f5ac0c8
Minor updates to comments and names
aarongable Mar 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion akamai/cache-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func (cpc *CachePurgeClient) authedRequest(endpoint string, body v3PurgeRequest)
}

cpc.log.AuditInfof("Purge request sent successfully (ID %s) (body %s). Purge expected in %ds",
purgeInfo.PurgeID, purgeInfo.EstimatedSeconds, reqBody)
purgeInfo.PurgeID, reqBody, purgeInfo.EstimatedSeconds)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,5 @@ func AlreadyRevokedError(msg string, args ...interface{}) error {
}

func BadRevocationReasonError(reason int64) error {
return New(AlreadyRevoked, "disallowed revocation reason: %d", reason)
return New(BadRevocationReason, "disallowed revocation reason: %d", reason)
}
7 changes: 4 additions & 3 deletions features/featureflag_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions features/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ const (
GetAuthzUseIndex
// Check the failed authorization limit before doing authz reuse.
CheckFailedAuthorizationsFirst
// AllowReRevocation causes the RA to allow the revocation reason of an
// already-revoked certificate to be updated to `keyCompromise` from any
// other reason if that compromise is demonstrated by making the second
// revocation request signed by the certificate keypair.
AllowReRevocation
// MozRevocationReasons causes the RA to enforce the following upcoming
// Mozilla policies regarding revocation:
// - A subscriber can request that their certificate be revoked with reason
Expand Down Expand Up @@ -97,6 +102,7 @@ var features = map[FeatureFlag]bool{
GetAuthzReadOnly: false,
GetAuthzUseIndex: false,
CheckFailedAuthorizationsFirst: false,
AllowReRevocation: false,
MozRevocationReasons: false,
}

Expand Down
19 changes: 17 additions & 2 deletions ra/ra.go
Original file line number Diff line number Diff line change
Expand Up @@ -2111,7 +2111,17 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
// to the blocked keys list is a worse failure than failing to revoke in the
// first place, because it means that bad-key-revoker won't revoke the cert
// anyway.
if reason == ocsp.KeyCompromise {
var shouldBlock bool
if features.Enabled(features.AllowReRevocation) {
// If we're allowing re-revocation, then block the key for all keyCompromise
// requests, no matter whether the revocation itself succeeded or failed.
shouldBlock = reason == ocsp.KeyCompromise
} else {
// Otherwise, only block the key if the revocation above succeeded, or
// failed for a reason other than "already revoked".
shouldBlock = (reason == ocsp.KeyCompromise && !errors.Is(revokeErr, berrors.AlreadyRevoked))
}
if shouldBlock {
var digest core.Sha256Digest
digest, err = core.KeyDigest(cert.PublicKey)
if err != nil {
Expand All @@ -2132,7 +2142,12 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
// than keyCompromise.
err = revokeErr
if err != nil {
if !errors.Is(err, berrors.AlreadyRevoked) || reason != ocsp.KeyCompromise {
// Immediately error out, rather than trying re-revocation, if the error was
// anything other than AlreadyRevoked, if the requested reason is anything
// other than keyCompromise, or if we're not yet using the new logic.
if !errors.Is(err, berrors.AlreadyRevoked) ||
reason != ocsp.KeyCompromise ||
!features.Enabled(features.AllowReRevocation) {
return nil, err
}
err = ra.updateRevocationForKeyCompromise(ctx, cert.SerialNumber, int64(issuerID))
Expand Down
32 changes: 27 additions & 5 deletions ra/ra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3872,6 +3872,19 @@ func TestRevokeCertByKey(t *testing.T) {
test.AssertEquals(t, len(mockSA.blocked), 0)
test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)], int64(ocsp.Unspecified))

// Re-revoking for any reason should fail, because it isn't enabled.
_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
Cert: cert.Raw,
Code: ocsp.KeyCompromise,
})
test.AssertError(t, err, "should have failed")

// Enable re-revocation.
_ = features.Set(map[string]bool{
features.MozRevocationReasons.String(): false,
features.AllowReRevocation.String(): true,
})

// Re-revoking for the same reason should fail.
_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
Cert: cert.Raw,
Expand Down Expand Up @@ -3950,13 +3963,26 @@ func TestRevokeCertByKey_Moz(t *testing.T) {
test.AssertEquals(t, len(mockSA.blocked[0].Comment), 0)
test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)], int64(ocsp.KeyCompromise))

// Re-revoking should fail, because re-revocation is not allowed.
_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
Cert: cert.Raw,
})
test.AssertError(t, err, "should have failed")

// Enable re-revocation.
_ = features.Set(map[string]bool{
features.MozRevocationReasons.String(): true,
features.AllowReRevocation.String(): true,
})

// Re-revoking should fail, because it is already revoked for keyCompromise.
_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
Cert: cert.Raw,
})
test.AssertError(t, err, "should have failed")

// Reset, revoke for some other reason, and try again.
// Reset and have the Subscriber revoke for a different reason.
// Then re-revoking using the key should work.
mockSA.revoked = make(map[string]int64)
_, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{
Cert: cert.Raw,
Expand All @@ -3968,10 +3994,6 @@ func TestRevokeCertByKey_Moz(t *testing.T) {
Cert: cert.Raw,
})
test.AssertNotError(t, err, "should have succeeded")
_, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{
Cert: cert.Raw,
})
test.AssertError(t, err, "should have failed")
}

func TestAdministrativelyRevokeCertificate(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions test/config-next/ra.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"StoreRevokerInfo": true,
"RestrictRSAKeySizes": true,
"StreamlineOrderAndAuthzs": true,
"AllowReRevocation": true,
"MozRevocationReasons": true
},
"CTLogGroups2": [
Expand Down
6 changes: 5 additions & 1 deletion test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def ocsp_verify(cert_file, issuer_file, ocsp_response):
raise(Exception("OCSP verify failure"))
return output

def verify_ocsp(cert_file, issuer_file, url, status="revoked"):
def verify_ocsp(cert_file, issuer_file, url, status="revoked", reason=None):
ocsp_request = make_ocsp_req(cert_file, issuer_file)
responses = fetch_ocsp(ocsp_request, url)

Expand All @@ -114,6 +114,10 @@ def verify_ocsp(cert_file, issuer_file, url, status="revoked"):
if not re.search("%s: %s" % (cert_file, status), verify_output):
print(verify_output)
raise(Exception("OCSP response wasn't '%s'" % status))
if reason is not None:
if not re.search("Reason: %s" % reason, verify_output):
print(verify_output)
raise(Exception("OCSP response wasn't '%s'" % reason))
return verify_output

def reset_akamai_purges():
Expand Down
Loading