1 package notmain
2
3 import (
4 "context"
5 "fmt"
6 "net"
7 "os"
8 "strings"
9 "testing"
10 "time"
11
12 "github.com/jmhodges/clock"
13 corepb "github.com/letsencrypt/boulder/core/proto"
14 "github.com/letsencrypt/boulder/db"
15 blog "github.com/letsencrypt/boulder/log"
16 "github.com/letsencrypt/boulder/metrics"
17 "github.com/letsencrypt/boulder/sa"
18 "github.com/letsencrypt/boulder/test"
19 "github.com/letsencrypt/boulder/test/vars"
20 )
21
22 var (
23 regA *corepb.Registration
24 regB *corepb.Registration
25 regC *corepb.Registration
26 regD *corepb.Registration
27 )
28
29 const (
30 emailARaw = "test@example.com"
31 emailBRaw = "example@notexample.com"
32 emailCRaw = "test-example@notexample.com"
33 telNum = "666-666-7777"
34 )
35
36 func TestContactAuditor(t *testing.T) {
37 testCtx := setup(t)
38 defer testCtx.cleanUp()
39
40
41 testCtx.addRegistrations(t)
42
43 resChan := make(chan *result, 10)
44 err := testCtx.c.run(context.Background(), resChan)
45 test.AssertNotError(t, err, "received error")
46
47
48 test.AssertEquals(t, len(resChan), 4)
49 for entry := range resChan {
50 err := validateContacts(entry.id, entry.createdAt, entry.contacts)
51 switch entry.id {
52 case regA.Id:
53
54 test.AssertDeepEquals(t, entry.contacts, []string{"mailto:test@example.com"})
55 test.AssertError(t, err, "failed to error on a contact that violates our e-mail policy")
56 case regB.Id:
57
58 test.AssertDeepEquals(t, entry.contacts, []string{"mailto:example@notexample.com"})
59 test.AssertNotError(t, err, "received error for a valid contact entry")
60 case regC.Id:
61
62 test.AssertDeepEquals(t, entry.contacts, []string{"mailto:test-example@notexample.com"})
63 test.AssertNotError(t, err, "received error for a valid contact entry")
64
65
66 _, err := unmarshalContact([]byte("[ mailto:test@example.com ]"))
67 test.AssertError(t, err, "failed to error while unmarshaling invalid Contact JSON")
68
69
70
71 contacts, err := unmarshalContact([]byte(`[ "mailto:test@example.com", "tel:666-666-7777" ]`))
72 test.AssertNotError(t, err, "received error while unmarshaling valid Contact JSON")
73
74
75 err = validateContacts(entry.id, entry.createdAt, contacts)
76 test.AssertError(t, err, "failed to error on 2 invalid Contact entries")
77 case regD.Id:
78 test.AssertDeepEquals(t, entry.contacts, []string{"tel:666-666-7777"})
79 test.AssertError(t, err, "failed to error on an invalid contact entry")
80 default:
81 t.Errorf("ID: %d was not expected", entry.id)
82 }
83 }
84
85
86 data, err := os.ReadFile(testCtx.c.resultsFile.Name())
87 if err != nil {
88 t.Error(err)
89 }
90
91
92 contentLines := strings.Split(strings.TrimRight(string(data), "\n"), "\n")
93 test.AssertEquals(t, len(contentLines), 2)
94
95
96 for _, line := range contentLines {
97 test.AssertEquals(t, len(strings.Split(line, "\t")), 6)
98 }
99 }
100
101 type testCtx struct {
102 c contactAuditor
103 dbMap *db.WrappedMap
104 ssa *sa.SQLStorageAuthority
105 cleanUp func()
106 }
107
108 func (tc testCtx) addRegistrations(t *testing.T) {
109 emailA := "mailto:" + emailARaw
110 emailB := "mailto:" + emailBRaw
111 emailC := "mailto:" + emailCRaw
112 tel := "tel:" + telNum
113
114
115 jsonKeyA := []byte(`{
116 "kty":"RSA",
117 "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
118 "e":"AQAB"
119 }`)
120 jsonKeyB := []byte(`{
121 "kty":"RSA",
122 "n":"z8bp-jPtHt4lKBqepeKF28g_QAEOuEsCIou6sZ9ndsQsEjxEOQxQ0xNOQezsKa63eogw8YS3vzjUcPP5BJuVzfPfGd5NVUdT-vSSwxk3wvk_jtNqhrpcoG0elRPQfMVsQWmxCAXCVRz3xbcFI8GTe-syynG3l-g1IzYIIZVNI6jdljCZML1HOMTTW4f7uJJ8mM-08oQCeHbr5ejK7O2yMSSYxW03zY-Tj1iVEebROeMv6IEEJNFSS4yM-hLpNAqVuQxFGetwtwjDMC1Drs1dTWrPuUAAjKGrP151z1_dE74M5evpAhZUmpKv1hY-x85DC6N0hFPgowsanmTNNiV75w",
123 "e":"AAEAAQ"
124 }`)
125 jsonKeyC := []byte(`{
126 "kty":"RSA",
127 "n":"rFH5kUBZrlPj73epjJjyCxzVzZuV--JjKgapoqm9pOuOt20BUTdHqVfC2oDclqM7HFhkkX9OSJMTHgZ7WaVqZv9u1X2yjdx9oVmMLuspX7EytW_ZKDZSzL-sCOFCuQAuYKkLbsdcA3eHBK_lwc4zwdeHFMKIulNvLqckkqYB9s8GpgNXBDIQ8GjR5HuJke_WUNjYHSd8jY1LU9swKWsLQe2YoQUz_ekQvBvBCoaFEtrtRaSJKNLIVDObXFr2TLIiFiM0Em90kK01-eQ7ZiruZTKomll64bRFPoNo4_uwubddg3xTqur2vdF3NyhTrYdvAgTem4uC0PFjEQ1bK_djBQ",
128 "e":"AQAB"
129 }`)
130 jsonKeyD := []byte(`{
131 "kty":"RSA",
132 "n":"rFH5kUBZrlPj73epjJjyCxzVzZuV--JjKgapoqm9pOuOt20BUTdHqVfC2oDclqM7HFhkkX9OSJMTHgZ7WaVqZv9u1X2yjdx9oVmMLuspX7EytW_ZKDZSzL-FCOFCuQAuYKkLbsdcA3eHBK_lwc4zwdeHFMKIulNvLqckkqYB9s8GpgNXBDIQ8GjR5HuJke_WUNjYHSd8jY1LU9swKWsLQe2YoQUz_ekQvBvBCoaFEtrtRaSJKNLIVDObXFr2TLIiFiM0Em90kK01-eQ7ZiruZTKomll64bRFPoNo4_uwubddg3xTqur2vdF3NyhTrYdvAgTem4uC0PFjEQ1bK_djBQ",
133 "e":"AQAB"
134 }`)
135
136 initialIP, err := net.ParseIP("127.0.0.1").MarshalText()
137 test.AssertNotError(t, err, "Couldn't create initialIP")
138
139 regA = &corepb.Registration{
140 Id: 1,
141 Contact: []string{emailA},
142 Key: jsonKeyA,
143 InitialIP: initialIP,
144 }
145 regB = &corepb.Registration{
146 Id: 2,
147 Contact: []string{emailB},
148 Key: jsonKeyB,
149 InitialIP: initialIP,
150 }
151 regC = &corepb.Registration{
152 Id: 3,
153 Contact: []string{emailC},
154 Key: jsonKeyC,
155 InitialIP: initialIP,
156 }
157
158 regD = &corepb.Registration{
159 Id: 4,
160 Contact: []string{tel},
161 Key: jsonKeyD,
162 InitialIP: initialIP,
163 }
164
165
166 ctx := context.Background()
167 regA, err = tc.ssa.NewRegistration(ctx, regA)
168 test.AssertNotError(t, err, "Couldn't store regA")
169 regB, err = tc.ssa.NewRegistration(ctx, regB)
170 test.AssertNotError(t, err, "Couldn't store regB")
171 regC, err = tc.ssa.NewRegistration(ctx, regC)
172 test.AssertNotError(t, err, "Couldn't store regC")
173 regD, err = tc.ssa.NewRegistration(ctx, regD)
174 test.AssertNotError(t, err, "Couldn't store regD")
175 }
176
177 func setup(t *testing.T) testCtx {
178 log := blog.UseMock()
179
180
181
182 dbMap, err := sa.DBMapForTest(vars.DBConnSAFullPerms)
183 if err != nil {
184 t.Fatalf("Couldn't connect to the database: %s", err)
185 }
186
187
188 file, err := os.CreateTemp("", fmt.Sprintf("audit-%s", time.Now().Format("2006-01-02T15:04")))
189 if err != nil {
190 t.Fatal(err)
191 }
192
193 cleanUp := func() {
194 test.ResetBoulderTestDatabase(t)
195 file.Close()
196 os.Remove(file.Name())
197 }
198
199 db, err := sa.DBMapForTest(vars.DBConnSAMailer)
200 if err != nil {
201 t.Fatalf("Couldn't connect to the database: %s", err)
202 }
203
204 ssa, err := sa.NewSQLStorageAuthority(dbMap, dbMap, nil, 1, 0, clock.New(), log, metrics.NoopRegisterer)
205 if err != nil {
206 t.Fatalf("unable to create SQLStorageAuthority: %s", err)
207 }
208
209 return testCtx{
210 c: contactAuditor{
211 db: db,
212 resultsFile: file,
213 logger: blog.NewMock(),
214 },
215 dbMap: dbMap,
216 ssa: ssa,
217 cleanUp: cleanUp,
218 }
219 }
220
View as plain text