github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/jwt_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 "net/http" 23 "os" 24 "testing" 25 "time" 26 27 jwtgo "github.com/golang-jwt/jwt/v4" 28 xjwt "github.com/minio/minio/internal/jwt" 29 ) 30 31 func getTokenString(accessKey, secretKey string) (string, error) { 32 claims := xjwt.NewMapClaims() 33 claims.SetExpiry(UTCNow().Add(defaultJWTExpiry)) 34 claims.SetAccessKey(accessKey) 35 token := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims) 36 return token.SignedString([]byte(secretKey)) 37 } 38 39 // Tests web request authenticator. 40 func TestWebRequestAuthenticate(t *testing.T) { 41 ctx, cancel := context.WithCancel(context.Background()) 42 defer cancel() 43 44 obj, fsDir, err := prepareFS(ctx) 45 if err != nil { 46 t.Fatal(err) 47 } 48 defer os.RemoveAll(fsDir) 49 if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { 50 t.Fatal(err) 51 } 52 53 creds := globalActiveCred 54 token, err := getTokenString(creds.AccessKey, creds.SecretKey) 55 if err != nil { 56 t.Fatalf("unable get token %s", err) 57 } 58 testCases := []struct { 59 req *http.Request 60 expectedErr error 61 }{ 62 // Set valid authorization header. 63 { 64 req: &http.Request{ 65 Header: http.Header{ 66 "Authorization": []string{token}, 67 }, 68 }, 69 expectedErr: nil, 70 }, 71 // No authorization header. 72 { 73 req: &http.Request{ 74 Header: http.Header{}, 75 }, 76 expectedErr: errNoAuthToken, 77 }, 78 // Invalid authorization token. 79 { 80 req: &http.Request{ 81 Header: http.Header{ 82 "Authorization": []string{"invalid-token"}, 83 }, 84 }, 85 expectedErr: errAuthentication, 86 }, 87 } 88 89 for i, testCase := range testCases { 90 _, _, _, gotErr := metricsRequestAuthenticate(testCase.req) 91 if testCase.expectedErr != gotErr { 92 t.Errorf("Test %d, expected err %s, got %s", i+1, testCase.expectedErr, gotErr) 93 } 94 } 95 } 96 97 func BenchmarkParseJWTStandardClaims(b *testing.B) { 98 ctx, cancel := context.WithCancel(context.Background()) 99 defer cancel() 100 101 obj, fsDir, err := prepareFS(ctx) 102 if err != nil { 103 b.Fatal(err) 104 } 105 defer os.RemoveAll(fsDir) 106 if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { 107 b.Fatal(err) 108 } 109 110 creds := globalActiveCred 111 token, err := authenticateNode(creds.AccessKey, creds.SecretKey, "") 112 if err != nil { 113 b.Fatal(err) 114 } 115 116 b.ResetTimer() 117 b.ReportAllocs() 118 b.RunParallel(func(pb *testing.PB) { 119 for pb.Next() { 120 err = xjwt.ParseWithStandardClaims(token, xjwt.NewStandardClaims(), []byte(creds.SecretKey)) 121 if err != nil { 122 b.Fatal(err) 123 } 124 } 125 }) 126 } 127 128 func BenchmarkParseJWTMapClaims(b *testing.B) { 129 ctx, cancel := context.WithCancel(context.Background()) 130 defer cancel() 131 132 obj, fsDir, err := prepareFS(ctx) 133 if err != nil { 134 b.Fatal(err) 135 } 136 defer os.RemoveAll(fsDir) 137 if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { 138 b.Fatal(err) 139 } 140 141 creds := globalActiveCred 142 token, err := authenticateNode(creds.AccessKey, creds.SecretKey, "") 143 if err != nil { 144 b.Fatal(err) 145 } 146 147 b.ResetTimer() 148 b.ReportAllocs() 149 b.RunParallel(func(pb *testing.PB) { 150 for pb.Next() { 151 err = xjwt.ParseWithClaims(token, xjwt.NewMapClaims(), func(*xjwt.MapClaims) ([]byte, error) { 152 return []byte(creds.SecretKey), nil 153 }) 154 if err != nil { 155 b.Fatal(err) 156 } 157 } 158 }) 159 } 160 161 func BenchmarkAuthenticateNode(b *testing.B) { 162 ctx, cancel := context.WithCancel(context.Background()) 163 defer cancel() 164 165 obj, fsDir, err := prepareFS(ctx) 166 if err != nil { 167 b.Fatal(err) 168 } 169 defer os.RemoveAll(fsDir) 170 if err = newTestConfig(globalMinioDefaultRegion, obj); err != nil { 171 b.Fatal(err) 172 } 173 174 creds := globalActiveCred 175 b.Run("uncached", func(b *testing.B) { 176 fn := authenticateNode 177 b.ResetTimer() 178 b.ReportAllocs() 179 for i := 0; i < b.N; i++ { 180 fn(creds.AccessKey, creds.SecretKey, "aud") 181 } 182 }) 183 b.Run("cached", func(b *testing.B) { 184 fn := cachedAuthenticateNode(time.Second) 185 b.ResetTimer() 186 b.ReportAllocs() 187 for i := 0; i < b.N; i++ { 188 fn(creds.AccessKey, creds.SecretKey, "aud") 189 } 190 }) 191 }