config_test.go raw
1 package test
2
3 import (
4 "testing"
5
6 "github.com/stretchr/testify/assert"
7 "github.com/stretchr/testify/require"
8
9 "github.com/getAlby/hub/config"
10 "github.com/getAlby/hub/tests"
11 )
12
13 func TestCheckUnlockPasswordCache_InvalidSecond(t *testing.T) {
14 unlockPassword := "123"
15 svc, err := tests.CreateTestServiceWithMnemonic(t, "", unlockPassword)
16 require.NoError(t, err)
17 defer svc.Remove()
18
19 err = svc.Cfg.SaveUnlockPasswordCheck(unlockPassword)
20 require.NoError(t, err)
21
22 value, err := svc.Cfg.Get("UnlockPasswordCheck", unlockPassword)
23 require.NoError(t, err)
24 require.Equal(t, "THIS STRING SHOULD MATCH IF PASSWORD IS CORRECT", value)
25
26 assert.True(t, svc.Cfg.CheckUnlockPassword(unlockPassword))
27 assert.False(t, svc.Cfg.CheckUnlockPassword(unlockPassword+"1"))
28 assert.False(t, svc.Cfg.CheckUnlockPassword(""))
29 }
30 func TestCheckUnlockPasswordCache_InvalidFirst(t *testing.T) {
31 unlockPassword := "123"
32 svc, err := tests.CreateTestServiceWithMnemonic(t, "", unlockPassword)
33 require.NoError(t, err)
34 defer svc.Remove()
35
36 err = svc.Cfg.SaveUnlockPasswordCheck(unlockPassword)
37 require.NoError(t, err)
38
39 value, err := svc.Cfg.Get("UnlockPasswordCheck", unlockPassword)
40 require.NoError(t, err)
41 require.Equal(t, "THIS STRING SHOULD MATCH IF PASSWORD IS CORRECT", value)
42
43 value, err = svc.Cfg.Get("UnlockPasswordCheck", unlockPassword+"1")
44 require.Error(t, err)
45
46 assert.False(t, svc.Cfg.CheckUnlockPassword(""))
47 assert.False(t, svc.Cfg.CheckUnlockPassword(unlockPassword+"1"))
48 assert.True(t, svc.Cfg.CheckUnlockPassword(unlockPassword))
49 }
50
51 func TestCheckUnlockPassword_ChangePassword(t *testing.T) {
52 unlockPassword := "123"
53 svc, err := tests.CreateTestServiceWithMnemonic(t, "", unlockPassword)
54 require.NoError(t, err)
55 defer svc.Remove()
56
57 err = svc.Cfg.SaveUnlockPasswordCheck(unlockPassword)
58 require.NoError(t, err)
59
60 value, err := svc.Cfg.Get("UnlockPasswordCheck", unlockPassword)
61 require.NoError(t, err)
62 require.Equal(t, "THIS STRING SHOULD MATCH IF PASSWORD IS CORRECT", value)
63
64 assert.True(t, svc.Cfg.CheckUnlockPassword(unlockPassword))
65
66 newUnlockPassword := "1234"
67
68 err = svc.Cfg.ChangeUnlockPassword(unlockPassword, newUnlockPassword)
69 require.NoError(t, err)
70
71 assert.False(t, svc.Cfg.CheckUnlockPassword(unlockPassword))
72 assert.True(t, svc.Cfg.CheckUnlockPassword(newUnlockPassword))
73 // test caching
74 assert.False(t, svc.Cfg.CheckUnlockPassword(unlockPassword))
75 assert.True(t, svc.Cfg.CheckUnlockPassword(newUnlockPassword))
76 }
77
78 func TestCheckUnlockPassword_MissingCanaryFailsClosed(t *testing.T) {
79 svc, err := tests.CreateTestService(t)
80 require.NoError(t, err)
81 defer svc.Remove()
82
83 // A fresh hub has not saved the unlock-password canary yet.
84 set, err := svc.Cfg.IsUnlockPasswordCheckSet()
85 require.NoError(t, err)
86 assert.False(t, set)
87
88 // Without the canary, no password may validate - including an empty one.
89 assert.False(t, svc.Cfg.CheckUnlockPassword(""))
90 assert.False(t, svc.Cfg.CheckUnlockPassword("any-password"))
91
92 // After the canary is saved, only the correct password validates.
93 err = svc.Cfg.SaveUnlockPasswordCheck("correct")
94 require.NoError(t, err)
95
96 set, err = svc.Cfg.IsUnlockPasswordCheckSet()
97 require.NoError(t, err)
98 assert.True(t, set)
99
100 assert.True(t, svc.Cfg.CheckUnlockPassword("correct"))
101 assert.False(t, svc.Cfg.CheckUnlockPassword("wrong"))
102 assert.False(t, svc.Cfg.CheckUnlockPassword(""))
103 }
104
105 func TestCheckUnlockPassword_NoPasswordHub(t *testing.T) {
106 svc, err := tests.CreateTestService(t)
107 require.NoError(t, err)
108 defer svc.Remove()
109
110 // A hub configured without an unlock password stores the canary unencrypted;
111 // the empty password must still validate after the fail-closed change.
112 err = svc.Cfg.SaveUnlockPasswordCheck("")
113 require.NoError(t, err)
114
115 set, err := svc.Cfg.IsUnlockPasswordCheckSet()
116 require.NoError(t, err)
117 assert.True(t, set)
118
119 assert.True(t, svc.Cfg.CheckUnlockPassword(""))
120 }
121
122 func TestSetIgnore_NoEncryptionKey(t *testing.T) {
123 svc, err := tests.CreateTestService(t)
124 require.NoError(t, err)
125 defer svc.Remove()
126
127 err = svc.Cfg.SetIgnore("key", "value", "")
128 require.NoError(t, err)
129
130 value, err := svc.Cfg.Get("key", "")
131 assert.Equal(t, "value", value)
132
133 err = svc.Cfg.SetIgnore("key", "value2", "")
134 require.NoError(t, err)
135
136 // value should not be updated
137 updatedValue, err := svc.Cfg.Get("key", "")
138 assert.Equal(t, "value", updatedValue)
139 }
140
141 func TestSetIgnore_EncryptionKey(t *testing.T) {
142 svc, err := tests.CreateTestService(t)
143 require.NoError(t, err)
144 defer svc.Remove()
145
146 unlockPassword := "123"
147
148 err = svc.Cfg.SetIgnore("key", "value", unlockPassword)
149 require.NoError(t, err)
150
151 value, err := svc.Cfg.Get("key", unlockPassword)
152 assert.Equal(t, "value", value)
153
154 invalidValue, err := svc.Cfg.Get("key", unlockPassword+"1")
155 assert.Error(t, err)
156 assert.Equal(t, "", invalidValue)
157
158 err = svc.Cfg.SetIgnore("key", "value2", unlockPassword)
159 require.NoError(t, err)
160
161 // value should not be updated
162 updatedValue, err := svc.Cfg.Get("key", unlockPassword)
163 assert.Equal(t, "value", updatedValue)
164 }
165
166 func TestSetUpdate_NoEncryptionKey(t *testing.T) {
167 svc, err := tests.CreateTestService(t)
168 require.NoError(t, err)
169 defer svc.Remove()
170
171 err = svc.Cfg.SetUpdate("key", "value", "")
172 require.NoError(t, err)
173
174 value, err := svc.Cfg.Get("key", "")
175 assert.Equal(t, "value", value)
176
177 err = svc.Cfg.SetUpdate("key", "value2", "")
178 require.NoError(t, err)
179
180 // value should be updated
181 updatedValue, err := svc.Cfg.Get("key", "")
182 assert.Equal(t, "value2", updatedValue)
183 }
184
185 func TestSetUpdate_EncryptionKey(t *testing.T) {
186 svc, err := tests.CreateTestService(t)
187 require.NoError(t, err)
188 defer svc.Remove()
189
190 unlockPassword := "123"
191
192 err = svc.Cfg.SetUpdate("key", "value", unlockPassword)
193 require.NoError(t, err)
194
195 value, err := svc.Cfg.Get("key", unlockPassword)
196 assert.Equal(t, "value", value)
197
198 invalidValue, err := svc.Cfg.Get("key", unlockPassword+"1")
199 assert.Error(t, err)
200 assert.Equal(t, "", invalidValue)
201
202 err = svc.Cfg.SetUpdate("key", "value2", unlockPassword)
203 require.NoError(t, err)
204
205 // value should be updated
206 updatedValue, err := svc.Cfg.Get("key", unlockPassword)
207 assert.Equal(t, "value2", updatedValue)
208 }
209
210 func TestSetUpdate_NoEncryptionKeyToEncryptionKey(t *testing.T) {
211 svc, err := tests.CreateTestService(t)
212 require.NoError(t, err)
213 defer svc.Remove()
214
215 err = svc.Cfg.SetUpdate("key", "value", "")
216 require.NoError(t, err)
217
218 value, err := svc.Cfg.Get("key", "")
219 assert.Equal(t, "value", value)
220
221 unlockPassword := "123"
222
223 err = svc.Cfg.SetUpdate("key", "value2", unlockPassword)
224 require.NoError(t, err)
225
226 // value should be updated
227 updatedValue, err := svc.Cfg.Get("key", unlockPassword)
228 assert.Equal(t, "value2", updatedValue)
229 }
230
231 func TestSetUpdate_EncryptionKeyToNoEncryptionKey(t *testing.T) {
232 svc, err := tests.CreateTestService(t)
233 require.NoError(t, err)
234 defer svc.Remove()
235
236 unlockPassword := "123"
237
238 err = svc.Cfg.SetUpdate("key", "value", unlockPassword)
239 require.NoError(t, err)
240
241 value, err := svc.Cfg.Get("key", unlockPassword)
242 assert.Equal(t, "value", value)
243
244 err = svc.Cfg.SetUpdate("key", "value2", "")
245 require.NoError(t, err)
246
247 // value should be updated
248 updatedValue, err := svc.Cfg.Get("key", "")
249 assert.Equal(t, "value2", updatedValue)
250 }
251
252 func TestJWTSecret_GeneratedOnLoad(t *testing.T) {
253 svc, err := tests.CreateTestService(t)
254 require.NoError(t, err)
255 defer svc.Remove()
256
257 cfg, err := config.NewConfig(&config.AppConfig{}, svc.DB)
258 require.NoError(t, err)
259
260 err = cfg.SaveUnlockPasswordCheck("123")
261 require.NoError(t, err)
262
263 err = cfg.LoadJWTSecret("123")
264 require.NoError(t, err)
265
266 jwtSecret, err := cfg.GetJWTSecret()
267 require.NoError(t, err)
268 assert.NotEmpty(t, jwtSecret)
269
270 encryptedSecret, err := cfg.Get("JWTSecret", "")
271 require.NoError(t, err)
272 decryptedSecret, err := cfg.Get("JWTSecret", "123")
273 require.NoError(t, err)
274 assert.NotEqual(t, encryptedSecret, decryptedSecret)
275
276 // load again without doing anything, ensure the same JWT secret is returned
277 err = cfg.LoadJWTSecret("123")
278 require.NoError(t, err)
279 jwtSecret2, err := cfg.GetJWTSecret()
280 require.NoError(t, err)
281 assert.Equal(t, jwtSecret, jwtSecret2)
282 }
283
284 func TestJWTSecret_WrongPassword(t *testing.T) {
285 svc, err := tests.CreateTestService(t)
286 require.NoError(t, err)
287 defer svc.Remove()
288
289 cfg, err := config.NewConfig(&config.AppConfig{}, svc.DB)
290 require.NoError(t, err)
291
292 err = cfg.SaveUnlockPasswordCheck("123")
293 require.NoError(t, err)
294
295 err = cfg.LoadJWTSecret("123")
296 require.NoError(t, err)
297
298 err = cfg.LoadJWTSecret("wrong")
299 require.ErrorContains(t, err, "incorrect password")
300 }
301
302 func TestJWTSecret_ChangePassword(t *testing.T) {
303 svc, err := tests.CreateTestService(t)
304 require.NoError(t, err)
305 defer svc.Remove()
306
307 cfg, err := config.NewConfig(&config.AppConfig{}, svc.DB)
308 require.NoError(t, err)
309
310 err = cfg.SaveUnlockPasswordCheck("123")
311 require.NoError(t, err)
312
313 err = cfg.LoadJWTSecret("123")
314 require.NoError(t, err)
315
316 jwtSecret, err := cfg.GetJWTSecret()
317 require.NoError(t, err)
318 assert.NotEmpty(t, jwtSecret)
319
320 err = cfg.ChangeUnlockPassword("123", "1234")
321 require.NoError(t, err)
322
323 newJwtSecret, err := cfg.GetJWTSecret()
324 require.ErrorContains(t, err, "unlock")
325
326 err = cfg.LoadJWTSecret("1234")
327 require.NoError(t, err)
328
329 // a new JWT secret must be generated after password change
330 newJwtSecret, err = cfg.GetJWTSecret()
331 require.NoError(t, err)
332 assert.NotEmpty(t, newJwtSecret)
333 assert.NotEqual(t, newJwtSecret, jwtSecret)
334 }
335
336 func TestJWTSecret_ReplaceUnencryptedSecretOnLoad(t *testing.T) {
337 svc, err := tests.CreateTestService(t)
338 require.NoError(t, err)
339 defer svc.Remove()
340
341 cfg, err := config.NewConfig(&config.AppConfig{}, svc.DB)
342 require.NoError(t, err)
343
344 err = cfg.SaveUnlockPasswordCheck("123")
345 require.NoError(t, err)
346
347 // simulate a hub that had an unencrypted JWT secret
348 oldJwtSecret := "dummy secret"
349 err = svc.Cfg.SetUpdate("JWTSecret", oldJwtSecret, "")
350 require.NoError(t, err)
351
352 err = cfg.LoadJWTSecret("123")
353 require.NoError(t, err)
354
355 jwtSecret, err := cfg.GetJWTSecret()
356 require.NoError(t, err)
357 assert.NotEmpty(t, jwtSecret)
358 assert.NotEqual(t, jwtSecret, oldJwtSecret)
359
360 // ensure it is saved to DB
361 jwtSecretFromCfg, err := cfg.Get("JWTSecret", "123")
362 require.NoError(t, err)
363 assert.Equal(t, jwtSecret, jwtSecretFromCfg)
364 }
365