Skip to content

Commit 7eb9430

Browse files
committed
fix: allow token lookups by all hashing algorithms used in store
Fix a bug that only allowed hashed tokens to be looked up if they used the currently active hashing algorithm. Also added tests for configuration migration scenarios (enabling and disabling hashing, changing hashing scheme).
1 parent 5279970 commit 7eb9430

File tree

2 files changed

+196
-6
lines changed

2 files changed

+196
-6
lines changed

authorization/storage.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (s *Store) autogenerateHasher(ctx context.Context, variantName string) (*Au
229229
for _, a := range auths {
230230
if a.HashedToken != "" {
231231
digest, err := tempDecoder.Decode(a.HashedToken)
232-
if err != nil {
232+
if err == nil {
233233
if influxdbDigest, ok := digest.(*influxdb2_algo.Digest); ok {
234234
foundVariants[influxdbDigest.Variant] = struct{}{}
235235
}

authorization/storage_authorization_test.go

Lines changed: 195 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ import (
1111
"github.com/influxdata/influxdb/v2/kit/platform"
1212
"github.com/influxdata/influxdb/v2/kv"
1313
"github.com/influxdata/influxdb/v2/kv/migration/all"
14+
influxdb2_algo "github.com/influxdata/influxdb/v2/pkg/crypt/algorithm/influxdb2"
1415
"github.com/stretchr/testify/require"
1516
"go.uber.org/zap/zaptest"
1617
)
1718

19+
const (
20+
authIndexName = "authorizationindexv1"
21+
hashedAuthIndexName = "authorizationhashedindexv1"
22+
)
23+
1824
func TestAuth(t *testing.T) {
1925
checkIndexCounts := func(t *testing.T, tx kv.Tx, expAuthIndexCount, expHashedAuthIndexCount int) {
2026
t.Helper()
2127

22-
const (
23-
authIndexName = "authorizationindexv1"
24-
hashedAuthIndexName = "authorizationhashedindexv1"
25-
)
26-
2728
indexCount := make(map[string]int)
2829
for _, indexName := range []string{authIndexName, hashedAuthIndexName} {
2930
index, err := tx.Bucket([]byte(indexName))
@@ -279,3 +280,192 @@ func TestAuth(t *testing.T) {
279280
}
280281
}
281282
}
283+
284+
func TestAuthorizationStore_HashingConfigChanges(t *testing.T) {
285+
sha256, err := influxdb2_algo.New(influxdb2_algo.WithVariant(influxdb2_algo.VariantSHA256))
286+
require.NoError(t, err)
287+
sha512, err := influxdb2_algo.New(influxdb2_algo.WithVariant(influxdb2_algo.VariantSHA512))
288+
require.NoError(t, err)
289+
290+
type authData struct {
291+
ID platform.ID
292+
Token string
293+
HashedToken string
294+
}
295+
type testConfig struct {
296+
enabled bool
297+
algo string
298+
}
299+
type testCase struct {
300+
desc string
301+
config testConfig
302+
action func(t *testing.T, ctx context.Context, store *authorization.Store, tx kv.Tx)
303+
exp []authData
304+
hashedTokens []string // tokens which only exists as hashes
305+
}
306+
cases := []testCase{
307+
{
308+
desc: "initial unhashed",
309+
config: testConfig{enabled: false},
310+
action: func(t *testing.T, ctx context.Context, store *authorization.Store, tx kv.Tx) {
311+
a := &influxdb.Authorization{
312+
ID: platform.ID(1),
313+
OrgID: platform.ID(1),
314+
UserID: platform.ID(1),
315+
Token: "Token#1",
316+
}
317+
require.NoError(t, store.CreateAuthorization(ctx, tx, a))
318+
},
319+
exp: []authData{
320+
{ID: platform.ID(1), Token: "Token#1"},
321+
},
322+
},
323+
{
324+
desc: "upgrade hashed #1", // update hash and indices
325+
config: testConfig{enabled: true, algo: influxdb2_algo.VariantIdentifierSHA256},
326+
exp: []authData{
327+
{ID: platform.ID(1), HashedToken: sha256.MustHash("Token#1").Encode()},
328+
},
329+
hashedTokens: []string{"Token#1"},
330+
},
331+
{
332+
desc: "downgrade hashed #1", // can't unhash
333+
config: testConfig{enabled: false, algo: influxdb2_algo.VariantIdentifierSHA256},
334+
action: func(t *testing.T, ctx context.Context, store *authorization.Store, tx kv.Tx) {
335+
a := &influxdb.Authorization{
336+
ID: platform.ID(2),
337+
OrgID: platform.ID(2),
338+
UserID: platform.ID(2),
339+
Token: "Token#2",
340+
}
341+
require.NoError(t, store.CreateAuthorization(ctx, tx, a))
342+
},
343+
exp: []authData{
344+
{ID: platform.ID(1), HashedToken: sha256.MustHash("Token#1").Encode()},
345+
{ID: platform.ID(2), Token: "Token#2"},
346+
},
347+
hashedTokens: []string{"Token#1"},
348+
},
349+
{
350+
desc: "upgrade hashed sha512", // can't rehash existing, use new algo for new auths
351+
config: testConfig{enabled: true, algo: influxdb2_algo.VariantIdentifierSHA512},
352+
action: func(t *testing.T, ctx context.Context, store *authorization.Store, tx kv.Tx) {
353+
a := &influxdb.Authorization{
354+
ID: platform.ID(3),
355+
OrgID: platform.ID(3),
356+
UserID: platform.ID(3),
357+
Token: "Token#3",
358+
}
359+
require.NoError(t, store.CreateAuthorization(ctx, tx, a))
360+
},
361+
exp: []authData{
362+
{ID: platform.ID(1), HashedToken: sha256.MustHash("Token#1").Encode()},
363+
{ID: platform.ID(2), HashedToken: sha512.MustHash("Token#2").Encode()},
364+
{ID: platform.ID(3), HashedToken: sha512.MustHash("Token#3").Encode()},
365+
},
366+
hashedTokens: []string{"Token#1", "Token#2", "Token#3"},
367+
},
368+
}
369+
370+
ctx := context.Background()
371+
372+
// The underlying kv store persists across tests cases. This allows for testing how opening with
373+
// new authentication configurations impacts the data.
374+
kvStore := inmem.NewKVStore()
375+
err = all.Up(ctx, zaptest.NewLogger(t), kvStore)
376+
require.NoError(t, err)
377+
378+
for _, tc := range cases {
379+
t.Run(tc.desc, func(t *testing.T) {
380+
// Create new authorization.Store for test cases using existing kvStore.
381+
variantName := tc.config.algo
382+
if variantName == "" {
383+
if !tc.config.enabled {
384+
variantName = authorization.DefaultHashVariantName
385+
} else {
386+
require.Fail(t, "Must specific algo if hashing is enabled for test case")
387+
}
388+
}
389+
store, err := authorization.NewStore(ctx, kvStore, tc.config.enabled, authorization.WithAuthorizationHashVariantName(variantName))
390+
require.NoError(t, err)
391+
require.NotNil(t, store)
392+
393+
// Execute action, if given. Simply opening the store with a different configuration may be the "action".
394+
if tc.action != nil {
395+
err = kvStore.Update(ctx, func(tx kv.Tx) error {
396+
tc.action(t, ctx, store, tx)
397+
return nil
398+
})
399+
require.NoError(t, err)
400+
}
401+
402+
// Check results.
403+
err = kvStore.View(ctx, func(tx kv.Tx) error {
404+
// Collect all authorization data from store.
405+
storedAuths, err := store.ListAuthorizations(ctx, tx, influxdb.AuthorizationFilter{})
406+
require.NoError(t, err)
407+
408+
// Collect auth data from data currently in store
409+
actualAuthData := make([]authData, 0, len(storedAuths))
410+
for _, sa := range storedAuths {
411+
ad := authData{ID: sa.ID, Token: sa.Token, HashedToken: sa.HashedToken}
412+
actualAuthData = append(actualAuthData, ad)
413+
}
414+
415+
// Check that authData matches exp.
416+
require.ElementsMatch(t, tc.exp, actualAuthData)
417+
418+
// Collect data from kvStore's token index.
419+
collectIndex := func(indexName string) map[string]platform.ID {
420+
indexMap := make(map[string]platform.ID)
421+
index, err := tx.Bucket([]byte(indexName))
422+
require.NoError(t, err)
423+
cursor, err := index.Cursor()
424+
require.NoError(t, err)
425+
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
426+
var id platform.ID
427+
require.NoError(t, id.Decode(v))
428+
indexMap[string(k)] = id
429+
}
430+
return indexMap
431+
}
432+
actualTokenIndex := collectIndex(authIndexName)
433+
actualHashedIndex := collectIndex(hashedAuthIndexName)
434+
435+
// Collect expected token and hashed indices.
436+
expTokenIndex := make(map[string]platform.ID)
437+
expHashedIndex := make(map[string]platform.ID)
438+
for _, d := range tc.exp {
439+
if d.Token != "" {
440+
expTokenIndex[d.Token] = d.ID
441+
}
442+
if d.HashedToken != "" {
443+
expHashedIndex[d.HashedToken] = d.ID
444+
}
445+
}
446+
447+
// Compare indices.
448+
require.Equal(t, expTokenIndex, actualTokenIndex)
449+
require.Equal(t, expHashedIndex, actualHashedIndex)
450+
451+
// Make sure we can lookup all tokens.
452+
var allTokens []string
453+
for _, d := range tc.exp {
454+
if d.Token != "" {
455+
allTokens = append(allTokens, d.Token)
456+
}
457+
}
458+
allTokens = append(allTokens, tc.hashedTokens...)
459+
460+
for _, token := range allTokens {
461+
auth, err := store.GetAuthorizationByToken(ctx, tx, token)
462+
require.NoError(t, err, "error looking up token %q", token)
463+
require.NotNil(t, auth)
464+
}
465+
466+
return nil
467+
})
468+
})
469+
470+
}
471+
}

0 commit comments

Comments
 (0)