1
0

runtime: publish READER-VM130-PUT-INTERFACE-AUDIT-331

This commit is contained in:
homelab-runtime-publisher
2026-07-23 05:02:20 +00:00
parent 7e530890ca
commit 69539320f2
4 changed files with 240 additions and 75 deletions
@@ -0,0 +1,30 @@
{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "READER-VM130-PUT-INTERFACE-AUDIT-331",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "cluster-audit",
"started_at_utc": "2026-07-23T05:02:19Z",
"finished_at_utc": "2026-07-23T05:02:19Z",
"reference_register_checked": true,
"reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
"error_register_checked": true,
"error_register_sha256": "08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752",
"command_sha256": "e8c9b036754a539b1282f1d1a4f3c2e6aacd2c36db93f7ab61f759039c7b9dc3",
"duplicate_failed_command_blocked": false,
"block_reason": null,
"execution_started": true,
"changes_made": false,
"sanitized": true,
"secrets_included": false,
"private_addresses_included": false,
"raw_evidence_retained_locally": true,
"raw_evidence_sha256": "b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4",
"sanitized_output_sha256": "b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/test\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sha256sum\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/awk\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sed\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/bash\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/stat\nDETAIL=PUT_HELPER_SHA256=1166303044c104bcce68a5557b297ea034205ae8c497da7199e8a9f1cffc6bd8\nDETAIL=PUT_HELPER_INTEGRITY=PASS\nDETAIL=PUT_HELPER_METADATA=root:root|750|3227|regular file\nDETAIL=PUT_HELPER_FIRST_LINE=#!/usr/bin/bash\nDETAIL=PUT_HELPER_SYNTAX=PASS\nDETAIL=PUT_HELPER_LINE_COUNT=83\nDETAIL=PUT_HELPER_SOURCE_BEGIN\n#!/usr/bin/bash\nset -Eeuo pipefail\n\nreadonly VM_HELPER=/usr/local/sbin/homelab-vm130-exec\nreadonly VM_HELPER_SHA256=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275\nreadonly SSH=/usr/bin/ssh\nreadonly JQ=/usr/bin/jq\nreadonly SHA256SUM=/usr/bin/sha256sum\nreadonly STAT=/usr/bin/stat\nreadonly MKTEMP=/usr/bin/mktemp\nreadonly RM=/usr/bin/rm\nreadonly CAT=/usr/bin/cat\nreadonly HOST=root@pve03\nreadonly VMID=130\nreadonly MAX_SIZE=1048576\n\nfail() {\n printf 'VM130_PUT_ERROR=%s\\n' \"$1\" >&2\n exit \"${2:-1}\"\n}\n\n(( $# == 2 )) || fail USAGE 64\nsource_file=$1\nremote_name=$2\n\n[[ \"$remote_name\" =~ ^homelab-[A-Za-z0-9._-]{1,96}$ ]] || fail REMOTE_NAME 65\nremote_file=\"/tmp/$remote_name\"\n\n[[ -x \"$VM_HELPER\" ]] || fail VM_HELPER_MISSING 69\nactual_vm_sha=$(\"$SHA256SUM\" \"$VM_HELPER\" | /usr/bin/awk '{print $1}')\n[[ \"$actual_vm_sha\" == \"$VM_HELPER_SHA256\" ]] || fail VM_HELPER_INTEGRITY 70\n\n[[ -f \"$source_file\" && ! -L \"$source_file\" ]] || fail SOURCE_TYPE 66\nsource_meta=$(\"$STAT\" -c '%U:%G|%a|%s|%F' \"$source_file\")\nIFS='|' read -r source_owner source_mode source_size source_type <<<\"$source_meta\"\n[[ \"$source_owner\" == root:root && \"$source_mode\" == 600 && \"$source_type\" == regular*file ]] || fail SOURCE_METADATA 66\n[[ \"$source_size\" =~ ^[0-9]+$ ]] && (( source_size > 0 && source_size <= MAX_SIZE )) || fail SOURCE_SIZE 66\nsource_sha=$(\"$SHA256SUM\" \"$source_file\" | /usr/bin/awk '{print $1}')\n\nif \"$VM_HELPER\" /usr/bin/test -e \"$remote_file\"; then\n fail REMOTE_EXISTS 68\nfi\n\ntmpdir=$(\"$MKTEMP\" -d /tmp/homelab-vm130-put.XXXXXX)\nremote_created=NO\ncleanup() {\n rc=$?\n if [[ \"$remote_created\" == YES && \"$rc\" -ne 0 ]]; then\n \"$VM_HELPER\" /usr/bin/rm -f -- \"$remote_file\" >/dev/null 2>&1 || true\n fi\n \"$RM\" -rf -- \"$tmpdir\"\n}\ntrap cleanup EXIT\n\nprintf -v remote_cmd '%q ' /usr/sbin/qm guest exec \"$VMID\" --pass-stdin 1 -- /usr/bin/dd \"of=$remote_file\" status=none\nif raw=$(\"$SSH\" -o BatchMode=yes -o ConnectTimeout=8 \"$HOST\" \"$remote_cmd\" <\"$source_file\" 2>\"$tmpdir/ssh.err\"); then\n ssh_rc=0\nelse\n ssh_rc=$?\nfi\n(( ssh_rc == 0 )) || {\n \"$CAT\" \"$tmpdir/ssh.err\" >&2\n fail SSH_FAILURE 125\n}\n\"$JQ\" -e 'type==\"object\" and (.exited==1) and (.exitcode|type==\"number\")' <<<\"$raw\" >/dev/null 2>&1 || fail INVALID_QGA_JSON 126\nguest_rc=$(\"$JQ\" -r '.exitcode' <<<\"$raw\")\nguest_out=$(\"$JQ\" -r '.\"out-data\" // empty' <<<\"$raw\")\nguest_err=$(\"$JQ\" -r '.\"err-data\" // empty' <<<\"$raw\")\n[[ \"$guest_rc\" == 0 && -z \"$guest_out\" && -z \"$guest_err\" ]] || fail GUEST_WRITE 74\nremote_created=YES\n\n\"$VM_HELPER\" /usr/bin/chown root:root \"$remote_file\"\n\"$VM_HELPER\" /usr/bin/chmod 0600 \"$remote_file\"\nremote_meta=$(\"$VM_HELPER\" /usr/bin/stat -c '%U:%G|%a|%s|%F' \"$remote_file\")\nIFS='|' read -r remote_owner remote_mode remote_size remote_type <<<\"$remote_meta\"\n[[ \"$remote_owner\" == root:root && \"$remote_mode\" == 600 && \"$remote_size\" == \"$source_size\" && \"$remote_type\" == regular*file ]] || fail REMOTE_METADATA 74\nremote_sha=$(\"$VM_HELPER\" /usr/bin/sha256sum \"$remote_file\" | /usr/bin/awk '{print $1}')\n[[ \"$remote_sha\" == \"$source_sha\" ]] || fail REMOTE_INTEGRITY 74\n\nprintf 'VM130_PUT=READY\\n'\nprintf 'REMOTE_FILE=%s\\n' \"$remote_file\"\nprintf 'SIZE=%s\\n' \"$source_size\"\nprintf 'SHA256=%s\\n' \"$source_sha\"\nDETAIL=PUT_HELPER_SOURCE_END\nDETAIL=PUT_HELPER_SOURCE_TRUNCATED=NO\nCHANGES_MADE=NO\n"
}
@@ -0,0 +1,123 @@
CHAT_OUTPUT_BEGIN
COMMAND_ID=READER-VM130-PUT-INTERFACE-AUDIT-331
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=cluster-audit
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752
COMMAND_SHA256=e8c9b036754a539b1282f1d1a4f3c2e6aacd2c36db93f7ab61f759039c7b9dc3
DUPLICATE_FAILED_COMMAND_BLOCKED=false
EXECUTION_STARTED=true
CHANGES_MADE=false
SANITIZED=yes
SECRETS_INCLUDED=no
PRIVATE_ADDRESSES_INCLUDED=no
RAW_EVIDENCE_SHA256=b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4
SANITIZED_OUTPUT_SHA256=b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4
OUTPUT_BEGIN
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/test
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sha256sum
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/awk
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sed
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/bash
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/stat
DETAIL=PUT_HELPER_SHA256=1166303044c104bcce68a5557b297ea034205ae8c497da7199e8a9f1cffc6bd8
DETAIL=PUT_HELPER_INTEGRITY=PASS
DETAIL=PUT_HELPER_METADATA=root:root|750|3227|regular file
DETAIL=PUT_HELPER_FIRST_LINE=#!/usr/bin/bash
DETAIL=PUT_HELPER_SYNTAX=PASS
DETAIL=PUT_HELPER_LINE_COUNT=83
DETAIL=PUT_HELPER_SOURCE_BEGIN
#!/usr/bin/bash
set -Eeuo pipefail
readonly VM_HELPER=/usr/local/sbin/homelab-vm130-exec
readonly VM_HELPER_SHA256=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275
readonly SSH=/usr/bin/ssh
readonly JQ=/usr/bin/jq
readonly SHA256SUM=/usr/bin/sha256sum
readonly STAT=/usr/bin/stat
readonly MKTEMP=/usr/bin/mktemp
readonly RM=/usr/bin/rm
readonly CAT=/usr/bin/cat
readonly HOST=root@pve03
readonly VMID=130
readonly MAX_SIZE=1048576
fail() {
printf 'VM130_PUT_ERROR=%s\n' "$1" >&2
exit "${2:-1}"
}
(( $# == 2 )) || fail USAGE 64
source_file=$1
remote_name=$2
[[ "$remote_name" =~ ^homelab-[A-Za-z0-9._-]{1,96}$ ]] || fail REMOTE_NAME 65
remote_file="/tmp/$remote_name"
[[ -x "$VM_HELPER" ]] || fail VM_HELPER_MISSING 69
actual_vm_sha=$("$SHA256SUM" "$VM_HELPER" | /usr/bin/awk '{print $1}')
[[ "$actual_vm_sha" == "$VM_HELPER_SHA256" ]] || fail VM_HELPER_INTEGRITY 70
[[ -f "$source_file" && ! -L "$source_file" ]] || fail SOURCE_TYPE 66
source_meta=$("$STAT" -c '%U:%G|%a|%s|%F' "$source_file")
IFS='|' read -r source_owner source_mode source_size source_type <<<"$source_meta"
[[ "$source_owner" == root:root && "$source_mode" == 600 && "$source_type" == regular*file ]] || fail SOURCE_METADATA 66
[[ "$source_size" =~ ^[0-9]+$ ]] && (( source_size > 0 && source_size <= MAX_SIZE )) || fail SOURCE_SIZE 66
source_sha=$("$SHA256SUM" "$source_file" | /usr/bin/awk '{print $1}')
if "$VM_HELPER" /usr/bin/test -e "$remote_file"; then
fail REMOTE_EXISTS 68
fi
tmpdir=$("$MKTEMP" -d /tmp/homelab-vm130-put.XXXXXX)
remote_created=NO
cleanup() {
rc=$?
if [[ "$remote_created" == YES && "$rc" -ne 0 ]]; then
"$VM_HELPER" /usr/bin/rm -f -- "$remote_file" >/dev/null 2>&1 || true
fi
"$RM" -rf -- "$tmpdir"
}
trap cleanup EXIT
printf -v remote_cmd '%q ' /usr/sbin/qm guest exec "$VMID" --pass-stdin 1 -- /usr/bin/dd "of=$remote_file" status=none
if raw=$("$SSH" -o BatchMode=yes -o ConnectTimeout=8 "$HOST" "$remote_cmd" <"$source_file" 2>"$tmpdir/ssh.err"); then
ssh_rc=0
else
ssh_rc=$?
fi
(( ssh_rc == 0 )) || {
"$CAT" "$tmpdir/ssh.err" >&2
fail SSH_FAILURE 125
}
"$JQ" -e 'type=="object" and (.exited==1) and (.exitcode|type=="number")' <<<"$raw" >/dev/null 2>&1 || fail INVALID_QGA_JSON 126
guest_rc=$("$JQ" -r '.exitcode' <<<"$raw")
guest_out=$("$JQ" -r '."out-data" // empty' <<<"$raw")
guest_err=$("$JQ" -r '."err-data" // empty' <<<"$raw")
[[ "$guest_rc" == 0 && -z "$guest_out" && -z "$guest_err" ]] || fail GUEST_WRITE 74
remote_created=YES
"$VM_HELPER" /usr/bin/chown root:root "$remote_file"
"$VM_HELPER" /usr/bin/chmod 0600 "$remote_file"
remote_meta=$("$VM_HELPER" /usr/bin/stat -c '%U:%G|%a|%s|%F' "$remote_file")
IFS='|' read -r remote_owner remote_mode remote_size remote_type <<<"$remote_meta"
[[ "$remote_owner" == root:root && "$remote_mode" == 600 && "$remote_size" == "$source_size" && "$remote_type" == regular*file ]] || fail REMOTE_METADATA 74
remote_sha=$("$VM_HELPER" /usr/bin/sha256sum "$remote_file" | /usr/bin/awk '{print $1}')
[[ "$remote_sha" == "$source_sha" ]] || fail REMOTE_INTEGRITY 74
printf 'VM130_PUT=READY\n'
printf 'REMOTE_FILE=%s\n' "$remote_file"
printf 'SIZE=%s\n' "$source_size"
printf 'SHA256=%s\n' "$source_sha"
DETAIL=PUT_HELPER_SOURCE_END
DETAIL=PUT_HELPER_SOURCE_TRUNCATED=NO
CHANGES_MADE=NO
OUTPUT_END
CHAT_OUTPUT_END
+7 -7
View File
@@ -1,19 +1,19 @@
{
"schema_version": 1,
"channel": "homelab-runtime",
"command_id": "READER-CHANGE-GATE-INTERFACE-AUDIT-330",
"command_id": "READER-VM130-PUT-INTERFACE-AUDIT-331",
"status": "OK",
"rc": 0,
"host": "pve01",
"mode": "read-only",
"component": "cluster-audit",
"started_at_utc": "2026-07-23T05:00:00Z",
"finished_at_utc": "2026-07-23T05:00:00Z",
"started_at_utc": "2026-07-23T05:02:19Z",
"finished_at_utc": "2026-07-23T05:02:19Z",
"reference_register_checked": true,
"reference_sha256": "5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e",
"error_register_checked": true,
"error_register_sha256": "08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752",
"command_sha256": "0c6a6c62888e384581527e16d35802a1835bef622617b27a301d9077cc33f923",
"command_sha256": "e8c9b036754a539b1282f1d1a4f3c2e6aacd2c36db93f7ab61f759039c7b9dc3",
"duplicate_failed_command_blocked": false,
"block_reason": null,
"execution_started": true,
@@ -22,9 +22,9 @@
"secrets_included": false,
"private_addresses_included": false,
"raw_evidence_retained_locally": true,
"raw_evidence_sha256": "cccc50fe97b2ddc7711107f77a40cbebc700089145145f641d4ae62f19876fdd",
"sanitized_output_sha256": "1c4864ae4d0b36b1d2cf7d1376c7ffa5415174750f0eda9b0201fbb4bb84c1ac",
"raw_evidence_sha256": "b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4",
"sanitized_output_sha256": "b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4",
"output_truncated_in_json": false,
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
"output": "DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/test\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sha256sum\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/awk\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sed\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/bash\nDETAIL=CHANGE_GATE_SHA256=90470653345baac426d1ff6d3e3b1109a611ef7ba8d98b7453be0f732ced3597\nDETAIL=CHANGE_GATE_INTEGRITY=PASS\nDETAIL=CHANGE_GATE_SYNTAX=PASS\nDETAIL=CHANGE_GATE_LINE_COUNT=74\nDETAIL=CHANGE_GATE_SOURCE_BEGIN\n#!/usr/bin/bash\nset -Eeuo pipefail\n\nVM=/usr/local/sbin/homelab-vm130-exec\nNG=/usr/local/sbin/homelab-edge-nginx-exec\nVM_SHA=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275\nNG_SHA=f900b15bfdd19a1b543037cf8b9c1583e71dc8115bbb5812cf74d474e3e7859b\nTARGET=/opt/npmplus/custom_nginx/server_proxy.conf\nDIR=/opt/npmplus/custom_nginx\n\nfail() {\n printf 'CHANGE_GATE_ERROR=%s\\n' \"$1\" >&2\n exit \"${2:-1}\"\n}\n\n(( $# == 2 )) || fail USAGE 64\ncandidate=$1\nexpected_current=$2\n\n[[ \"$expected_current\" =~ ^[0-9a-f]{64}$ ]] || fail EXPECTED_SHA 65\n[[ -x \"$VM\" ]] || fail VM_MISSING 69\n[[ -x \"$NG\" ]] || fail NGINX_HELPER_MISSING 69\n[[ \"$(/usr/bin/sha256sum \"$VM\" | /usr/bin/awk '{print $1}')\" == \"$VM_SHA\" ]] || fail VM_INTEGRITY 70\n[[ \"$(/usr/bin/sha256sum \"$NG\" | /usr/bin/awk '{print $1}')\" == \"$NG_SHA\" ]] || fail NGINX_HELPER_INTEGRITY 70\n\n[[ -f \"$candidate\" && ! -L \"$candidate\" ]] || fail CANDIDATE_TYPE 66\nmeta=$(/usr/bin/stat -c '%U:%G|%a|%s' \"$candidate\")\nIFS='|' read -r owner mode size <<<\"$meta\"\n[[ \"$owner\" == root:root && \"$mode\" == 600 ]] || fail CANDIDATE_METADATA 66\n[[ \"$size\" =~ ^[0-9]+$ ]] && (( size > 0 && size <= 8192 )) || fail CANDIDATE_SIZE 66\n\ncap=$(/usr/bin/systemctl show homelab-reader-v3.service -p Environment --value |\n /usr/bin/sed -n 's/.*HOMELAB_READER_CAPABILITY=\\([^ ]*\\).*/\\1/p')\n[[ \"$cap\" =~ ^[0-9a-f]{64}$ ]] || fail CAPABILITY 67\n\ntmp=$(/usr/bin/mktemp)\ntrap '/usr/bin/rm -f -- \"$tmp\"' EXIT\n/usr/bin/printf '%s\\n' \\\n \"location ^~ /.well-known/homelab-reader/${cap}/ {\" \\\n \" proxy_pass http://[PRIVATE_IP]:18788/${cap}/;\" \\\n ' proxy_http_version 1.1;' \\\n ' proxy_set_header Host $host;' \\\n ' proxy_set_header Connection \"\";' \\\n ' proxy_buffering off;' \\\n ' proxy_cache off;' \\\n '}' >\"$tmp\"\n/usr/bin/cmp -s \"$candidate\" \"$tmp\" || fail CANDIDATE_CONTENT 66\ncandidate_sha=$(/usr/bin/sha256sum \"$candidate\" | /usr/bin/awk '{print $1}')\n\ntarget_meta=$(\"$VM\" /usr/bin/stat -c '%U:%G|%a|%F' \"$TARGET\")\nIFS='|' read -r target_owner target_mode target_type <<<\"$target_meta\"\n[[ \"$target_owner\" == root:root && \"$target_mode\" == 644 && \"$target_type\" == regular*file ]] || fail TARGET_METADATA 68\ncurrent_sha=$(\"$VM\" /usr/bin/sha256sum \"$TARGET\" | /usr/bin/awk '{print $1}')\n[[ \"$current_sha\" == \"$expected_current\" ]] || fail TARGET_CHANGED 68\n\ndir_meta=$(\"$VM\" /usr/bin/stat -c '%U:%G|%a|%F' \"$DIR\")\nIFS='|' read -r dir_owner dir_mode dir_type <<<\"$dir_meta\"\n[[ \"$dir_owner\" == root:root && \"$dir_mode\" == 755 && \"$dir_type\" == directory ]] || fail DIR_METADATA 68\n\"$VM\" /usr/bin/test -w \"$DIR\" || fail DIR_NOT_WRITABLE 68\n\n\"$NG\" /usr/local/bin/nginx -t >/dev/null 2>&1 || fail NGINX_CONFIG 69\n[[ \"$(/usr/bin/curl -fsS -m5 \"http://[PRIVATE_IP]:18788/${cap}/health\")\" == '{\"status\":\"ok\",\"version\":3}' ]] || fail LOCAL_READER 69\n[[ \"$(\"$VM\" /usr/bin/curl -fsS -m5 \"http://[PRIVATE_IP]:18788/${cap}/health\")\" == '{\"status\":\"ok\",\"version\":3}' ]] || fail EDGE_READER 69\n[[ \"$(/usr/bin/curl -sS -m8 --resolve git.gram1.ru:443:[PRIVATE_IP] -o /dev/null -w '%{http_code}' https://git.gram1.ru/)\" == 200 ]] || fail GITEA 69\n\nprintf 'CHANGE_GATE=READY\\n'\nprintf 'CANDIDATE_SHA256=%s\\n' \"$candidate_sha\"\nprintf 'CURRENT_SHA256=%s\\n' \"$current_sha\"\nprintf 'TARGET_METADATA=%s\\n' \"$target_meta\"\nprintf 'TARGET_DIRECTORY_METADATA=%s\\n' \"$dir_meta\"\nprintf 'NGINX_CURRENT_CONFIG=PASS\\n'\nprintf 'LOCAL_READER_CHECK=PASS\\n'\nprintf 'EDGE_READER_CHECK=PASS\\n'\nprintf 'GITEA_CHECK=PASS\\n'\nDETAIL=CHANGE_GATE_SOURCE_END\nDETAIL=CHANGE_GATE_SOURCE_TRUNCATED=NO\nCHANGES_MADE=NO\n"
"output": "DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/test\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sha256sum\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/awk\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sed\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/bash\nDETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/stat\nDETAIL=PUT_HELPER_SHA256=1166303044c104bcce68a5557b297ea034205ae8c497da7199e8a9f1cffc6bd8\nDETAIL=PUT_HELPER_INTEGRITY=PASS\nDETAIL=PUT_HELPER_METADATA=root:root|750|3227|regular file\nDETAIL=PUT_HELPER_FIRST_LINE=#!/usr/bin/bash\nDETAIL=PUT_HELPER_SYNTAX=PASS\nDETAIL=PUT_HELPER_LINE_COUNT=83\nDETAIL=PUT_HELPER_SOURCE_BEGIN\n#!/usr/bin/bash\nset -Eeuo pipefail\n\nreadonly VM_HELPER=/usr/local/sbin/homelab-vm130-exec\nreadonly VM_HELPER_SHA256=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275\nreadonly SSH=/usr/bin/ssh\nreadonly JQ=/usr/bin/jq\nreadonly SHA256SUM=/usr/bin/sha256sum\nreadonly STAT=/usr/bin/stat\nreadonly MKTEMP=/usr/bin/mktemp\nreadonly RM=/usr/bin/rm\nreadonly CAT=/usr/bin/cat\nreadonly HOST=root@pve03\nreadonly VMID=130\nreadonly MAX_SIZE=1048576\n\nfail() {\n printf 'VM130_PUT_ERROR=%s\\n' \"$1\" >&2\n exit \"${2:-1}\"\n}\n\n(( $# == 2 )) || fail USAGE 64\nsource_file=$1\nremote_name=$2\n\n[[ \"$remote_name\" =~ ^homelab-[A-Za-z0-9._-]{1,96}$ ]] || fail REMOTE_NAME 65\nremote_file=\"/tmp/$remote_name\"\n\n[[ -x \"$VM_HELPER\" ]] || fail VM_HELPER_MISSING 69\nactual_vm_sha=$(\"$SHA256SUM\" \"$VM_HELPER\" | /usr/bin/awk '{print $1}')\n[[ \"$actual_vm_sha\" == \"$VM_HELPER_SHA256\" ]] || fail VM_HELPER_INTEGRITY 70\n\n[[ -f \"$source_file\" && ! -L \"$source_file\" ]] || fail SOURCE_TYPE 66\nsource_meta=$(\"$STAT\" -c '%U:%G|%a|%s|%F' \"$source_file\")\nIFS='|' read -r source_owner source_mode source_size source_type <<<\"$source_meta\"\n[[ \"$source_owner\" == root:root && \"$source_mode\" == 600 && \"$source_type\" == regular*file ]] || fail SOURCE_METADATA 66\n[[ \"$source_size\" =~ ^[0-9]+$ ]] && (( source_size > 0 && source_size <= MAX_SIZE )) || fail SOURCE_SIZE 66\nsource_sha=$(\"$SHA256SUM\" \"$source_file\" | /usr/bin/awk '{print $1}')\n\nif \"$VM_HELPER\" /usr/bin/test -e \"$remote_file\"; then\n fail REMOTE_EXISTS 68\nfi\n\ntmpdir=$(\"$MKTEMP\" -d /tmp/homelab-vm130-put.XXXXXX)\nremote_created=NO\ncleanup() {\n rc=$?\n if [[ \"$remote_created\" == YES && \"$rc\" -ne 0 ]]; then\n \"$VM_HELPER\" /usr/bin/rm -f -- \"$remote_file\" >/dev/null 2>&1 || true\n fi\n \"$RM\" -rf -- \"$tmpdir\"\n}\ntrap cleanup EXIT\n\nprintf -v remote_cmd '%q ' /usr/sbin/qm guest exec \"$VMID\" --pass-stdin 1 -- /usr/bin/dd \"of=$remote_file\" status=none\nif raw=$(\"$SSH\" -o BatchMode=yes -o ConnectTimeout=8 \"$HOST\" \"$remote_cmd\" <\"$source_file\" 2>\"$tmpdir/ssh.err\"); then\n ssh_rc=0\nelse\n ssh_rc=$?\nfi\n(( ssh_rc == 0 )) || {\n \"$CAT\" \"$tmpdir/ssh.err\" >&2\n fail SSH_FAILURE 125\n}\n\"$JQ\" -e 'type==\"object\" and (.exited==1) and (.exitcode|type==\"number\")' <<<\"$raw\" >/dev/null 2>&1 || fail INVALID_QGA_JSON 126\nguest_rc=$(\"$JQ\" -r '.exitcode' <<<\"$raw\")\nguest_out=$(\"$JQ\" -r '.\"out-data\" // empty' <<<\"$raw\")\nguest_err=$(\"$JQ\" -r '.\"err-data\" // empty' <<<\"$raw\")\n[[ \"$guest_rc\" == 0 && -z \"$guest_out\" && -z \"$guest_err\" ]] || fail GUEST_WRITE 74\nremote_created=YES\n\n\"$VM_HELPER\" /usr/bin/chown root:root \"$remote_file\"\n\"$VM_HELPER\" /usr/bin/chmod 0600 \"$remote_file\"\nremote_meta=$(\"$VM_HELPER\" /usr/bin/stat -c '%U:%G|%a|%s|%F' \"$remote_file\")\nIFS='|' read -r remote_owner remote_mode remote_size remote_type <<<\"$remote_meta\"\n[[ \"$remote_owner\" == root:root && \"$remote_mode\" == 600 && \"$remote_size\" == \"$source_size\" && \"$remote_type\" == regular*file ]] || fail REMOTE_METADATA 74\nremote_sha=$(\"$VM_HELPER\" /usr/bin/sha256sum \"$remote_file\" | /usr/bin/awk '{print $1}')\n[[ \"$remote_sha\" == \"$source_sha\" ]] || fail REMOTE_INTEGRITY 74\n\nprintf 'VM130_PUT=READY\\n'\nprintf 'REMOTE_FILE=%s\\n' \"$remote_file\"\nprintf 'SIZE=%s\\n' \"$source_size\"\nprintf 'SHA256=%s\\n' \"$source_sha\"\nDETAIL=PUT_HELPER_SOURCE_END\nDETAIL=PUT_HELPER_SOURCE_TRUNCATED=NO\nCHANGES_MADE=NO\n"
}
+80 -68
View File
@@ -1,5 +1,5 @@
CHAT_OUTPUT_BEGIN
COMMAND_ID=READER-CHANGE-GATE-INTERFACE-AUDIT-330
COMMAND_ID=READER-VM130-PUT-INTERFACE-AUDIT-331
STATUS=OK
RC=0
HOST=pve01
@@ -9,102 +9,114 @@ REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752
COMMAND_SHA256=0c6a6c62888e384581527e16d35802a1835bef622617b27a301d9077cc33f923
COMMAND_SHA256=e8c9b036754a539b1282f1d1a4f3c2e6aacd2c36db93f7ab61f759039c7b9dc3
DUPLICATE_FAILED_COMMAND_BLOCKED=false
EXECUTION_STARTED=true
CHANGES_MADE=false
SANITIZED=yes
SECRETS_INCLUDED=no
PRIVATE_ADDRESSES_INCLUDED=no
RAW_EVIDENCE_SHA256=cccc50fe97b2ddc7711107f77a40cbebc700089145145f641d4ae62f19876fdd
SANITIZED_OUTPUT_SHA256=1c4864ae4d0b36b1d2cf7d1376c7ffa5415174750f0eda9b0201fbb4bb84c1ac
RAW_EVIDENCE_SHA256=b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4
SANITIZED_OUTPUT_SHA256=b8700f3f22291a9240833ee3553ab23c76aa5fb1d21c5659f330f36ffa8931f4
OUTPUT_BEGIN
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/test
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sha256sum
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/awk
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/sed
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/bash
DETAIL=CHANGE_GATE_SHA256=90470653345baac426d1ff6d3e3b1109a611ef7ba8d98b7453be0f732ced3597
DETAIL=CHANGE_GATE_INTEGRITY=PASS
DETAIL=CHANGE_GATE_SYNTAX=PASS
DETAIL=CHANGE_GATE_LINE_COUNT=74
DETAIL=CHANGE_GATE_SOURCE_BEGIN
DETAIL=LOCAL_DEPENDENCY=PASS:/usr/bin/stat
DETAIL=PUT_HELPER_SHA256=1166303044c104bcce68a5557b297ea034205ae8c497da7199e8a9f1cffc6bd8
DETAIL=PUT_HELPER_INTEGRITY=PASS
DETAIL=PUT_HELPER_METADATA=root:root|750|3227|regular file
DETAIL=PUT_HELPER_FIRST_LINE=#!/usr/bin/bash
DETAIL=PUT_HELPER_SYNTAX=PASS
DETAIL=PUT_HELPER_LINE_COUNT=83
DETAIL=PUT_HELPER_SOURCE_BEGIN
#!/usr/bin/bash
set -Eeuo pipefail
VM=/usr/local/sbin/homelab-vm130-exec
NG=/usr/local/sbin/homelab-edge-nginx-exec
VM_SHA=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275
NG_SHA=f900b15bfdd19a1b543037cf8b9c1583e71dc8115bbb5812cf74d474e3e7859b
TARGET=/opt/npmplus/custom_nginx/server_proxy.conf
DIR=/opt/npmplus/custom_nginx
readonly VM_HELPER=/usr/local/sbin/homelab-vm130-exec
readonly VM_HELPER_SHA256=1959773393723b013af7c93cd29a7b833fd607c903d044e2fcef6accaa29c275
readonly SSH=/usr/bin/ssh
readonly JQ=/usr/bin/jq
readonly SHA256SUM=/usr/bin/sha256sum
readonly STAT=/usr/bin/stat
readonly MKTEMP=/usr/bin/mktemp
readonly RM=/usr/bin/rm
readonly CAT=/usr/bin/cat
readonly HOST=root@pve03
readonly VMID=130
readonly MAX_SIZE=1048576
fail() {
printf 'CHANGE_GATE_ERROR=%s\n' "$1" >&2
printf 'VM130_PUT_ERROR=%s\n' "$1" >&2
exit "${2:-1}"
}
(( $# == 2 )) || fail USAGE 64
candidate=$1
expected_current=$2
source_file=$1
remote_name=$2
[[ "$expected_current" =~ ^[0-9a-f]{64}$ ]] || fail EXPECTED_SHA 65
[[ -x "$VM" ]] || fail VM_MISSING 69
[[ -x "$NG" ]] || fail NGINX_HELPER_MISSING 69
[[ "$(/usr/bin/sha256sum "$VM" | /usr/bin/awk '{print $1}')" == "$VM_SHA" ]] || fail VM_INTEGRITY 70
[[ "$(/usr/bin/sha256sum "$NG" | /usr/bin/awk '{print $1}')" == "$NG_SHA" ]] || fail NGINX_HELPER_INTEGRITY 70
[[ "$remote_name" =~ ^homelab-[A-Za-z0-9._-]{1,96}$ ]] || fail REMOTE_NAME 65
remote_file="/tmp/$remote_name"
[[ -f "$candidate" && ! -L "$candidate" ]] || fail CANDIDATE_TYPE 66
meta=$(/usr/bin/stat -c '%U:%G|%a|%s' "$candidate")
IFS='|' read -r owner mode size <<<"$meta"
[[ "$owner" == root:root && "$mode" == 600 ]] || fail CANDIDATE_METADATA 66
[[ "$size" =~ ^[0-9]+$ ]] && (( size > 0 && size <= 8192 )) || fail CANDIDATE_SIZE 66
[[ -x "$VM_HELPER" ]] || fail VM_HELPER_MISSING 69
actual_vm_sha=$("$SHA256SUM" "$VM_HELPER" | /usr/bin/awk '{print $1}')
[[ "$actual_vm_sha" == "$VM_HELPER_SHA256" ]] || fail VM_HELPER_INTEGRITY 70
cap=$(/usr/bin/systemctl show homelab-reader-v3.service -p Environment --value |
/usr/bin/sed -n 's/.*HOMELAB_READER_CAPABILITY=\([^ ]*\).*/\1/p')
[[ "$cap" =~ ^[0-9a-f]{64}$ ]] || fail CAPABILITY 67
[[ -f "$source_file" && ! -L "$source_file" ]] || fail SOURCE_TYPE 66
source_meta=$("$STAT" -c '%U:%G|%a|%s|%F' "$source_file")
IFS='|' read -r source_owner source_mode source_size source_type <<<"$source_meta"
[[ "$source_owner" == root:root && "$source_mode" == 600 && "$source_type" == regular*file ]] || fail SOURCE_METADATA 66
[[ "$source_size" =~ ^[0-9]+$ ]] && (( source_size > 0 && source_size <= MAX_SIZE )) || fail SOURCE_SIZE 66
source_sha=$("$SHA256SUM" "$source_file" | /usr/bin/awk '{print $1}')
tmp=$(/usr/bin/mktemp)
trap '/usr/bin/rm -f -- "$tmp"' EXIT
/usr/bin/printf '%s\n' \
"location ^~ /.well-known/homelab-reader/${cap}/ {" \
" proxy_pass http://[PRIVATE_IP]:18788/${cap}/;" \
' proxy_http_version 1.1;' \
' proxy_set_header Host $host;' \
' proxy_set_header Connection "";' \
' proxy_buffering off;' \
' proxy_cache off;' \
'}' >"$tmp"
/usr/bin/cmp -s "$candidate" "$tmp" || fail CANDIDATE_CONTENT 66
candidate_sha=$(/usr/bin/sha256sum "$candidate" | /usr/bin/awk '{print $1}')
if "$VM_HELPER" /usr/bin/test -e "$remote_file"; then
fail REMOTE_EXISTS 68
fi
target_meta=$("$VM" /usr/bin/stat -c '%U:%G|%a|%F' "$TARGET")
IFS='|' read -r target_owner target_mode target_type <<<"$target_meta"
[[ "$target_owner" == root:root && "$target_mode" == 644 && "$target_type" == regular*file ]] || fail TARGET_METADATA 68
current_sha=$("$VM" /usr/bin/sha256sum "$TARGET" | /usr/bin/awk '{print $1}')
[[ "$current_sha" == "$expected_current" ]] || fail TARGET_CHANGED 68
tmpdir=$("$MKTEMP" -d /tmp/homelab-vm130-put.XXXXXX)
remote_created=NO
cleanup() {
rc=$?
if [[ "$remote_created" == YES && "$rc" -ne 0 ]]; then
"$VM_HELPER" /usr/bin/rm -f -- "$remote_file" >/dev/null 2>&1 || true
fi
"$RM" -rf -- "$tmpdir"
}
trap cleanup EXIT
dir_meta=$("$VM" /usr/bin/stat -c '%U:%G|%a|%F' "$DIR")
IFS='|' read -r dir_owner dir_mode dir_type <<<"$dir_meta"
[[ "$dir_owner" == root:root && "$dir_mode" == 755 && "$dir_type" == directory ]] || fail DIR_METADATA 68
"$VM" /usr/bin/test -w "$DIR" || fail DIR_NOT_WRITABLE 68
printf -v remote_cmd '%q ' /usr/sbin/qm guest exec "$VMID" --pass-stdin 1 -- /usr/bin/dd "of=$remote_file" status=none
if raw=$("$SSH" -o BatchMode=yes -o ConnectTimeout=8 "$HOST" "$remote_cmd" <"$source_file" 2>"$tmpdir/ssh.err"); then
ssh_rc=0
else
ssh_rc=$?
fi
(( ssh_rc == 0 )) || {
"$CAT" "$tmpdir/ssh.err" >&2
fail SSH_FAILURE 125
}
"$JQ" -e 'type=="object" and (.exited==1) and (.exitcode|type=="number")' <<<"$raw" >/dev/null 2>&1 || fail INVALID_QGA_JSON 126
guest_rc=$("$JQ" -r '.exitcode' <<<"$raw")
guest_out=$("$JQ" -r '."out-data" // empty' <<<"$raw")
guest_err=$("$JQ" -r '."err-data" // empty' <<<"$raw")
[[ "$guest_rc" == 0 && -z "$guest_out" && -z "$guest_err" ]] || fail GUEST_WRITE 74
remote_created=YES
"$NG" /usr/local/bin/nginx -t >/dev/null 2>&1 || fail NGINX_CONFIG 69
[[ "$(/usr/bin/curl -fsS -m5 "http://[PRIVATE_IP]:18788/${cap}/health")" == '{"status":"ok","version":3}' ]] || fail LOCAL_READER 69
[[ "$("$VM" /usr/bin/curl -fsS -m5 "http://[PRIVATE_IP]:18788/${cap}/health")" == '{"status":"ok","version":3}' ]] || fail EDGE_READER 69
[[ "$(/usr/bin/curl -sS -m8 --resolve git.gram1.ru:443:[PRIVATE_IP] -o /dev/null -w '%{http_code}' https://git.gram1.ru/)" == 200 ]] || fail GITEA 69
"$VM_HELPER" /usr/bin/chown root:root "$remote_file"
"$VM_HELPER" /usr/bin/chmod 0600 "$remote_file"
remote_meta=$("$VM_HELPER" /usr/bin/stat -c '%U:%G|%a|%s|%F' "$remote_file")
IFS='|' read -r remote_owner remote_mode remote_size remote_type <<<"$remote_meta"
[[ "$remote_owner" == root:root && "$remote_mode" == 600 && "$remote_size" == "$source_size" && "$remote_type" == regular*file ]] || fail REMOTE_METADATA 74
remote_sha=$("$VM_HELPER" /usr/bin/sha256sum "$remote_file" | /usr/bin/awk '{print $1}')
[[ "$remote_sha" == "$source_sha" ]] || fail REMOTE_INTEGRITY 74
printf 'CHANGE_GATE=READY\n'
printf 'CANDIDATE_SHA256=%s\n' "$candidate_sha"
printf 'CURRENT_SHA256=%s\n' "$current_sha"
printf 'TARGET_METADATA=%s\n' "$target_meta"
printf 'TARGET_DIRECTORY_METADATA=%s\n' "$dir_meta"
printf 'NGINX_CURRENT_CONFIG=PASS\n'
printf 'LOCAL_READER_CHECK=PASS\n'
printf 'EDGE_READER_CHECK=PASS\n'
printf 'GITEA_CHECK=PASS\n'
DETAIL=CHANGE_GATE_SOURCE_END
DETAIL=CHANGE_GATE_SOURCE_TRUNCATED=NO
printf 'VM130_PUT=READY\n'
printf 'REMOTE_FILE=%s\n' "$remote_file"
printf 'SIZE=%s\n' "$source_size"
printf 'SHA256=%s\n' "$source_sha"
DETAIL=PUT_HELPER_SOURCE_END
DETAIL=PUT_HELPER_SOURCE_TRUNCATED=NO
CHANGES_MADE=NO
OUTPUT_END