|
| 1 | +#cloud-config |
| 2 | +# hardbox cloud-init user-data template — Microsoft Azure (Virtual Machines) |
| 3 | +# |
| 4 | +# Usage: |
| 5 | +# Pass this file as custom-data when creating an Azure VM: |
| 6 | +# az vm create \ |
| 7 | +# --name my-vm \ |
| 8 | +# --custom-data cloud-init/azure-user-data.yaml \ |
| 9 | +# ... |
| 10 | +# |
| 11 | +# Note: Azure passes custom-data as base64; the az CLI handles encoding automatically. |
| 12 | +# For ARM templates, base64-encode the file content in the customData property. |
| 13 | +# |
| 14 | +# Variables (customise before use): |
| 15 | +# HARDBOX_VERSION : hardbox release tag (default: latest) |
| 16 | +# HARDBOX_PROFILE : compliance profile to apply (default: cloud-azure) |
| 17 | +# HARDBOX_REPORT_CONTAINER : Azure Blob Storage container URI for reports |
| 18 | +# (e.g. https://myaccount.blob.core.windows.net/hardbox/) |
| 19 | +# HARDBOX_SCHEDULE : systemd timer interval for re-hardening (default: daily) |
| 20 | +# |
| 21 | +# Requirements: |
| 22 | +# - VM managed identity must have Storage Blob Data Contributor role on the container |
| 23 | +# - Instance must have internet access or Private Endpoint to download hardbox |
| 24 | +# - Azure Monitor Agent recommended for forwarding hardbox logs to Log Analytics |
| 25 | + |
| 26 | +write_files: |
| 27 | + - path: /etc/hardbox/cloud-init.env |
| 28 | + permissions: "0640" |
| 29 | + owner: root:root |
| 30 | + content: | |
| 31 | + HARDBOX_VERSION=latest |
| 32 | + HARDBOX_PROFILE=cloud-azure |
| 33 | + HARDBOX_REPORT_CONTAINER=https://CHANGE-ME.blob.core.windows.net/hardbox/ |
| 34 | + HARDBOX_SCHEDULE=daily |
| 35 | + HARDBOX_INSTALL_DIR=/usr/local/bin |
| 36 | + HARDBOX_REPORT_DIR=/var/lib/hardbox/reports |
| 37 | + CLOUD_PROVIDER=azure |
| 38 | +
|
| 39 | + - path: /usr/local/lib/hardbox/install.sh |
| 40 | + permissions: "0750" |
| 41 | + owner: root:root |
| 42 | + content: | |
| 43 | + #!/bin/bash |
| 44 | + # hardbox installer with checksum verification |
| 45 | + set -euo pipefail |
| 46 | + source /etc/hardbox/cloud-init.env |
| 47 | +
|
| 48 | + ARCH=$(uname -m) |
| 49 | + case "$ARCH" in |
| 50 | + x86_64) GOARCH="amd64" ;; |
| 51 | + aarch64) GOARCH="arm64" ;; |
| 52 | + *) echo "Unsupported architecture: $ARCH"; exit 1 ;; |
| 53 | + esac |
| 54 | +
|
| 55 | + if [ "$HARDBOX_VERSION" = "latest" ]; then |
| 56 | + HARDBOX_VERSION=$(curl -fsSL \ |
| 57 | + "https://api.github.com/repos/jackby03/hardbox/releases/latest" \ |
| 58 | + | grep '"tag_name"' | cut -d'"' -f4) |
| 59 | + fi |
| 60 | +
|
| 61 | + BASE_URL="https://github.com/jackby03/hardbox/releases/download/${HARDBOX_VERSION}" |
| 62 | + BINARY="hardbox_Linux_${GOARCH}" |
| 63 | + CHECKSUM_FILE="hardbox_${HARDBOX_VERSION#v}_checksums.txt" |
| 64 | +
|
| 65 | + echo "Installing hardbox ${HARDBOX_VERSION} (${GOARCH})..." |
| 66 | + curl -fsSL "${BASE_URL}/${BINARY}" -o /tmp/hardbox |
| 67 | + curl -fsSL "${BASE_URL}/${CHECKSUM_FILE}" -o /tmp/hardbox_checksums.txt |
| 68 | +
|
| 69 | + # Verify checksum |
| 70 | + EXPECTED=$(grep "${BINARY}" /tmp/hardbox_checksums.txt | awk '{print $1}') |
| 71 | + ACTUAL=$(sha256sum /tmp/hardbox | awk '{print $1}') |
| 72 | + if [ "$EXPECTED" != "$ACTUAL" ]; then |
| 73 | + echo "Checksum mismatch! Expected: $EXPECTED, Got: $ACTUAL" >&2 |
| 74 | + exit 1 |
| 75 | + fi |
| 76 | +
|
| 77 | + install -m 0755 /tmp/hardbox "${HARDBOX_INSTALL_DIR}/hardbox" |
| 78 | + rm -f /tmp/hardbox /tmp/hardbox_checksums.txt |
| 79 | + echo "hardbox installed: $(hardbox version)" |
| 80 | +
|
| 81 | + - path: /usr/local/lib/hardbox/harden.sh |
| 82 | + permissions: "0750" |
| 83 | + owner: root:root |
| 84 | + content: | |
| 85 | + #!/bin/bash |
| 86 | + # hardbox apply + report upload to Azure Blob Storage |
| 87 | + set -euo pipefail |
| 88 | + source /etc/hardbox/cloud-init.env |
| 89 | +
|
| 90 | + mkdir -p "${HARDBOX_REPORT_DIR}" |
| 91 | + TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ) |
| 92 | +
|
| 93 | + # Retrieve VM metadata from Azure IMDS |
| 94 | + IMDS_BASE="http://169.254.169.254/metadata/instance" |
| 95 | + VM_NAME=$(curl -fsSL "${IMDS_BASE}/compute/name?api-version=2021-02-01&format=text" \ |
| 96 | + -H "Metadata:true" 2>/dev/null || echo "unknown") |
| 97 | + RESOURCE_GROUP=$(curl -fsSL \ |
| 98 | + "${IMDS_BASE}/compute/resourceGroupName?api-version=2021-02-01&format=text" \ |
| 99 | + -H "Metadata:true" 2>/dev/null || echo "unknown") |
| 100 | + REPORT_FILE="${HARDBOX_REPORT_DIR}/hardbox-${VM_NAME}-${TIMESTAMP}.html" |
| 101 | +
|
| 102 | + echo "Applying hardbox profile: ${HARDBOX_PROFILE}" |
| 103 | + hardbox apply \ |
| 104 | + --profile "${HARDBOX_PROFILE}" \ |
| 105 | + --format html \ |
| 106 | + --output "${REPORT_FILE}" \ |
| 107 | + --non-interactive |
| 108 | +
|
| 109 | + # Upload report to Azure Blob Storage via managed identity (az cli) |
| 110 | + if [ "${HARDBOX_REPORT_CONTAINER}" != "https://CHANGE-ME.blob.core.windows.net/hardbox/" ]; then |
| 111 | + if command -v az &>/dev/null; then |
| 112 | + echo "Uploading report to ${HARDBOX_REPORT_CONTAINER}" |
| 113 | + az storage blob upload \ |
| 114 | + --blob-url "${HARDBOX_REPORT_CONTAINER}${RESOURCE_GROUP}/${VM_NAME}/${TIMESTAMP}.html" \ |
| 115 | + --file "${REPORT_FILE}" \ |
| 116 | + --auth-mode login \ |
| 117 | + --overwrite \ |
| 118 | + --no-progress |
| 119 | + echo "Report uploaded successfully" |
| 120 | + else |
| 121 | + echo "Warning: az CLI not available; skipping blob upload" >&2 |
| 122 | + fi |
| 123 | + fi |
| 124 | +
|
| 125 | + logger -t hardbox \ |
| 126 | + "hardbox apply complete — profile=${HARDBOX_PROFILE} vm=${VM_NAME} rg=${RESOURCE_GROUP}" |
| 127 | +
|
| 128 | + - path: /etc/systemd/system/hardbox-harden.service |
| 129 | + permissions: "0644" |
| 130 | + owner: root:root |
| 131 | + content: | |
| 132 | + [Unit] |
| 133 | + Description=hardbox system hardening |
| 134 | + After=network-online.target walinuxagent.service |
| 135 | + Wants=network-online.target |
| 136 | +
|
| 137 | + [Service] |
| 138 | + Type=oneshot |
| 139 | + ExecStart=/usr/local/lib/hardbox/harden.sh |
| 140 | + StandardOutput=journal |
| 141 | + StandardError=journal |
| 142 | + SyslogIdentifier=hardbox |
| 143 | +
|
| 144 | + - path: /etc/systemd/system/hardbox-harden.timer |
| 145 | + permissions: "0644" |
| 146 | + owner: root:root |
| 147 | + content: | |
| 148 | + [Unit] |
| 149 | + Description=hardbox periodic re-hardening timer |
| 150 | + Requires=hardbox-harden.service |
| 151 | +
|
| 152 | + [Timer] |
| 153 | + OnBootSec=2min |
| 154 | + OnCalendar=daily |
| 155 | + Persistent=true |
| 156 | +
|
| 157 | + [Install] |
| 158 | + WantedBy=timers.target |
| 159 | +
|
| 160 | +runcmd: |
| 161 | + # Install hardbox binary with checksum verification |
| 162 | + - /usr/local/lib/hardbox/install.sh |
| 163 | + |
| 164 | + # Enable and start systemd timer for periodic re-hardening |
| 165 | + - systemctl daemon-reload |
| 166 | + - systemctl enable hardbox-harden.timer |
| 167 | + - systemctl start hardbox-harden.timer |
| 168 | + |
| 169 | + # Run initial hardening immediately |
| 170 | + - systemctl start hardbox-harden.service |
0 commit comments