feat(backend): add script interpreters
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/grpcsrv/commander"
|
||||
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/models"
|
||||
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/repository"
|
||||
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ScriptHandlers struct {
|
||||
svc *service.ScriptService
|
||||
cmder *commander.Commander
|
||||
}
|
||||
|
||||
func NewScriptHandlers(svc *service.ScriptService, cmder *commander.Commander) ScriptHandlers {
|
||||
return ScriptHandlers{svc: svc, cmder: cmder}
|
||||
}
|
||||
|
||||
// RunScript executes a script on a target agent.
|
||||
// @Summary Run a script on an agent
|
||||
// @Description Resolves interpreter argv[] and sends the full command to the agent
|
||||
// @Tags scripts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body RunScriptIn true "Script request"
|
||||
// @Success 201 {object} RunScriptOut
|
||||
// @Router /scripts/run [post]
|
||||
func (self *ScriptHandlers) RunScript(c *gin.Context) {
|
||||
err := func() error {
|
||||
type RunScriptIn struct {
|
||||
AgentID string `json:"agent_id" binding:"required"`
|
||||
InterpreterID int64 `json:"interpreter_id" binding:"required"`
|
||||
ScriptText string `json:"script_text" binding:"required"`
|
||||
Stdin *string `json:"stdin"`
|
||||
}
|
||||
var in RunScriptIn
|
||||
if err := c.Bind(&in); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command, err := self.svc.ResolveCommand(c.Request.Context(), in.InterpreterID, in.ScriptText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agent, ok := self.cmder.GetAgent(in.AgentID)
|
||||
if !ok {
|
||||
c.Status(http.StatusNotFound)
|
||||
return fmt.Errorf("agent not found")
|
||||
}
|
||||
|
||||
jid, err := agent.AddJob(models.JobForInsert{
|
||||
Command: command,
|
||||
Stdin: in.Stdin,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
job, err := agent.WaitJob(jid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type RunScriptOut struct {
|
||||
ID int64 `json:"id"`
|
||||
Command []string `json:"command"`
|
||||
Stdin *string `json:"stdin"`
|
||||
Stdout string `json:"stdout"`
|
||||
Stderr string `json:"stderr"`
|
||||
Status int32 `json:"status"`
|
||||
}
|
||||
c.JSON(http.StatusCreated, RunScriptOut{
|
||||
ID: job.ID,
|
||||
Command: job.Command,
|
||||
Stdin: job.Stdin,
|
||||
Stdout: job.Stdout,
|
||||
Stderr: job.Stderr,
|
||||
Status: job.Status,
|
||||
})
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ListInterpreters returns all registered script interpreters.
|
||||
// @Summary List interpreters
|
||||
// @Description Returns all script interpreters available in the system
|
||||
// @Tags scripts
|
||||
// @Produce json
|
||||
// @Success 200 {array} repository.ScriptInterpreter
|
||||
// @Router /scripts/interpreters [get]
|
||||
func (self *ScriptHandlers) ListInterpreters(c *gin.Context) {
|
||||
interpreters, err := self.svc.List(c.Request.Context())
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, interpreters)
|
||||
}
|
||||
|
||||
// CreateInterpreter registers a new script interpreter.
|
||||
// @Summary Create interpreter
|
||||
// @Description Registers a new script interpreter with name, label, and argv
|
||||
// @Tags scripts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body repository.ScriptInterpreterCreate true "Interpreter definition"
|
||||
// @Success 201 {object} repository.ScriptInterpreter
|
||||
// @Router /scripts/interpreters [post]
|
||||
func (self *ScriptHandlers) CreateInterpreter(c *gin.Context) {
|
||||
var in repository.ScriptInterpreterCreate
|
||||
if err := c.BindJSON(&in); err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
si, err := self.svc.Create(c.Request.Context(), in)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, si)
|
||||
}
|
||||
|
||||
// GetInterpreter returns a single interpreter by ID.
|
||||
// @Summary Get interpreter
|
||||
// @Description Returns a script interpreter by ID
|
||||
// @Tags scripts
|
||||
// @Produce json
|
||||
// @Param id path int true "Interpreter ID"
|
||||
// @Success 200 {object} repository.ScriptInterpreter
|
||||
// @Router /scripts/interpreters/:id [get]
|
||||
func (self *ScriptHandlers) GetInterpreter(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
si, err := self.svc.GetByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, si)
|
||||
}
|
||||
|
||||
// UpdateInterpreter updates an interpreter.
|
||||
// @Summary Update interpreter
|
||||
// @Description Updates fields of a script interpreter
|
||||
// @Tags scripts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Interpreter ID"
|
||||
// @Param body body repository.ScriptInterpreterUpdate true "Interpreter fields"
|
||||
// @Success 200 {object} repository.ScriptInterpreter
|
||||
// @Router /scripts/interpreters/:id [put]
|
||||
func (self *ScriptHandlers) UpdateInterpreter(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
var in repository.ScriptInterpreterUpdate
|
||||
if err := c.BindJSON(&in); err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
si, err := self.svc.Update(c.Request.Context(), id, in)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, si)
|
||||
}
|
||||
|
||||
// DeleteInterpreter removes an interpreter.
|
||||
// @Summary Delete interpreter
|
||||
// @Description Removes a script interpreter by ID
|
||||
// @Tags scripts
|
||||
// @Param id path int true "Interpreter ID"
|
||||
// @Success 204
|
||||
// @Router /scripts/interpreters/:id [delete]
|
||||
func (self *ScriptHandlers) DeleteInterpreter(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := self.svc.Delete(c.Request.Context(), id); err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
Reference in New Issue
Block a user