Skip to content

Commit

Permalink
wfe: Use separate UpdateRegistrationContact & UpdateRegistrationKey m…
Browse files Browse the repository at this point in the history
…ethods (#7827)

Fixes #7716
Part of #5554
  • Loading branch information
jprenken authored Dec 13, 2024
1 parent efaa370 commit 62f1a26
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 64 deletions.
2 changes: 1 addition & 1 deletion test/integration/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestAccountEmailError(t *testing.T) {
longStringBuf.WriteString("@a.com")

createErrorPrefix := "Error creating new account :: "
updateErrorPrefix := "Unable to update account :: "
updateErrorPrefix := "Unable to update account :: invalid contact: "

testCases := []struct {
name string
Expand Down
72 changes: 18 additions & 54 deletions wfe2/wfe.go
Original file line number Diff line number Diff line change
Expand Up @@ -1442,8 +1442,8 @@ func (wfe *WebFrontEndImpl) Account(

// updateAccount unmarshals an account update request from the provided
// requestBody to update the given registration. Important: It is assumed the
// request has already been authenticated by the caller. If the request is
// a valid update the resulting updated account is returned, otherwise a problem
// request has already been authenticated by the caller. If the request is a
// valid update the resulting updated account is returned, otherwise a problem
// is returned.
func (wfe *WebFrontEndImpl) updateAccount(
ctx context.Context,
Expand All @@ -1461,56 +1461,29 @@ func (wfe *WebFrontEndImpl) updateAccount(
return nil, probs.Malformed("Error unmarshaling account")
}

// Convert existing account to corepb.Registration
basePb, err := bgrpc.RegistrationToPB(*currAcct)
if err != nil {
return nil, probs.ServerInternal("Error updating account")
}

var contacts []string
var contactsPresent bool
if accountUpdateRequest.Contact != nil {
contactsPresent = true
contacts = *accountUpdateRequest.Contact
}

// Copy over the fields from the request to the registration object used for
// the RA updates.
// Create corepb.Registration from provided account information
updatePb := &corepb.Registration{
Contact: contacts,
ContactsPresent: contactsPresent,
Status: string(accountUpdateRequest.Status),
}

// People *will* POST their full accounts to this endpoint, including
// the 'valid' status, to avoid always failing out when that happens only
// attempt to deactivate if the provided status is different from their current
// status.
//
// If a user tries to send both a deactivation request and an update to their
// contacts or subscriber agreement URL the deactivation will take place and
// return before an update would be performed.
if updatePb.Status != "" && updatePb.Status != basePb.Status {
if updatePb.Status != string(core.StatusDeactivated) {
return nil, probs.Malformed("Invalid value provided for status field")
}
_, err := wfe.ra.DeactivateRegistration(ctx, basePb)
// If a user tries to send both a deactivation request and an update to
// their contacts, the deactivation will take place and return before an
// update would be performed. Deactivation deletes the contacts field.
if accountUpdateRequest.Status == core.StatusDeactivated {
_, err = wfe.ra.DeactivateRegistration(ctx, &corepb.Registration{Id: currAcct.ID, Status: string(core.StatusDeactivated)})
if err != nil {
return nil, web.ProblemDetailsForError(err, "Unable to deactivate account")
}

currAcct.Status = core.StatusDeactivated
return currAcct, nil
}

// Account objects contain a JWK object which are merged in UpdateRegistration
// if it is different from the existing account key. Since this isn't how you
// update the key we just copy the existing one into the update object here. This
// ensures the key isn't changed and that we can cleanly serialize the update as
// JSON to send via RPC to the RA.
updatePb.Key = basePb.Key
if accountUpdateRequest.Status != core.StatusValid && accountUpdateRequest.Status != "" {
return nil, probs.Malformed("Invalid value provided for status field")
}

updatedAcct, err := wfe.ra.UpdateRegistration(ctx, &rapb.UpdateRegistrationRequest{Base: basePb, Update: updatePb})
var contacts []string
if accountUpdateRequest.Contact != nil {
contacts = *accountUpdateRequest.Contact
}

updatedAcct, err := wfe.ra.UpdateRegistrationContact(ctx, &rapb.UpdateRegistrationContactRequest{RegistrationID: currAcct.ID, Contacts: contacts})
if err != nil {
return nil, web.ProblemDetailsForError(err, "Unable to update account")
}
Expand Down Expand Up @@ -1993,18 +1966,9 @@ func (wfe *WebFrontEndImpl) KeyRollover(
wfe.sendError(response, logEvent, web.ProblemDetailsForError(err, "Failed to lookup existing keys"), err)
return
}
// Convert account to proto for grpc
regPb, err := bgrpc.RegistrationToPB(*acct)
if err != nil {
wfe.sendError(response, logEvent, probs.ServerInternal("Error marshaling Registration to proto"), err)
return
}

// Copy new key into an empty registration to provide as the update
updatePb := &corepb.Registration{Key: newKeyBytes}

// Update the account key to the new key
updatedAcctPb, err := wfe.ra.UpdateRegistration(ctx, &rapb.UpdateRegistrationRequest{Base: regPb, Update: updatePb})
updatedAcctPb, err := wfe.ra.UpdateRegistrationKey(ctx, &rapb.UpdateRegistrationKeyRequest{RegistrationID: acct.ID, Jwk: newKeyBytes})
if err != nil {
if errors.Is(err, berrors.Duplicate) {
// It is possible that between checking for the existing key, and performing the update
Expand Down
19 changes: 10 additions & 9 deletions wfe2/wfe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,15 @@ func (ra *MockRegistrationAuthority) NewRegistration(ctx context.Context, in *co
return in, nil
}

func (ra *MockRegistrationAuthority) UpdateRegistration(ctx context.Context, in *rapb.UpdateRegistrationRequest, _ ...grpc.CallOption) (*corepb.Registration, error) {
if !bytes.Equal(in.Base.Key, in.Update.Key) {
in.Base.Key = in.Update.Key
}
return in.Base, nil
func (ra *MockRegistrationAuthority) UpdateRegistrationContact(ctx context.Context, in *rapb.UpdateRegistrationContactRequest, _ ...grpc.CallOption) (*corepb.Registration, error) {
return &corepb.Registration{
Contact: in.Contacts,
Key: []byte(test1KeyPublicJSON),
}, nil
}

func (ra *MockRegistrationAuthority) UpdateRegistrationKey(ctx context.Context, in *rapb.UpdateRegistrationKeyRequest, _ ...grpc.CallOption) (*corepb.Registration, error) {
return &corepb.Registration{Key: in.Jwk}, nil
}

func (ra *MockRegistrationAuthority) PerformValidation(context.Context, *rapb.PerformValidationRequest, ...grpc.CallOption) (*corepb.Authorization, error) {
Expand Down Expand Up @@ -3211,10 +3215,7 @@ func TestKeyRollover(t *testing.T) {
Payload: `{"oldKey":` + test1KeyPublicJSON + `,"account":"http://localhost/acme/acct/1"}`,
ExpectedResponse: `{
"key": ` + string(newJWKJSON) + `,
"contact": [
"mailto:person@mail.com"
],
"status": "valid"
"status": ""
}`,
NewKey: newKeyPriv,
},
Expand Down

0 comments on commit 62f1a26

Please sign in to comment.