mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-19 14:08:34 +00:00
fixed tfa route for handling insertion of tfa number
Better handling of existing systems already enrolled, done via checking if the config.yml file exists and ping through its credentials as opposed to checking for machine_ID UI justification improvements on repositories pages
This commit is contained in:
@@ -311,6 +311,37 @@ else
|
||||
mkdir -p /etc/patchmon
|
||||
fi
|
||||
|
||||
# Check if agent is already configured and working (before we overwrite anything)
|
||||
info "🔍 Checking if agent is already configured..."
|
||||
|
||||
if [[ -f /etc/patchmon/config.yml ]] && [[ -f /etc/patchmon/credentials.yml ]]; then
|
||||
if [[ -f /usr/local/bin/patchmon-agent ]]; then
|
||||
info "📋 Found existing agent configuration"
|
||||
info "🧪 Testing existing configuration with ping..."
|
||||
|
||||
if /usr/local/bin/patchmon-agent ping >/dev/null 2>&1; then
|
||||
success "✅ Agent is already configured and ping successful"
|
||||
info "📋 Existing configuration is working - skipping installation"
|
||||
info ""
|
||||
info "If you want to reinstall, remove the configuration files first:"
|
||||
info " sudo rm -f /etc/patchmon/config.yml /etc/patchmon/credentials.yml"
|
||||
echo ""
|
||||
exit 0
|
||||
else
|
||||
warning "⚠️ Agent configuration exists but ping failed"
|
||||
warning "⚠️ Will move existing configuration and reinstall"
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
warning "⚠️ Configuration files exist but agent binary is missing"
|
||||
warning "⚠️ Will move existing configuration and reinstall"
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
success "✅ Agent not yet configured - proceeding with installation"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 2: Create configuration files
|
||||
info "🔐 Creating configuration files..."
|
||||
|
||||
@@ -426,33 +457,6 @@ if [[ -f "/etc/patchmon/logs/patchmon-agent.log" ]]; then
|
||||
fi
|
||||
|
||||
# Step 4: Test the configuration
|
||||
# Check if this machine is already enrolled
|
||||
info "🔍 Checking if machine is already enrolled..."
|
||||
existing_check=$(curl $CURL_FLAGS -s -X POST \
|
||||
-H "X-API-ID: $API_ID" \
|
||||
-H "X-API-KEY: $API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"machine_id\": \"$MACHINE_ID\"}" \
|
||||
"$PATCHMON_URL/api/v1/hosts/check-machine-id" \
|
||||
-w "\n%{http_code}" 2>&1)
|
||||
|
||||
http_code=$(echo "$existing_check" | tail -n 1)
|
||||
response_body=$(echo "$existing_check" | sed '$d')
|
||||
|
||||
if [[ "$http_code" == "200" ]]; then
|
||||
already_enrolled=$(echo "$response_body" | jq -r '.exists' 2>/dev/null || echo "false")
|
||||
if [[ "$already_enrolled" == "true" ]]; then
|
||||
warning "⚠️ This machine is already enrolled in PatchMon"
|
||||
info "Machine ID: $MACHINE_ID"
|
||||
info "Existing host: $(echo "$response_body" | jq -r '.host.friendly_name' 2>/dev/null)"
|
||||
info ""
|
||||
info "The agent will be reinstalled/updated with existing credentials."
|
||||
echo ""
|
||||
else
|
||||
success "✅ Machine not yet enrolled - proceeding with installation"
|
||||
fi
|
||||
fi
|
||||
|
||||
info "🧪 Testing API credentials and connectivity..."
|
||||
if /usr/local/bin/patchmon-agent ping; then
|
||||
success "✅ TEST: API credentials are valid and server is reachable"
|
||||
|
||||
@@ -230,6 +230,40 @@ while IFS= read -r line; do
|
||||
|
||||
info " ✓ Host enrolled successfully: $api_id"
|
||||
|
||||
# Check if agent is already installed and working
|
||||
info " Checking if agent is already configured..."
|
||||
config_check=$(timeout 10 pct exec "$vmid" -- bash -c "
|
||||
if [[ -f /etc/patchmon/config.yml ]] && [[ -f /etc/patchmon/credentials.yml ]]; then
|
||||
if [[ -f /usr/local/bin/patchmon-agent ]]; then
|
||||
# Try to ping using existing configuration
|
||||
if /usr/local/bin/patchmon-agent ping >/dev/null 2>&1; then
|
||||
echo 'ping_success'
|
||||
else
|
||||
echo 'ping_failed'
|
||||
fi
|
||||
else
|
||||
echo 'binary_missing'
|
||||
fi
|
||||
else
|
||||
echo 'not_configured'
|
||||
fi
|
||||
" 2>/dev/null </dev/null || echo "error")
|
||||
|
||||
if [[ "$config_check" == "ping_success" ]]; then
|
||||
info " ✓ Host already enrolled and agent ping successful - skipping"
|
||||
((skipped_count++)) || true
|
||||
echo ""
|
||||
continue
|
||||
elif [[ "$config_check" == "ping_failed" ]]; then
|
||||
warn " ⚠ Agent configuration exists but ping failed - will reinstall"
|
||||
elif [[ "$config_check" == "binary_missing" ]]; then
|
||||
warn " ⚠ Config exists but agent binary missing - will reinstall"
|
||||
elif [[ "$config_check" == "not_configured" ]]; then
|
||||
info " ℹ Agent not yet configured - proceeding with installation"
|
||||
else
|
||||
warn " ⚠ Could not check agent status - proceeding with installation"
|
||||
fi
|
||||
|
||||
# Ensure curl is installed in the container
|
||||
info " Checking for curl in container..."
|
||||
curl_check=$(timeout 10 pct exec "$vmid" -- bash -c "command -v curl >/dev/null 2>&1 && echo 'installed' || echo 'missing'" 2>/dev/null </dev/null || echo "error")
|
||||
@@ -283,9 +317,10 @@ while IFS= read -r line; do
|
||||
install_exit_code=0
|
||||
|
||||
# Download and execute in separate steps to avoid stdin issues with piping
|
||||
install_output=$(timeout 180 pct exec "$vmid" -- bash -c "
|
||||
# Pass CURL_FLAGS as environment variable to container
|
||||
install_output=$(timeout 180 pct exec "$vmid" --env CURL_FLAGS="$CURL_FLAGS" -- bash -c "
|
||||
cd /tmp
|
||||
curl $CURL_FLAGS \
|
||||
curl \$CURL_FLAGS \
|
||||
-H \"X-API-ID: $api_id\" \
|
||||
-H \"X-API-KEY: $api_key\" \
|
||||
-o patchmon-install.sh \
|
||||
@@ -422,9 +457,10 @@ if [[ ${#dpkg_error_containers[@]} -gt 0 ]]; then
|
||||
info " Retrying agent installation..."
|
||||
|
||||
install_exit_code=0
|
||||
install_output=$(timeout 180 pct exec "$vmid" -- bash -c "
|
||||
# Pass CURL_FLAGS as environment variable to container
|
||||
install_output=$(timeout 180 pct exec "$vmid" --env CURL_FLAGS="$CURL_FLAGS" -- bash -c "
|
||||
cd /tmp
|
||||
curl $CURL_FLAGS \
|
||||
curl \$CURL_FLAGS \
|
||||
-H \"X-API-ID: $api_id\" \
|
||||
-H \"X-API-KEY: $api_key\" \
|
||||
-o patchmon-install.sh \
|
||||
|
||||
@@ -60,9 +60,14 @@ router.post(
|
||||
authenticateToken,
|
||||
[
|
||||
body("token")
|
||||
.notEmpty()
|
||||
.withMessage("Token is required")
|
||||
.isString()
|
||||
.withMessage("Token must be a string")
|
||||
.isLength({ min: 6, max: 6 })
|
||||
.withMessage("Token must be 6 digits"),
|
||||
body("token").isNumeric().withMessage("Token must contain only numbers"),
|
||||
.withMessage("Token must be exactly 6 digits")
|
||||
.matches(/^\d{6}$/)
|
||||
.withMessage("Token must contain only numbers"),
|
||||
],
|
||||
async (req, res) => {
|
||||
try {
|
||||
@@ -71,7 +76,11 @@ router.post(
|
||||
return res.status(400).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
const { token } = req.body;
|
||||
// Ensure token is a string (convert if needed)
|
||||
let { token } = req.body;
|
||||
if (typeof token !== "string") {
|
||||
token = String(token);
|
||||
}
|
||||
const userId = req.user.id;
|
||||
|
||||
// Get user's TFA secret
|
||||
|
||||
@@ -237,8 +237,14 @@ const Repositories = () => {
|
||||
|
||||
// Handle special cases
|
||||
if (sortField === "security") {
|
||||
aValue = a.isSecure ? "Secure" : "Insecure";
|
||||
bValue = b.isSecure ? "Secure" : "Insecure";
|
||||
// Use the same logic as filtering to determine isSecure
|
||||
const aIsSecure =
|
||||
a.isSecure !== undefined ? a.isSecure : a.url.startsWith("https://");
|
||||
const bIsSecure =
|
||||
b.isSecure !== undefined ? b.isSecure : b.url.startsWith("https://");
|
||||
// Sort by boolean: true (Secure) comes before false (Insecure) when ascending
|
||||
aValue = aIsSecure ? 1 : 0;
|
||||
bValue = bIsSecure ? 1 : 0;
|
||||
} else if (sortField === "status") {
|
||||
aValue = a.is_active ? "Active" : "Inactive";
|
||||
bValue = b.is_active ? "Active" : "Inactive";
|
||||
@@ -535,12 +541,12 @@ const Repositories = () => {
|
||||
{visibleColumns.map((column) => (
|
||||
<th
|
||||
key={column.id}
|
||||
className="px-4 py-2 text-center text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider"
|
||||
className="px-4 py-2 text-left text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSort(column.id)}
|
||||
className="flex items-center gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors"
|
||||
className="flex items-center justify-start gap-1 hover:text-secondary-700 dark:hover:text-secondary-200 transition-colors"
|
||||
>
|
||||
{column.label}
|
||||
{getSortIcon(column.id)}
|
||||
@@ -559,7 +565,7 @@ const Repositories = () => {
|
||||
{visibleColumns.map((column) => (
|
||||
<td
|
||||
key={column.id}
|
||||
className="px-4 py-2 whitespace-nowrap text-center"
|
||||
className="px-4 py-2 whitespace-nowrap text-left"
|
||||
>
|
||||
{renderCellContent(column, repo)}
|
||||
</td>
|
||||
@@ -622,7 +628,7 @@ const Repositories = () => {
|
||||
? repo.isSecure
|
||||
: repo.url.startsWith("https://");
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="flex items-center justify-start">
|
||||
{isSecure ? (
|
||||
<div className="flex items-center gap-1 text-green-600">
|
||||
<Lock className="h-4 w-4" />
|
||||
@@ -651,14 +657,14 @@ const Repositories = () => {
|
||||
);
|
||||
case "hostCount":
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-1 text-sm text-secondary-900 dark:text-white">
|
||||
<div className="flex items-center justify-start gap-1 text-sm text-secondary-900 dark:text-white">
|
||||
<Server className="h-4 w-4" />
|
||||
<span>{repo.hostCount}</span>
|
||||
</div>
|
||||
);
|
||||
case "actions":
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="flex items-center justify-start">
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => handleDeleteRepository(repo, e)}
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "patchmon",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "patchmon",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"license": "AGPL-3.0",
|
||||
"workspaces": [
|
||||
"backend",
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"backend": {
|
||||
"name": "patchmon-backend",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@bull-board/api": "^6.13.1",
|
||||
@@ -59,7 +59,7 @@
|
||||
},
|
||||
"frontend": {
|
||||
"name": "patchmon-frontend",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.2",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
|
||||
Reference in New Issue
Block a user