mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-10-24 08:33:38 +00:00
fix: manual host creation and improve host identification
- Add machine_id support for manual host creation from GUI
- Generate temporary 'pending-{uuid}' machine_id for new hosts
- Agent now collects and sends machine_id on every update
- Backend replaces pending machine_id with real one on first agent connection
- Remove unnecessary duplicate name check (friendly_name can be duplicated)
- Add get_machine_id() function to agent (reads from /etc/machine-id, /var/lib/dbus/machine-id, or generates fallback)
- Display IP address in Network tab on host details page
- Fix network tab visibility conditions to include host.ip
This ensures proper host identification using machine_id while maintaining backwards compatibility with API credentials as the primary authentication method.
This commit is contained in:
@@ -56,6 +56,28 @@ warning() {
|
|||||||
log "WARNING: $1"
|
log "WARNING: $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Get or generate machine ID
|
||||||
|
get_machine_id() {
|
||||||
|
# Try standard locations for machine-id
|
||||||
|
if [[ -f /etc/machine-id ]]; then
|
||||||
|
cat /etc/machine-id
|
||||||
|
elif [[ -f /var/lib/dbus/machine-id ]]; then
|
||||||
|
cat /var/lib/dbus/machine-id
|
||||||
|
else
|
||||||
|
# Fallback: generate from hardware UUID or hostname+MAC
|
||||||
|
if command -v dmidecode &> /dev/null; then
|
||||||
|
local uuid=$(dmidecode -s system-uuid 2>/dev/null | tr -d ' -' | tr '[:upper:]' '[:lower:]')
|
||||||
|
if [[ -n "$uuid" && "$uuid" != "notpresent" ]]; then
|
||||||
|
echo "$uuid"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Last resort: hash hostname + primary MAC address
|
||||||
|
local primary_mac=$(ip link show | grep -oP '(?<=link/ether\s)[0-9a-f:]+' | head -1 | tr -d ':')
|
||||||
|
echo "$HOSTNAME-$primary_mac" | sha256sum | cut -d' ' -f1 | cut -c1-32
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Check if running as root
|
# Check if running as root
|
||||||
check_root() {
|
check_root() {
|
||||||
if [[ $EUID -ne 0 ]]; then
|
if [[ $EUID -ne 0 ]]; then
|
||||||
@@ -865,6 +887,9 @@ send_update() {
|
|||||||
|
|
||||||
# Merge all JSON objects into one
|
# Merge all JSON objects into one
|
||||||
local merged_json=$(echo "$hardware_json $network_json $system_json" | jq -s '.[0] * .[1] * .[2]')
|
local merged_json=$(echo "$hardware_json $network_json $system_json" | jq -s '.[0] * .[1] * .[2]')
|
||||||
|
# Get machine ID
|
||||||
|
local machine_id=$(get_machine_id)
|
||||||
|
|
||||||
# Create the base payload and merge with system info
|
# Create the base payload and merge with system info
|
||||||
local base_payload=$(cat <<EOF
|
local base_payload=$(cat <<EOF
|
||||||
{
|
{
|
||||||
@@ -875,7 +900,8 @@ send_update() {
|
|||||||
"hostname": "$HOSTNAME",
|
"hostname": "$HOSTNAME",
|
||||||
"ip": "$IP_ADDRESS",
|
"ip": "$IP_ADDRESS",
|
||||||
"architecture": "$ARCHITECTURE",
|
"architecture": "$ARCHITECTURE",
|
||||||
"agentVersion": "$AGENT_VERSION"
|
"agentVersion": "$AGENT_VERSION",
|
||||||
|
"machineId": "$machine_id"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -172,15 +172,6 @@ router.post(
|
|||||||
// Generate unique API credentials for this host
|
// Generate unique API credentials for this host
|
||||||
const { apiId, apiKey } = generateApiCredentials();
|
const { apiId, apiKey } = generateApiCredentials();
|
||||||
|
|
||||||
// Check if host already exists
|
|
||||||
const existingHost = await prisma.hosts.findUnique({
|
|
||||||
where: { friendly_name: friendly_name },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingHost) {
|
|
||||||
return res.status(409).json({ error: "Host already exists" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// If hostGroupId is provided, verify the group exists
|
// If hostGroupId is provided, verify the group exists
|
||||||
if (hostGroupId) {
|
if (hostGroupId) {
|
||||||
const hostGroup = await prisma.host_groups.findUnique({
|
const hostGroup = await prisma.host_groups.findUnique({
|
||||||
@@ -196,6 +187,7 @@ router.post(
|
|||||||
const host = await prisma.hosts.create({
|
const host = await prisma.hosts.create({
|
||||||
data: {
|
data: {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
|
machine_id: `pending-${uuidv4()}`, // Temporary placeholder until agent connects with real machine_id
|
||||||
friendly_name: friendly_name,
|
friendly_name: friendly_name,
|
||||||
os_type: "unknown", // Will be updated when agent connects
|
os_type: "unknown", // Will be updated when agent connects
|
||||||
os_version: "unknown", // Will be updated when agent connects
|
os_version: "unknown", // Will be updated when agent connects
|
||||||
@@ -321,6 +313,10 @@ router.post(
|
|||||||
.optional()
|
.optional()
|
||||||
.isArray()
|
.isArray()
|
||||||
.withMessage("Load average must be an array"),
|
.withMessage("Load average must be an array"),
|
||||||
|
body("machineId")
|
||||||
|
.optional()
|
||||||
|
.isString()
|
||||||
|
.withMessage("Machine ID must be a string"),
|
||||||
],
|
],
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
@@ -338,6 +334,11 @@ router.post(
|
|||||||
updated_at: new Date(),
|
updated_at: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update machine_id if provided and current one is a placeholder
|
||||||
|
if (req.body.machineId && host.machine_id.startsWith("pending-")) {
|
||||||
|
updateData.machine_id = req.body.machineId;
|
||||||
|
}
|
||||||
|
|
||||||
// Basic system info
|
// Basic system info
|
||||||
if (req.body.osType) updateData.os_type = req.body.osType;
|
if (req.body.osType) updateData.os_type = req.body.osType;
|
||||||
if (req.body.osVersion) updateData.os_version = req.body.osVersion;
|
if (req.body.osVersion) updateData.os_version = req.body.osVersion;
|
||||||
|
|||||||
@@ -466,11 +466,23 @@ const HostDetail = () => {
|
|||||||
|
|
||||||
{/* Network Information */}
|
{/* Network Information */}
|
||||||
{activeTab === "network" &&
|
{activeTab === "network" &&
|
||||||
(host.gateway_ip ||
|
(host.ip ||
|
||||||
|
host.gateway_ip ||
|
||||||
host.dns_servers ||
|
host.dns_servers ||
|
||||||
host.network_interfaces) && (
|
host.network_interfaces) && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{host.ip && (
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-secondary-500 dark:text-secondary-300">
|
||||||
|
IP Address
|
||||||
|
</p>
|
||||||
|
<p className="font-medium text-secondary-900 dark:text-white font-mono text-sm">
|
||||||
|
{host.ip}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{host.gateway_ip && (
|
{host.gateway_ip && (
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-secondary-500 dark:text-secondary-300">
|
<p className="text-xs text-secondary-500 dark:text-secondary-300">
|
||||||
@@ -802,6 +814,7 @@ const HostDetail = () => {
|
|||||||
|
|
||||||
{activeTab === "network" &&
|
{activeTab === "network" &&
|
||||||
!(
|
!(
|
||||||
|
host.ip ||
|
||||||
host.gateway_ip ||
|
host.gateway_ip ||
|
||||||
host.dns_servers ||
|
host.dns_servers ||
|
||||||
host.network_interfaces
|
host.network_interfaces
|
||||||
|
|||||||
Reference in New Issue
Block a user