github.com/nektos/act@v0.2.63/pkg/common/auth.go (about)

     1  // Copyright 2024 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package common
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"net/http"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/golang-jwt/jwt/v5"
    14  	log "github.com/sirupsen/logrus"
    15  )
    16  
    17  type actionsClaims struct {
    18  	jwt.RegisteredClaims
    19  	Scp    string `json:"scp"`
    20  	TaskID int64
    21  	RunID  int64
    22  	JobID  int64
    23  	Ac     string `json:"ac"`
    24  }
    25  
    26  type actionsCacheScope struct {
    27  	Scope      string
    28  	Permission actionsCachePermission
    29  }
    30  
    31  type actionsCachePermission int
    32  
    33  const (
    34  	actionsCachePermissionRead = 1 << iota
    35  	actionsCachePermissionWrite
    36  )
    37  
    38  func CreateAuthorizationToken(taskID, runID, jobID int64) (string, error) {
    39  	now := time.Now()
    40  
    41  	ac, err := json.Marshal(&[]actionsCacheScope{
    42  		{
    43  			Scope:      "",
    44  			Permission: actionsCachePermissionWrite,
    45  		},
    46  	})
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  
    51  	claims := actionsClaims{
    52  		RegisteredClaims: jwt.RegisteredClaims{
    53  			ExpiresAt: jwt.NewNumericDate(now.Add(24 * time.Hour)),
    54  			NotBefore: jwt.NewNumericDate(now),
    55  		},
    56  		Scp:    fmt.Sprintf("Actions.Results:%d:%d", runID, jobID),
    57  		TaskID: taskID,
    58  		RunID:  runID,
    59  		JobID:  jobID,
    60  		Ac:     string(ac),
    61  	}
    62  	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    63  
    64  	tokenString, err := token.SignedString([]byte{})
    65  	if err != nil {
    66  		return "", err
    67  	}
    68  
    69  	return tokenString, nil
    70  }
    71  
    72  func ParseAuthorizationToken(req *http.Request) (int64, error) {
    73  	h := req.Header.Get("Authorization")
    74  	if h == "" {
    75  		return 0, nil
    76  	}
    77  
    78  	parts := strings.SplitN(h, " ", 2)
    79  	if len(parts) != 2 {
    80  		log.Errorf("split token failed: %s", h)
    81  		return 0, fmt.Errorf("split token failed")
    82  	}
    83  
    84  	token, err := jwt.ParseWithClaims(parts[1], &actionsClaims{}, func(t *jwt.Token) (any, error) {
    85  		if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
    86  			return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
    87  		}
    88  		return []byte{}, nil
    89  	})
    90  	if err != nil {
    91  		return 0, err
    92  	}
    93  
    94  	c, ok := token.Claims.(*actionsClaims)
    95  	if !token.Valid || !ok {
    96  		return 0, fmt.Errorf("invalid token claim")
    97  	}
    98  
    99  	return c.TaskID, nil
   100  }