diff --git a/go/vt/vtadmin/api.go b/go/vt/vtadmin/api.go index 418ca38e94c..aac504940a9 100644 --- a/go/vt/vtadmin/api.go +++ b/go/vt/vtadmin/api.go @@ -178,6 +178,7 @@ func NewAPI(clusters []*cluster.Cluster, opts Options) *API { experimentalRouter := router.PathPrefix("/experimental").Subrouter() experimentalRouter.HandleFunc("/tablet/{tablet}/debug/vars", httpAPI.Adapt(experimental.TabletDebugVarsPassthrough)).Name("API.TabletDebugVarsPassthrough") + experimentalRouter.HandleFunc("/whoami", httpAPI.Adapt(experimental.WhoAmI)) if !opts.HTTPOpts.DisableDebug { // Due to the way net/http/pprof insists on registering its handlers, we diff --git a/go/vt/vtadmin/http/experimental/whoami.go b/go/vt/vtadmin/http/experimental/whoami.go new file mode 100644 index 00000000000..654edc781be --- /dev/null +++ b/go/vt/vtadmin/http/experimental/whoami.go @@ -0,0 +1,21 @@ +package experimental + +import ( + "context" + + vtadminhttp "vitess.io/vitess/go/vt/vtadmin/http" + "vitess.io/vitess/go/vt/vtadmin/rbac" +) + +// WhoAmI is an experimental route for extracting authenticated Actors from +// the request, to see who is authenticated on the frontend. +func WhoAmI(ctx context.Context, r vtadminhttp.Request, api *vtadminhttp.API) *vtadminhttp.JSONResponse { + data := map[string]interface{}{} + actor, ok := rbac.FromContext(ctx) + data["authenticated"] = ok + if ok { + data["actor"] = actor + } + + return vtadminhttp.NewJSONResponse(data, nil) +} diff --git a/go/vt/vtadmin/rbac/authentication.go b/go/vt/vtadmin/rbac/authentication.go index a43dcbb2e1f..142e5961e3a 100644 --- a/go/vt/vtadmin/rbac/authentication.go +++ b/go/vt/vtadmin/rbac/authentication.go @@ -90,8 +90,8 @@ func AuthenticationUnaryInterceptor(authn Authenticator) grpc.UnaryServerInterce // Actor represents the subject in the "subject action resource" of an // authorization check. It has a name and many roles. type Actor struct { - Name string - Roles []string + Name string `json:"name"` + Roles []string `json:"roles"` } type actorkey struct{}