internal/access,internal/relui: use IAPFields instead of one-of context key
For gRPC, we have a nice IAPFields type and IAPFromContext helper. Use
that for HTTP as well rather than a one-off undocumented context key.
Change-Id: I6a6a636c1a48f7bf194a7e15fcbfaec77808646a
Reviewed-on: https://go-review.googlesource.com/c/build/+/666497
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/access/access.go b/internal/access/access.go
index ac560d9..9dc434c 100644
--- a/internal/access/access.go
+++ b/internal/access/access.go
@@ -73,8 +73,7 @@
log.Printf("JWT validation error: %v", err)
return
}
- ctx := context.WithValue(r.Context(), "subject", iap.ID)
- ctx = context.WithValue(ctx, "email", iap.Email)
+ ctx := ContextWithIAP(r.Context(), iap)
h.ServeHTTP(w, r.WithContext(ctx))
})
}
diff --git a/internal/relui/web.go b/internal/relui/web.go
index d47409c..c97532c 100644
--- a/internal/relui/web.go
+++ b/internal/relui/web.go
@@ -25,6 +25,7 @@
"github.com/google/uuid"
"github.com/jackc/pgx/v4"
"github.com/julienschmidt/httprouter"
+ "golang.org/x/build/internal/access"
"golang.org/x/build/internal/criadb"
"golang.org/x/build/internal/metrics"
"golang.org/x/build/internal/relui/db"
@@ -676,16 +677,16 @@
return true
}
- email := ctx.Value("email")
- if email == nil {
- log.Printf("request context did not contain expected 'email' value from IAP JWT")
+ iap, err := access.IAPFromContext(ctx)
+ if err != nil {
+ log.Printf("Error getting IAP fields from context: %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return false
}
- isMember, err := s.cria.IsMemberOfAny(ctx, fmt.Sprintf("user:%s", email), authorizedGroups)
+ isMember, err := s.cria.IsMemberOfAny(ctx, fmt.Sprintf("user:%s", iap.Email), authorizedGroups)
if err != nil {
- log.Printf("cria.IsMemberOfAny(user:%s) failed: %s", email, err)
+ log.Printf("cria.IsMemberOfAny(user:%s) failed: %s", iap.Email, err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return false
}
diff --git a/internal/relui/web_test.go b/internal/relui/web_test.go
index 4ac63fc..293608a 100644
--- a/internal/relui/web_test.go
+++ b/internal/relui/web_test.go
@@ -29,6 +29,7 @@
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/julienschmidt/httprouter"
+ "golang.org/x/build/internal/access"
"golang.org/x/build/internal/criadb"
"golang.org/x/build/internal/releasetargets"
"golang.org/x/build/internal/relui/db"
@@ -844,6 +845,11 @@
}
s := NewServer(p, worker, nil, SiteHeader{}, nil, criadb.NewTestDatabase(memberships))
+ iap := access.IAPFields{
+ Email: "test@google.com",
+ ID: "testid",
+ }
+
hourAgo := time.Now().Add(-1 * time.Hour)
q := db.New(p)
@@ -854,7 +860,7 @@
"workflow.schedule": []string{string(ScheduleImmediate)},
}.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req = req.WithContext(context.WithValue(req.Context(), "email", "test@google.com"))
+ req = req.WithContext(access.ContextWithIAP(req.Context(), iap))
rec := httptest.NewRecorder()
s.createWorkflowHandler(rec, req)
@@ -892,7 +898,7 @@
params := httprouter.Params{{Key: "id", Value: wfID.String()}, {Key: "name", Value: "beep"}}
req := httptest.NewRequest(http.MethodPost, path.Join("/workflows/", wfID.String(), "tasks", "beep", "retry"), nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req = req.WithContext(context.WithValue(req.Context(), "email", "test@google.com"))
+ req = req.WithContext(access.ContextWithIAP(req.Context(), iap))
rec := httptest.NewRecorder()
s.retryTaskHandler(rec, req, params)
@@ -933,7 +939,7 @@
params := httprouter.Params{{Key: "id", Value: wfID.String()}, {Key: "name", Value: "approve"}}
req := httptest.NewRequest(http.MethodPost, path.Join("/workflows/", wfID.String(), "tasks", "approve", "approve"), nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req = req.WithContext(context.WithValue(req.Context(), "email", "test@google.com"))
+ req = req.WithContext(access.ContextWithIAP(req.Context(), iap))
rec := httptest.NewRecorder()
s.approveTaskHandler(rec, req, params)
@@ -965,7 +971,7 @@
params := httprouter.Params{{Key: "id", Value: wfID.String()}}
req := httptest.NewRequest(http.MethodPost, path.Join("/workflows/", wfID.String(), "stop"), nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req = req.WithContext(context.WithValue(req.Context(), "email", "test@google.com"))
+ req = req.WithContext(access.ContextWithIAP(req.Context(), iap))
rec := httptest.NewRecorder()
s.stopWorkflowHandler(rec, req, params)
@@ -989,7 +995,7 @@
params := httprouter.Params{{Key: "id", Value: strconv.Itoa(int(sched.ID))}}
req := httptest.NewRequest(http.MethodPost, path.Join("/schedules/", strconv.Itoa(int(sched.ID)), "delete"), nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req = req.WithContext(context.WithValue(req.Context(), "email", "test@google.com"))
+ req = req.WithContext(access.ContextWithIAP(req.Context(), iap))
rec := httptest.NewRecorder()
s.deleteScheduleHandler(rec, req, params)