diff options
| -rw-r--r-- | dashboard/app/api.go | 7 | ||||
| -rw-r--r-- | dashboard/app/app_test.go | 3 | ||||
| -rw-r--r-- | dashboard/app/config.go | 3 | ||||
| -rw-r--r-- | pkg/auth/auth.go (renamed from dashboard/app/auth.go) | 25 | ||||
| -rw-r--r-- | pkg/auth/auth_test.go (renamed from dashboard/app/auth_test.go) | 18 |
5 files changed, 31 insertions, 25 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go index 748d7abb2..4107eb200 100644 --- a/dashboard/app/api.go +++ b/dashboard/app/api.go @@ -17,6 +17,7 @@ import ( "unicode/utf8" "github.com/google/syzkaller/dashboard/dashapi" + "github.com/google/syzkaller/pkg/auth" "github.com/google/syzkaller/pkg/email" "github.com/google/syzkaller/pkg/hash" "github.com/google/syzkaller/sys/targets" @@ -104,8 +105,8 @@ func handleAPI(c context.Context, r *http.Request) (reply interface{}, err error client := r.PostFormValue("client") method := r.PostFormValue("method") log.Infof(c, "api %q from %q", method, client) - auth := makeAuthEndpoint(googleTokenInfoEndpoint) - subj, err := auth.determineAuthSubj(timeNow(c), r.Header["Authorization"]) + auth := auth.MakeEndpoint(auth.GoogleTokenInfoEndpoint) + subj, err := auth.DetermineAuthSubj(timeNow(c), r.Header["Authorization"]) if err != nil { return nil, err } @@ -1351,7 +1352,7 @@ func GetEmails(r dashapi.Recipients, filter dashapi.RecipientType) []string { // corresponding namespace. func checkClient(conf *GlobalConfig, name0, secretPassword, oauthSubject string) (string, error) { checkAuth := func(ns, a string) (string, error) { - if strings.HasPrefix(a, oauthMagic) && a == oauthSubject { + if strings.HasPrefix(a, auth.OauthMagic) && a == oauthSubject { return ns, nil } if a != secretPassword { diff --git a/dashboard/app/app_test.go b/dashboard/app/app_test.go index 49df21d0d..777b73ce8 100644 --- a/dashboard/app/app_test.go +++ b/dashboard/app/app_test.go @@ -13,6 +13,7 @@ import ( "time" "github.com/google/syzkaller/dashboard/dashapi" + "github.com/google/syzkaller/pkg/auth" "github.com/google/syzkaller/sys/targets" "google.golang.org/appengine/user" ) @@ -57,7 +58,7 @@ var testConfig = &GlobalConfig{ FixBisectionAutoClose: true, Clients: map[string]string{ client1: password1, - "oauth": oauthMagic + "111111122222222", + "oauth": auth.OauthMagic + "111111122222222", }, Repos: []KernelRepo{ { diff --git a/dashboard/app/config.go b/dashboard/app/config.go index 08f8ce850..4aa79348f 100644 --- a/dashboard/app/config.go +++ b/dashboard/app/config.go @@ -12,6 +12,7 @@ import ( "time" "github.com/google/syzkaller/dashboard/dashapi" + "github.com/google/syzkaller/pkg/auth" "github.com/google/syzkaller/pkg/email" "github.com/google/syzkaller/pkg/vcs" ) @@ -202,7 +203,7 @@ type KcidbConfig struct { var ( namespaceNameRe = regexp.MustCompile("^[a-zA-Z0-9-_.]{4,32}$") clientNameRe = regexp.MustCompile("^[a-zA-Z0-9-_.]{4,100}$") - clientKeyRe = regexp.MustCompile("^([a-zA-Z0-9]{16,128})|(" + regexp.QuoteMeta(oauthMagic) + ".*)$") + clientKeyRe = regexp.MustCompile("^([a-zA-Z0-9]{16,128})|(" + regexp.QuoteMeta(auth.OauthMagic) + ".*)$") ) type ( diff --git a/dashboard/app/auth.go b/pkg/auth/auth.go index a6da8e24d..bd542bc32 100644 --- a/dashboard/app/auth.go +++ b/pkg/auth/auth.go @@ -22,7 +22,9 @@ // https://cloud.google.com/iap/docs/signed-headers-howto#retrieving_the_user_identity // from the IAP docs agrees to trust sub. -package main +// Package auth contains authentication related code supporting secret +// passwords and oauth2 tokens on GCE. +package auth import ( "encoding/json" @@ -39,21 +41,21 @@ import ( const ( // The official google oauth2 endpoint. - googleTokenInfoEndpoint = "https://oauth2.googleapis.com/tokeninfo" + GoogleTokenInfoEndpoint = "https://oauth2.googleapis.com/tokeninfo" // Used in the config map as a prefix to distinguish auth identifiers from secret passwords // (which contain arbitrary strings, that can't have this prefix). - oauthMagic = "OauthSubject:" + OauthMagic = "OauthSubject:" ) // Represent a verification backend. -type authEndpoint struct { +type Endpoint struct { // URL supporting tokeninfo auth2 protocol. url string // TODO(blackgnezdo): cache tokens with a bit of care for concurrency. } -func makeAuthEndpoint(u string) authEndpoint { - return authEndpoint{url: u} +func MakeEndpoint(u string) Endpoint { + return Endpoint{url: u} } // The JSON representation of JWT claims. @@ -72,7 +74,7 @@ type jwtClaims struct { Expiration time.Time } -func (auth *authEndpoint) queryTokenInfo(tokenValue string) (*jwtClaims, error) { +func (auth *Endpoint) queryTokenInfo(tokenValue string) (*jwtClaims, error) { resp, err := http.PostForm(auth.url, url.Values{"id_token": {tokenValue}}) if err != nil { return nil, err @@ -100,9 +102,10 @@ func (auth *authEndpoint) queryTokenInfo(tokenValue string) (*jwtClaims, error) // Returns the verified subject value based on the provided header // value or "" if it can't be determined. A valid result starts with -// oauthMagic. The now parameter is the current time to compare the -// claims against. -func (auth *authEndpoint) determineAuthSubj(now time.Time, authHeader []string) (string, error) { +// auth.OauthMagic. The now parameter is the current time to compare the +// claims against. The authHeader is styled as is typical for HTTP headers +// which carry the tokens prefixed by "Bearer " string. +func (auth *Endpoint) DetermineAuthSubj(now time.Time, authHeader []string) (string, error) { if len(authHeader) != 1 || !strings.HasPrefix(authHeader[0], "Bearer") { // This is a normal case when the client uses a password. return "", nil @@ -122,5 +125,5 @@ func (auth *authEndpoint) determineAuthSubj(now time.Time, authHeader []string) err := fmt.Errorf("token past expiration %v", claims.Expiration) return "", err } - return oauthMagic + claims.Subject, nil + return OauthMagic + claims.Subject, nil } diff --git a/dashboard/app/auth_test.go b/pkg/auth/auth_test.go index c6d5fba23..13a9c5749 100644 --- a/dashboard/app/auth_test.go +++ b/pkg/auth/auth_test.go @@ -1,7 +1,7 @@ -// Copyright 2017 syzkaller project authors. All rights reserved. +// 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 main +package auth import ( "encoding/json" @@ -15,7 +15,7 @@ import ( "github.com/google/syzkaller/dashboard/dashapi" ) -func reponseFor(t *testing.T, claims jwtClaims) (*httptest.Server, authEndpoint) { +func reponseFor(t *testing.T, claims jwtClaims) (*httptest.Server, Endpoint) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { bytes, err := json.Marshal(jwtClaimsParse{ Subject: claims.Subject, @@ -28,7 +28,7 @@ func reponseFor(t *testing.T, claims jwtClaims) (*httptest.Server, authEndpoint) w.Header()["Content-Type"] = []string{"application/json"} w.Write(bytes) })) - return ts, makeAuthEndpoint(ts.URL) + return ts, MakeEndpoint(ts.URL) } func TestBearerValid(t *testing.T) { @@ -41,7 +41,7 @@ func TestBearerValid(t *testing.T) { }) defer ts.Close() - got, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) + got, err := dut.DetermineAuthSubj(tm, []string{"Bearer x"}) if err != nil { t.Errorf("Unexpected error %v", err) } @@ -59,7 +59,7 @@ func TestBearerWrongAudience(t *testing.T) { }) defer ts.Close() - _, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) + _, err := dut.DetermineAuthSubj(tm, []string{"Bearer x"}) if !strings.HasPrefix(err.Error(), "unexpected audience") { t.Fatalf("Unexpected error %v", err) } @@ -74,7 +74,7 @@ func TestBearerExpired(t *testing.T) { }) defer ts.Close() - _, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) + _, err := dut.DetermineAuthSubj(tm, []string{"Bearer x"}) if !strings.HasPrefix(err.Error(), "token past expiration") { t.Fatalf("Unexpected error %v", err) } @@ -83,7 +83,7 @@ func TestBearerExpired(t *testing.T) { func TestMissingHeader(t *testing.T) { ts, dut := reponseFor(t, jwtClaims{}) defer ts.Close() - got, err := dut.determineAuthSubj(time.Now(), []string{}) + got, err := dut.DetermineAuthSubj(time.Now(), []string{}) if err != nil || got != "" { t.Errorf("Unexpected error %v %v", got, err) } @@ -92,7 +92,7 @@ func TestMissingHeader(t *testing.T) { func TestBadHeader(t *testing.T) { ts, dut := reponseFor(t, jwtClaims{}) defer ts.Close() - got, err := dut.determineAuthSubj(time.Now(), []string{"bad"}) + got, err := dut.DetermineAuthSubj(time.Now(), []string{"bad"}) if err != nil || got != "" { t.Errorf("Unexpected error %v %v", got, err) } |
