78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package artifacts
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// run, job, err
|
|
func JobInfo() (string, string, error) {
|
|
rt := os.Getenv("ACTIONS_RUNTIME_TOKEN")
|
|
var empty string
|
|
if rt == "" {
|
|
return empty, empty, fmt.Errorf("env ACTIONS_RUNTIME_TOKEN is only available from the context of an action")
|
|
}
|
|
jt, err := newJwtDecode(rt)
|
|
if err != nil {
|
|
return empty, empty, err
|
|
}
|
|
scp, ok := jt.Payload["scp"].(string)
|
|
if !ok {
|
|
return empty, empty, fmt.Errorf("no scp in ACTIONS_RUNTIME_TOKEN")
|
|
}
|
|
for _, scopes := range strings.Split(scp, " ") {
|
|
parts := strings.Split(scopes, ":")
|
|
if parts[0] != "Actions.Results" {
|
|
continue
|
|
}
|
|
if len(parts) != 3 {
|
|
return empty, empty, fmt.Errorf("invalid scp in ACTIONS_RUNTIME_TOKEN")
|
|
}
|
|
return parts[1], parts[2], nil
|
|
}
|
|
|
|
return empty, empty, fmt.Errorf("no backend ids found")
|
|
}
|
|
|
|
type jwt struct {
|
|
Header map[string]any
|
|
Payload map[string]any
|
|
Signature string
|
|
}
|
|
|
|
func newJwtDecode(token string) (*jwt, error) {
|
|
parts := strings.Split(token, ".")
|
|
if len(parts) != 3 {
|
|
return nil, fmt.Errorf("invalid JWT: expected 3 segments")
|
|
}
|
|
|
|
decode := func(seg string) ([]byte, error) {
|
|
if l := len(seg) % 4; l != 0 {
|
|
seg += strings.Repeat("=", 4-l)
|
|
}
|
|
return base64.URLEncoding.DecodeString(seg)
|
|
}
|
|
|
|
headerBytes, err := decode(parts[0])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid JWT header: %v", err)
|
|
}
|
|
var header map[string]any
|
|
if err := json.Unmarshal(headerBytes, &header); err != nil {
|
|
return nil, fmt.Errorf("invalid JWT header json: %v", err)
|
|
}
|
|
|
|
payloadBytes, err := decode(parts[1])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid JWT payload: %v", err)
|
|
}
|
|
var payload map[string]any
|
|
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
|
|
return nil, fmt.Errorf("invalid JWT payload json: %v", err)
|
|
}
|
|
|
|
return &jwt{Header: header, Payload: payload, Signature: parts[2]}, nil
|
|
}
|