Skip to content

Commit b5d58b7

Browse files
committed
SA: Deprecate IgnoreAccountContacts feature flag
1 parent afff84e commit b5d58b7

File tree

14 files changed

+50
-253
lines changed

14 files changed

+50
-253
lines changed

cmd/contact-auditor/main_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/jmhodges/clock"
12+
1213
corepb "github.com/letsencrypt/boulder/core/proto"
1314
"github.com/letsencrypt/boulder/db"
1415
blog "github.com/letsencrypt/boulder/log"
@@ -33,6 +34,11 @@ const (
3334
)
3435

3536
func TestContactAuditor(t *testing.T) {
37+
// Leave this technically in place until contact-auditor is fully deleted, but
38+
// this test cannot function now that the SA never stores nor retrieves
39+
// contacts.
40+
t.Skip()
41+
3642
testCtx := setup(t)
3743
defer testCtx.cleanUp()
3844

cmd/expiration-mailer/main_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,11 @@ func TestProcessCertsConnectError(t *testing.T) {
417417
}
418418

419419
func TestFindExpiringCertificates(t *testing.T) {
420+
// Leave this technically in place until expiration-mailer is fully deleted,
421+
// but this test cannot function now that the SA never stores nor retrieves
422+
// contacts.
423+
t.Skip()
424+
420425
testCtx := setup(t, []time.Duration{time.Hour * 24, time.Hour * 24 * 4, time.Hour * 24 * 7})
421426

422427
addExpiringCerts(t, testCtx)
@@ -620,6 +625,11 @@ func countGroupsAtCapacity(group string, counter *prometheus.GaugeVec) int {
620625
}
621626

622627
func TestFindCertsAtCapacity(t *testing.T) {
628+
// Leave this technically in place until expiration-mailer is fully deleted,
629+
// but this test cannot function now that the SA never stores nor retrieves
630+
// contacts.
631+
t.Skip()
632+
623633
testCtx := setup(t, []time.Duration{time.Hour * 24})
624634

625635
addExpiringCerts(t, testCtx)
@@ -776,6 +786,11 @@ func TestCertIsRenewed(t *testing.T) {
776786
}
777787

778788
func TestLifetimeOfACert(t *testing.T) {
789+
// Leave this technically in place until expiration-mailer is fully deleted,
790+
// but this test cannot function now that the SA never stores nor retrieves
791+
// contacts.
792+
t.Skip()
793+
779794
testCtx := setup(t, []time.Duration{time.Hour * 24, time.Hour * 24 * 4, time.Hour * 24 * 7})
780795
defer testCtx.cleanUp()
781796

@@ -882,6 +897,11 @@ func TestDontFindRevokedCert(t *testing.T) {
882897
}
883898

884899
func TestDedupOnRegistration(t *testing.T) {
900+
// Leave this technically in place until expiration-mailer is fully deleted,
901+
// but this test cannot function now that the SA never stores nor retrieves
902+
// contacts.
903+
t.Skip()
904+
885905
expiresIn := 96 * time.Hour
886906
testCtx := setup(t, []time.Duration{expiresIn})
887907

cmd/id-exporter/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/jmhodges/clock"
15+
1516
"github.com/letsencrypt/boulder/cmd"
1617
"github.com/letsencrypt/boulder/db"
1718
"github.com/letsencrypt/boulder/features"
@@ -77,8 +78,7 @@ func (c idExporter) findIDs(ctx context.Context) (idExporterResults, error) {
7778
`SELECT DISTINCT r.id
7879
FROM registrations AS r
7980
INNER JOIN certificates AS c on c.registrationID = r.id
80-
WHERE r.contact NOT IN ('[]', 'null')
81-
AND c.expires >= :expireCutoff;`,
81+
WHERE c.expires >= :expireCutoff;`,
8282
map[string]interface{}{
8383
"expireCutoff": c.clk.Now().Add(-c.grace),
8484
})

features/features.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type Config struct {
2525
EnforceMPIC bool
2626
MPICFullResults bool
2727
UnsplitIssuance bool
28+
IgnoreAccountContacts bool
2829

2930
// ServeRenewalInfo exposes the renewalInfo endpoint in the directory and for
3031
// GET requests. WARNING: This feature is a draft and highly unstable.
@@ -85,10 +86,6 @@ type Config struct {
8586
// StoreARIReplacesInOrders causes the SA to store and retrieve the optional
8687
// ARI replaces field in the orders table.
8788
StoreARIReplacesInOrders bool
88-
89-
// IgnoreAccountContacts causes the SA to omit the contacts column when
90-
// creating new account rows, and when retrieving existing account rows.
91-
IgnoreAccountContacts bool
9289
}
9390

9491
var fMu = new(sync.RWMutex)

ra/ra_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,7 @@ func TestNewRegistration(t *testing.T) {
485485
t.Fatalf("could not create new registration: %s", err)
486486
}
487487
test.AssertByteEquals(t, result.Key, acctKeyB)
488-
test.Assert(t, len(result.Contact) == 1, "Wrong number of contacts")
489-
test.Assert(t, mailto == (result.Contact)[0], "Contact didn't match")
488+
test.Assert(t, len(result.Contact) == 0, "Wrong number of contacts")
490489
test.Assert(t, result.Agreement == "", "Agreement didn't default empty")
491490

492491
reg, err := sa.GetRegistration(ctx, &sapb.RegistrationID{Id: result.Id})

sa/model.go

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
corepb "github.com/letsencrypt/boulder/core/proto"
2525
"github.com/letsencrypt/boulder/db"
2626
berrors "github.com/letsencrypt/boulder/errors"
27-
"github.com/letsencrypt/boulder/features"
2827
"github.com/letsencrypt/boulder/grpc"
2928
"github.com/letsencrypt/boulder/identifier"
3029
"github.com/letsencrypt/boulder/probs"
@@ -61,7 +60,7 @@ func badJSONError(msg string, jsonData []byte, err error) error {
6160
}
6261
}
6362

64-
const regFields = "id, jwk, jwk_sha256, contact, agreement, createdAt, LockCol, status"
63+
const regFields = "id, jwk, jwk_sha256, agreement, createdAt, LockCol, status"
6564

6665
// ClearEmail removes the provided email address from one specified registration. If
6766
// there are multiple email addresses present, it does not modify other ones. If the email
@@ -273,11 +272,13 @@ type regModel struct {
273272
ID int64 `db:"id"`
274273
Key []byte `db:"jwk"`
275274
KeySHA256 string `db:"jwk_sha256"`
276-
Contact string `db:"contact"`
277275
Agreement string `db:"agreement"`
278276
CreatedAt time.Time `db:"createdAt"`
279277
LockCol int64
280278
Status string `db:"status"`
279+
// Deprecated: never populated from the database, and always written to the
280+
// database as just "[]".
281+
Contact string `db:"contact"`
281282
}
282283

283284
func registrationPbToModel(reg *corepb.Registration) (*regModel, error) {
@@ -294,18 +295,6 @@ func registrationPbToModel(reg *corepb.Registration) (*regModel, error) {
294295
return nil, err
295296
}
296297

297-
// We don't want to write literal JSON "null" strings into the database if the
298-
// list of contact addresses is empty. Replace any possibly-`nil` slice with
299-
// an empty JSON array. We don't need to check reg.ContactPresent, because
300-
// we're going to write the whole object to the database anyway.
301-
jsonContact := []byte("[]")
302-
if len(reg.Contact) != 0 && !features.Get().IgnoreAccountContacts {
303-
jsonContact, err = json.Marshal(reg.Contact)
304-
if err != nil {
305-
return nil, err
306-
}
307-
}
308-
309298
var createdAt time.Time
310299
if !core.IsAnyNilOrZero(reg.CreatedAt) {
311300
createdAt = reg.CreatedAt.AsTime()
@@ -315,7 +304,7 @@ func registrationPbToModel(reg *corepb.Registration) (*regModel, error) {
315304
ID: reg.Id,
316305
Key: reg.Key,
317306
KeySHA256: sha,
318-
Contact: string(jsonContact),
307+
Contact: "[]",
319308
Agreement: reg.Agreement,
320309
CreatedAt: createdAt,
321310
Status: reg.Status,
@@ -327,18 +316,9 @@ func registrationModelToPb(reg *regModel) (*corepb.Registration, error) {
327316
return nil, errors.New("incomplete Registration retrieved from DB")
328317
}
329318

330-
contact := []string{}
331-
if len(reg.Contact) > 0 && !features.Get().IgnoreAccountContacts {
332-
err := json.Unmarshal([]byte(reg.Contact), &contact)
333-
if err != nil {
334-
return nil, err
335-
}
336-
}
337-
338319
return &corepb.Registration{
339320
Id: reg.ID,
340321
Key: reg.Key,
341-
Contact: contact,
342322
Agreement: reg.Agreement,
343323
CreatedAt: timestamppb.New(reg.CreatedAt.UTC()),
344324
Status: reg.Status,

sa/model_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ func TestRegistrationModelToPb(t *testing.T) {
5353
test.AssertNotError(t, err, "Should pass")
5454
}
5555

56-
func TestRegistrationPbToModel(t *testing.T) {}
57-
5856
func TestAuthzModel(t *testing.T) {
5957
// newTestAuthzPB returns a new *corepb.Authorization for `example.com` that
6058
// is valid, and contains a single valid HTTP-01 challenge. These are the

sa/sa_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func TestAddRegistration(t *testing.T) {
201201
t.Fatalf("Couldn't create new registration: %s", err)
202202
}
203203
test.Assert(t, reg.Id != 0, "ID shouldn't be 0")
204-
test.AssertDeepEquals(t, reg.Contact, contacts)
204+
test.AssertEquals(t, len(reg.Contact), 0)
205205

206206
_, err = sa.GetRegistration(ctx, &sapb.RegistrationID{Id: 0})
207207
test.AssertError(t, err, "Registration object for ID 0 was returned")
@@ -4461,6 +4461,7 @@ func newAcctKey(t *testing.T) []byte {
44614461
}
44624462

44634463
func TestUpdateRegistrationContact(t *testing.T) {
4464+
// TODO(#8199): Delete this.
44644465
sa, _, cleanUp := initSA(t)
44654466
defer cleanUp()
44664467

@@ -4517,13 +4518,13 @@ func TestUpdateRegistrationContact(t *testing.T) {
45174518
})
45184519
test.AssertNotError(t, err, "unexpected error for UpdateRegistrationContact()")
45194520
test.AssertEquals(t, updatedReg.Id, reg.Id)
4520-
test.AssertDeepEquals(t, updatedReg.Contact, tt.newContacts)
4521+
test.AssertEquals(t, len(updatedReg.Contact), 0)
45214522

45224523
refetchedReg, err := sa.GetRegistration(ctx, &sapb.RegistrationID{
45234524
Id: reg.Id,
45244525
})
45254526
test.AssertNotError(t, err, "retrieving registration")
4526-
test.AssertDeepEquals(t, refetchedReg.Contact, tt.newContacts)
4527+
test.AssertEquals(t, len(refetchedReg.Contact), 0)
45274528
})
45284529
}
45294530
}

test/config-next/sa.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@
4949
},
5050
"healthCheckInterval": "4s",
5151
"features": {
52-
"StoreARIReplacesInOrders": true,
53-
"IgnoreAccountContacts": true
52+
"StoreARIReplacesInOrders": true
5453
}
5554
},
5655
"syslog": {

test/config/sa.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
},
5252
"features": {
5353
"MultipleCertificateProfiles": true,
54-
"InsertAuthzsIndividually": true
54+
"InsertAuthzsIndividually": true,
55+
"IgnoreAccountContacts": true
5556
}
5657
},
5758
"syslog": {

test/integration/account_test.go

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"crypto/ecdsa"
77
"crypto/elliptic"
88
"crypto/rand"
9-
"os"
10-
"slices"
119
"strings"
1210
"testing"
1311

@@ -68,17 +66,9 @@ func TestNewAccount(t *testing.T) {
6866
t.Fatalf("NewAccount(tos: %t, contact: %#v) = %s, but want no err", tc.tos, tc.contact, err)
6967
}
7068

71-
// In config-next, we're wholly ignoring account contacts
72-
if strings.Contains(os.Getenv("BOULDER_CONFIG_DIR"), "config-next") {
73-
if len(acct.Contact) != 0 {
74-
t.Errorf("NewAccount(tos: %t, contact: %#v) = %#v, but want empty contacts", tc.tos, tc.contact, acct)
75-
}
76-
} else {
77-
if !slices.Equal(acct.Contact, tc.contact) {
78-
t.Errorf("NewAccount(tos: %t, contact: %#v) = %#v, but want contacts %q", tc.tos, tc.contact, acct, tc.contact)
79-
}
69+
if len(acct.Contact) != 0 {
70+
t.Errorf("NewAccount(tos: %t, contact: %#v) = %#v, but want empty contacts", tc.tos, tc.contact, acct)
8071
}
81-
8272
} else if tc.wantErr != "" {
8373
if err == nil {
8474
t.Fatalf("NewAccount(tos: %t, contact: %#v) = %#v, but want error %q", tc.tos, tc.contact, acct, tc.wantErr)
@@ -177,44 +167,4 @@ func TestAccountDeactivate(t *testing.T) {
177167
if got.Status != string(core.StatusDeactivated) {
178168
t.Errorf("account deactivation should have set status to %q, instead got %q", core.StatusDeactivated, got.Status)
179169
}
180-
181-
// TODO(#5554): Check that the contacts have been cleared. We can't do this
182-
// today because eggsampler/acme unmarshals the WFE's response into the same
183-
// account object as it used to make the request, and a wholly missing
184-
// contacts field doesn't overwrite whatever eggsampler was holding in memory.
185-
}
186-
187-
func TestAccountUpdate_UnspecifiedContacts(t *testing.T) {
188-
t.Parallel()
189-
190-
c, err := acme.NewClient("http://boulder.service.consul:4001/directory")
191-
if err != nil {
192-
t.Fatalf("failed to connect to acme directory: %s", err)
193-
}
194-
195-
acctKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
196-
if err != nil {
197-
t.Fatalf("failed to generate account key: %s", err)
198-
}
199-
200-
acct, err := c.NewAccount(acctKey, false, true, "mailto:example@"+random_domain())
201-
if err != nil {
202-
t.Fatalf("failed to create initial account: %s", err)
203-
}
204-
205-
// This request does not include the Contact field, meaning that the contacts
206-
// should remain unchanged (i.e. not be removed).
207-
acct, err = c.UpdateAccount(acct)
208-
if err != nil {
209-
t.Errorf("failed to no-op update account: %s", err)
210-
}
211-
if strings.Contains(os.Getenv("BOULDER_CONFIG_DIR"), "config-next") {
212-
if len(acct.Contact) != 0 {
213-
t.Errorf("unexpected number of contacts: want 0, got %d", len(acct.Contact))
214-
}
215-
} else {
216-
if len(acct.Contact) != 1 {
217-
t.Errorf("unexpected number of contacts: want 1, got %d", len(acct.Contact))
218-
}
219-
}
220170
}

test/integration/admin_test.go

Lines changed: 0 additions & 66 deletions
This file was deleted.

0 commit comments

Comments
 (0)