added status of agents to the webui

This commit is contained in:
Stefan Friese 2025-01-27 16:00:52 +00:00
parent c0764ac41d
commit 0498013d1d
8 changed files with 106 additions and 54 deletions

View File

@ -60,7 +60,6 @@ func registerAgent(agentName, agentId, agentIp, agentType string) error {
return nil
}
func connectToWebSocket(agentName, agentId, agentIp, agentType string) error {
wsURL := fmt.Sprintf("ws://%s/data?agentName=%s&agentId=%s&IPv4Address=%s&agentType=%s", webSocketAddr, url.QueryEscape(agentName), url.QueryEscape(agentId), url.QueryEscape(agentIp), url.QueryEscape(agentType))
var err error

29
main.go
View File

@ -15,6 +15,7 @@ import (
"syscall"
"gontrol/src/randomname"
"gontrol/src/server/database"
api "gontrol/src/server/api"
websocketserver "gontrol/src/server/websocket"
@ -53,19 +54,19 @@ func init() {
tmpl, _ = template.ParseGlob("templates/*.html")
}
func initDB (dbUser string, dbPassword string, dbHost string, dbPort int16, dbName string ) {
var err error
dbOpen := fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbUser,dbPassword, dbHost, dbPort, dbName)
db, err = sql.Open("mysql", dbOpen)
if err != nil {
log.Fatal(err)
}
// func initDB (dbUser string, dbPassword string, dbHost string, dbPort int16, dbName string ) {
// var err error
// dbOpen := fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbUser,dbPassword, dbHost, dbPort, dbName)
// db, err = sql.Open("mysql", dbOpen)
// if err != nil {
// log.Fatal(err)
// }
if err = db.Ping(); err != nil {
log.Fatal(err)
}
log.Println("Connected to database")
}
// if err = db.Ping(); err != nil {
// log.Fatal(err)
// }
// log.Println("Connected to database")
// }
func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
t, err := template.ParseFiles(tmpl)
@ -134,7 +135,6 @@ func getAgentIds(w http.ResponseWriter, r *http.Request) {
return
}
func main() {
var cfg Config
@ -154,7 +154,8 @@ func main() {
webMux.HandleFunc("/agentIds", getAgentIds)
webMux.HandleFunc("/agents/{agentId}", agentsHandler)
initDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
// initDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
db = database.InitDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
defer db.Close()
name := randomname.GenerateRandomName()
fmt.Println(name)

View File

@ -164,6 +164,6 @@ func GetAgentIds(db *sql.DB, w http.ResponseWriter, r *http.Request) {
agentIds = append(agentIds, strconv.Itoa(id))
}
w.Header().Set("Content-Type", "application/json")
// ocket.go.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(agentIds)
}

View File

@ -0,0 +1,26 @@
package database
import (
"fmt"
"log"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func InitDB (dbUser string, dbPassword string, dbHost string, dbPort int16, dbName string ) *sql.DB {
var db *sql.DB
var err error
dbOpen := fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbUser,dbPassword, dbHost, dbPort, dbName)
db, err = sql.Open("mysql", dbOpen)
if err != nil {
log.Fatal(err)
}
if err = db.Ping(); err != nil {
log.Fatal(err)
}
log.Println("Connected to database")
return db
}

View File

View File

@ -38,6 +38,9 @@ var getAgentNames http.HandlerFunc = func(w http.ResponseWriter, r *http.Request
agentSocketsMutex.Unlock()
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
json.NewEncoder(w).Encode(agentNames)
}

View File

@ -9,14 +9,6 @@
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<!-- <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> -->
<title>g2: gommand & gontrol</title>
<script>
document.body.addEventListener('htmx:afterRequest', (evt) => {
console.log(evt.detail.xhr.responseText);
});
document.body.addEventListener('htmx:responseError', (evt) => {
console.error(evt.detail.xhr.responseText);
});
</script>
<script>
document.addEventListener('DOMContentLoaded', () => {
fetch('/agentNames')
@ -31,26 +23,59 @@
});
})
.catch(error => console.error('Error fetching agent names:', error));
const socket = new WebSocket("ws://localhost:5555/executeCommand");
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'response') {
const output = document.getElementById('commandOutput');
output.textContent = "";
output.innerText = message.payload.trim();
console.log("Raw websocket Data:", event.data);
}
};
socket.onerror = (error) => {
console.error("Websocket error:", error);
};
socket.onclose = () => {
console.warn('Websocket connection closed.');
};
fetch('http://localhost:5555/agentNames')
.then(response => {
console.log('Fetch response status:', response.status);
return response.json();
})
.then(agentNames => {
console.log('Connected agent names:', agentNames);
// Your existing logic here
})
.catch(error => {
console.error('Error fetching agent names:', error);
});
const tableRows = document.querySelectorAll('#agentList table tbody tr');
console.log('Number of rows found:', tableRows.length);
tableRows.forEach((row, index) => {
const nameCell = row.querySelector('td[data-column="Name"]');
const statusCell = row.querySelector('td[data-column="Status"]');
console.log(`Row ${index + 1} - Name: ${nameCell?.textContent}, Status Cell Found: ${!!statusCell}`);
});
});
const updateAgentStatuses = () => {
fetch('http://localhost:5555/agentNames')
.then(response => response.json())
.then(agentNames => {
console.log("Agent names fetched:", agentNames);
// Get all rows in the table body
const tableRows = document.querySelectorAll('#agentList table tbody tr');
// Loop through each row to find the Name and update Status
tableRows.forEach(row => {
const nameCell = row.querySelector('td:nth-child(2)'); // Name is in the second column
const statusCell = row.querySelector('td:nth-child(5)'); // Status is in the fifth column
if (nameCell && statusCell) {
const agentName = nameCell.textContent.trim();
if (agentNames.includes(agentName)) {
statusCell.innerHTML = '<span class="badge bg-success">Connected</span>';
} else {
statusCell.innerHTML = '<span class="badge bg-danger">Disconnected</span>';
}
}
});
})
.catch(error => console.error('Error fetching agent names:', error));
};
// Initial call to update statuses
updateAgentStatuses();
// Set the function to run every 5 seconds
setInterval(updateAgentStatuses, 5000);
</script>
</head>
<body>
@ -60,6 +85,7 @@
<h2>Agents</h2>
<!-- Agent List -->
<!-- <div id="agentList" hx-get="/agents" hx-trigger="load, every 2s" hx-swap="innerHTML"></div> -->
<div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div>
<!-- Agent Commands -->
<div id="agentCommands">
@ -80,13 +106,6 @@
<pre id="commandOutput"></pre>
</div>
<!-- <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 -->
<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">

View File

@ -5,8 +5,9 @@
<th>Name</th>
<th>Type</th>
<th>IPv4 Address</th>
<th>Initial Contact</th>
<th>Last Contact</th>
<!-- <th>Initial Contact</th> -->
<!-- <th>Last Contact</th> -->
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
@ -17,8 +18,11 @@
<td>{{.AgentName}}</td>
<td>{{.AgentType}}</td>
<td>{{.IPv4Address}}</td>
<td>{{.InitialContact}}</td>
<td>{{.LastContact}}</td>
<!-- <td>{{.InitialContact}}</td> -->
<!-- <td>{{.LastContact}}</td> -->
<!-- <td><span class="badge bg-success">Connected</span></td> -->
<!-- <td><span class="badge bg-danger">Disconnected</span></td> -->
<td></td>
<td>
<button class="btn btn-warning" hx-get="/agents/{{.AgentID}}" hx-target="#agentDetails" hx-swap="innerHTML">View</button>