aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Steuck <gnezdo@google.com>2021-07-28 11:03:25 -0700
committerDmitry Vyukov <dvyukov@google.com>2021-07-30 18:21:17 +0200
commit5bfcec7dfd4ba51d38b41cea770ecc96e7e59d4d (patch)
treeef129d2b1e22acfd1c790c8189d7776a82daba91
parent14f590a6a765d9fbe53e2f7bacb5d9f6d7cb9063 (diff)
pkg/auth: move auth code into a new package for reuse in syz-hub
-rw-r--r--dashboard/app/api.go7
-rw-r--r--dashboard/app/app_test.go3
-rw-r--r--dashboard/app/config.go3
-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)
}