2024-02-02 15:25:59 +01:00
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"fmt"
"net/http"
"strings"
"time"
2024-03-05 18:34:42 +01:00
"code.gitea.io/gitea/modules/json"
2024-02-02 15:25:59 +01:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/golang-jwt/jwt/v5"
)
type actionsClaims struct {
jwt . RegisteredClaims
Scp string ` json:"scp" `
TaskID int64
RunID int64
JobID int64
2024-03-05 18:34:42 +01:00
Ac string ` json:"ac" `
2024-02-02 15:25:59 +01:00
}
2024-03-05 18:34:42 +01:00
type actionsCacheScope struct {
Scope string
Permission actionsCachePermission
}
type actionsCachePermission int
const (
actionsCachePermissionRead = 1 << iota
actionsCachePermissionWrite
)
2024-02-02 15:25:59 +01:00
func CreateAuthorizationToken ( taskID , runID , jobID int64 ) ( string , error ) {
now := time . Now ( )
2024-03-05 18:34:42 +01:00
ac , err := json . Marshal ( & [ ] actionsCacheScope {
{
Scope : "" ,
Permission : actionsCachePermissionWrite ,
} ,
} )
if err != nil {
return "" , err
}
2024-02-02 15:25:59 +01:00
claims := actionsClaims {
RegisteredClaims : jwt . RegisteredClaims {
ExpiresAt : jwt . NewNumericDate ( now . Add ( 24 * time . Hour ) ) ,
NotBefore : jwt . NewNumericDate ( now ) ,
} ,
Scp : fmt . Sprintf ( "Actions.Results:%d:%d" , runID , jobID ) ,
2024-03-05 18:34:42 +01:00
Ac : string ( ac ) ,
2024-02-02 15:25:59 +01:00
TaskID : taskID ,
RunID : runID ,
JobID : jobID ,
}
token := jwt . NewWithClaims ( jwt . SigningMethodHS256 , claims )
2024-02-19 01:39:04 +08:00
tokenString , err := token . SignedString ( setting . GetGeneralTokenSigningSecret ( ) )
2024-02-02 15:25:59 +01:00
if err != nil {
return "" , err
}
return tokenString , nil
}
func ParseAuthorizationToken ( req * http . Request ) ( int64 , error ) {
h := req . Header . Get ( "Authorization" )
if h == "" {
return 0 , nil
}
parts := strings . SplitN ( h , " " , 2 )
if len ( parts ) != 2 {
log . Error ( "split token failed: %s" , h )
return 0 , fmt . Errorf ( "split token failed" )
}
2024-11-20 09:24:09 -06:00
return TokenToTaskID ( parts [ 1 ] )
}
// TokenToTaskID returns the TaskID associated with the provided JWT token
func TokenToTaskID ( token string ) ( int64 , error ) {
parsedToken , err := jwt . ParseWithClaims ( token , & actionsClaims { } , func ( t * jwt . Token ) ( any , error ) {
2024-02-02 15:25:59 +01:00
if _ , ok := t . Method . ( * jwt . SigningMethodHMAC ) ; ! ok {
return nil , fmt . Errorf ( "unexpected signing method: %v" , t . Header [ "alg" ] )
}
2024-02-19 01:39:04 +08:00
return setting . GetGeneralTokenSigningSecret ( ) , nil
2024-02-02 15:25:59 +01:00
} )
if err != nil {
return 0 , err
}
2024-11-20 09:24:09 -06:00
c , ok := parsedToken . Claims . ( * actionsClaims )
if ! parsedToken . Valid || ! ok {
2024-02-02 15:25:59 +01:00
return 0 , fmt . Errorf ( "invalid token claim" )
}
return c . TaskID , nil
}