summaryrefslogtreecommitdiffstats
path: root/routers/api/actions/runner/interceptor.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--routers/api/actions/runner/interceptor.go80
1 files changed, 80 insertions, 0 deletions
diff --git a/routers/api/actions/runner/interceptor.go b/routers/api/actions/runner/interceptor.go
new file mode 100644
index 0000000..521ba91
--- /dev/null
+++ b/routers/api/actions/runner/interceptor.go
@@ -0,0 +1,80 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package runner
+
+import (
+ "context"
+ "crypto/subtle"
+ "errors"
+ "strings"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ auth_model "code.gitea.io/gitea/models/auth"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/modules/util"
+
+ "connectrpc.com/connect"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+const (
+ uuidHeaderKey = "x-runner-uuid"
+ tokenHeaderKey = "x-runner-token"
+)
+
+var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unaryFunc connect.UnaryFunc) connect.UnaryFunc {
+ return func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
+ methodName := getMethodName(request)
+ if methodName == "Register" {
+ return unaryFunc(ctx, request)
+ }
+ uuid := request.Header().Get(uuidHeaderKey)
+ token := request.Header().Get(tokenHeaderKey)
+
+ runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
+ if err != nil {
+ if errors.Is(err, util.ErrNotExist) {
+ return nil, status.Error(codes.Unauthenticated, "unregistered runner")
+ }
+ return nil, status.Error(codes.Internal, err.Error())
+ }
+ if subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))) != 1 {
+ return nil, status.Error(codes.Unauthenticated, "unregistered runner")
+ }
+
+ cols := []string{"last_online"}
+ runner.LastOnline = timeutil.TimeStampNow()
+ if methodName == "UpdateTask" || methodName == "UpdateLog" {
+ runner.LastActive = timeutil.TimeStampNow()
+ cols = append(cols, "last_active")
+ }
+ if err := actions_model.UpdateRunner(ctx, runner, cols...); err != nil {
+ log.Error("can't update runner status: %v", err)
+ }
+
+ ctx = context.WithValue(ctx, runnerCtxKey{}, runner)
+ return unaryFunc(ctx, request)
+ }
+}))
+
+func getMethodName(req connect.AnyRequest) string {
+ splits := strings.Split(req.Spec().Procedure, "/")
+ if len(splits) > 0 {
+ return splits[len(splits)-1]
+ }
+ return ""
+}
+
+type runnerCtxKey struct{}
+
+func GetRunner(ctx context.Context) *actions_model.ActionRunner {
+ if v := ctx.Value(runnerCtxKey{}); v != nil {
+ if r, ok := v.(*actions_model.ActionRunner); ok {
+ return r
+ }
+ }
+ return nil
+}