All checks were successful
Build (artifact) / build (push) Has been skipped
74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
package executor
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"os"
|
||
"os/exec"
|
||
"syscall"
|
||
"time"
|
||
|
||
"git.nevets.tech/Steven/certman/common"
|
||
pb "git.nevets.tech/Steven/certman/proto/v1"
|
||
)
|
||
|
||
type hookServer struct {
|
||
pb.UnimplementedHookServiceServer
|
||
}
|
||
|
||
func (s *hookServer) ExecuteHook(ctx context.Context, req *pb.ExecuteHookRequest) (*pb.ExecuteHookResponse, error) {
|
||
h := req.GetHook()
|
||
if h == nil {
|
||
return &pb.ExecuteHookResponse{Error: "missing hook"}, nil
|
||
}
|
||
|
||
// Minimal validation
|
||
if len(h.GetCommand()) == 0 {
|
||
return &pb.ExecuteHookResponse{Error: "command is empty"}, nil
|
||
}
|
||
|
||
// Timeout
|
||
timeout := time.Duration(h.GetTimeoutSeconds()) * time.Second
|
||
if timeout <= 0 {
|
||
timeout = 30 * time.Second
|
||
}
|
||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||
defer cancel()
|
||
|
||
// Build command
|
||
cmdArgs := h.GetCommand()
|
||
cmd := exec.CommandContext(ctx, cmdArgs[0], cmdArgs[1:]...)
|
||
if cwd := h.GetCwd(); cwd != "" {
|
||
cmd.Dir = cwd
|
||
}
|
||
|
||
// Env: inherit current + overlay provided
|
||
env := os.Environ()
|
||
for k, v := range h.GetEnv() {
|
||
env = append(env, k+"="+v)
|
||
}
|
||
cmd.Env = env
|
||
|
||
// Run as user/group if specified (Linux/Unix)
|
||
if h.GetUser() != "" || h.GetGroup() != "" {
|
||
cred, err := common.MakeCredential(h.GetUser(), h.GetGroup())
|
||
if err != nil {
|
||
return &pb.ExecuteHookResponse{Error: brief(err)}, nil
|
||
}
|
||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||
Credential: cred,
|
||
}
|
||
}
|
||
|
||
// We’re intentionally NOT returning stdout/stderr; only a brief error on failure.
|
||
if err := cmd.Run(); err != nil {
|
||
// If context deadline hit, make the error message short and explicit.
|
||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||
return &pb.ExecuteHookResponse{Error: "hook timed out"}, nil
|
||
}
|
||
return &pb.ExecuteHookResponse{Error: brief(err)}, nil
|
||
}
|
||
|
||
return &pb.ExecuteHookResponse{Error: ""}, nil
|
||
}
|