@@ -2,8 +2,15 @@ package client
2
2
3
3
import (
4
4
"context"
5
+ "crypto/rand"
6
+ "crypto/rsa"
7
+ "os"
8
+ "slices"
5
9
"testing"
10
+ "time"
6
11
12
+ "github.com/go-jose/go-jose/v4"
13
+ "github.com/go-jose/go-jose/v4/jwt"
7
14
"github.com/grafana/grafana-operator/v5/api/v1beta1"
8
15
"github.com/stretchr/testify/assert"
9
16
"github.com/stretchr/testify/require"
@@ -312,3 +319,87 @@ func TestGetAdminCredentials(t *testing.T) {
312
319
assert .Nil (t , got )
313
320
})
314
321
}
322
+
323
+ func TestGetBearerToken (t * testing.T ) {
324
+ t .Parallel ()
325
+
326
+ now := time .Now ()
327
+ body := jwt.Claims {
328
+ ID : "1234" ,
329
+ Issuer : "grafana.operator.com" ,
330
+ Audience : jwt.Audience {"https://grafana.operator.com" },
331
+ IssuedAt : jwt .NewNumericDate (now ),
332
+ NotBefore : jwt .NewNumericDate (now ),
333
+ Expiry : jwt .NewNumericDate (now .Add (time .Duration (30 * float64 (time .Second )))),
334
+ }
335
+
336
+ // Generate key
337
+ testRSAKey , err := rsa .GenerateKey (rand .Reader , 1024 ) // nolint:gosec
338
+ require .NotNil (t , testRSAKey )
339
+ require .NoError (t , err )
340
+
341
+ sk := jose.SigningKey {
342
+ Key : & jose.JSONWebKey {
343
+ Key : testRSAKey ,
344
+ KeyID : "test-key" ,
345
+ },
346
+ Algorithm : jose .RS256 ,
347
+ }
348
+
349
+ // Create signer, and sign token
350
+ signer , err := jose .NewSigner (sk , & jose.SignerOptions {EmbedJWK : true })
351
+ require .NoError (t , err )
352
+
353
+ origToken , err := jwt .Signed (signer ).Claims (body ).Serialize ()
354
+ require .NoError (t , err )
355
+
356
+ // Create tmp file
357
+ tokenFile , err := os .CreateTemp (os .TempDir (), "token-*" )
358
+ require .NoError (t , err )
359
+ require .NotNil (t , testRSAKey )
360
+
361
+ // Do not read token file purposefully
362
+ jwtCache = nil
363
+ noToken , err := getBearerToken (tokenFile .Name () + "-extra" )
364
+ require .Error (t , err )
365
+ require .Empty (t , noToken )
366
+ require .Nil (t , jwtCache )
367
+
368
+ // Write token to file
369
+ writtenBytes , err := tokenFile .WriteString (origToken )
370
+ require .Equal (t , len ([]byte (origToken )), writtenBytes )
371
+ require .NoError (t , err )
372
+
373
+ // Decode token
374
+ token , err := getBearerToken (tokenFile .Name ())
375
+ require .NoError (t , err )
376
+ require .Equal (t , origToken , token )
377
+ require .Equal (t , origToken , jwtCache .Token )
378
+ require .False (t , jwtCache .Expiration .IsZero ())
379
+
380
+ // Expire the cache and re-read token
381
+ jwtCache .Expiration = time .Now ().Add (- 10 * time .Second )
382
+ token , err = getBearerToken (tokenFile .Name ())
383
+ require .NoError (t , err )
384
+ require .Equal (t , origToken , token )
385
+ require .True (t , jwtCache .Expiration .After (time .Now ()))
386
+
387
+ // Mangle token
388
+ reversedOrigToken := []byte (origToken )
389
+ slices .Reverse (reversedOrigToken )
390
+ reversedWrittenBytes , err := tokenFile .Write (reversedOrigToken )
391
+ require .NoError (t , err )
392
+ require .Equal (t , len ([]byte (reversedOrigToken )), reversedWrittenBytes )
393
+
394
+ // Successfully get token from cache
395
+ token , err = getBearerToken (tokenFile .Name ())
396
+ require .NoError (t , err )
397
+ require .Equal (t , origToken , token )
398
+
399
+ // Reset cache and error on mangled token
400
+ jwtCache = nil
401
+ mangledToken , err := getBearerToken (tokenFile .Name ())
402
+ require .Error (t , err )
403
+ require .Empty (t , mangledToken )
404
+ require .Nil (t , jwtCache )
405
+ }
0 commit comments