aboutsummaryrefslogtreecommitdiffstats
path: root/dashboard/dashapi/jwt.go
diff options
context:
space:
mode:
authorGreg Steuck <gnezdo@google.com>2021-07-28 12:43:45 -0700
committerDmitry Vyukov <dvyukov@google.com>2021-07-30 18:21:17 +0200
commit7fa384c47c7a97db7f667797bfc8e1ea78167f39 (patch)
tree9fd778bedbdd2d8fce9fd380a729047a6e36378c /dashboard/dashapi/jwt.go
parenta31eceb86df9acc2a471945de8e17fd53091f149 (diff)
pkg/auth: move jwt to auth to be shared by syz-hub clients
Diffstat (limited to 'dashboard/dashapi/jwt.go')
-rw-r--r--dashboard/dashapi/jwt.go92
1 files changed, 0 insertions, 92 deletions
diff --git a/dashboard/dashapi/jwt.go b/dashboard/dashapi/jwt.go
deleted file mode 100644
index 7c0cd25ca..000000000
--- a/dashboard/dashapi/jwt.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2021 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package dashapi
-
-import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "strings"
- "sync"
- "time"
-)
-
-type expiringToken struct {
- token string
- expiration time.Time
-}
-
-// Returns the unverified expiration value from the given JWT token.
-func extractJwtExpiration(token string) (time.Time, error) {
- // https://datatracker.ietf.org/doc/html/rfc7519#section-3
- pieces := strings.Split(token, ".")
- if len(pieces) != 3 {
- return time.Time{}, fmt.Errorf("unexpected number of JWT components %v", len(pieces))
- }
- decoded, err := base64.RawURLEncoding.DecodeString(pieces[1])
- if err != nil {
- return time.Time{}, err
- }
- claims := struct {
- Expiration int64 `json:"exp"`
- }{-123456} // Hopefully a notably broken value.
- if err = json.Unmarshal(decoded, &claims); err != nil {
- return time.Time{}, err
- }
- return time.Unix(claims.Expiration, 0), nil
-}
-
-// Queries the metadata server and returns the bearer token of the service account.
-// The token is scoped for the official dashboard.
-func retrieveJwtToken(ctor RequestCtor, doer RequestDoer) (*expiringToken, error) {
- const v1meta = "http://metadata.google.internal/computeMetadata/v1"
- req, err := ctor("GET", v1meta+"/instance/service-accounts/default/identity?audience="+DashboardAudience, nil)
- if err != nil {
- return nil, err
- }
- req.Header.Add("Metadata-Flavor", "Google")
- resp, err := doer(req)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
- token := string(data)
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("failed metadata get %v: %s", resp.Status, token)
- }
- expiration, err := extractJwtExpiration(token)
- if err != nil {
- return nil, err
- }
- return &expiringToken{token, expiration}, nil
-}
-
-// Augments the given doer with an authorization header carrying the
-// given token. The token gets refreshed when it becomes stale.
-func atachJwtToken(ctor RequestCtor, doer RequestDoer, token *expiringToken) RequestDoer {
- lock := sync.Mutex{}
- return func(req *http.Request) (*http.Response, error) {
- lock.Lock()
- if token.expiration.Before(time.Now()) {
- // Keeping the lock while making http request is dubious, but
- // making multiple concurrent requests is not any better.
- t, err := retrieveJwtToken(ctor, doer)
- if err != nil {
- // Can't get a new token, so returning the error preemptively.
- lock.Unlock()
- return nil, err
- }
- *token = *t
- }
- req.Header.Add("Authorization", "Bearer "+token.token)
- lock.Unlock()
- return doer(req)
- }
-}