feat: streamline platform and secure data access
- move the relational data center to MySQL and a standalone workbench\n- add Interface Center API credentials, policies, logs, and DBeaver SSH guidance\n- harden authentication and deployment while retiring unused management surfaces
This commit is contained in:
1 parent
15368f2779
commit
3dd5731751
137 files changed
+8571
-14151
No files matched your search
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
umask 077
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
||||
BACKUP_ROOT="${DATA_BACKUP_ROOT:-${PROJECT_DIR}/backups/mysql}"
|
||||
PASSPHRASE_FILE="${DATA_BACKUP_PASSPHRASE_FILE:-}"
|
||||
|
||||
if [[ -z "${PASSPHRASE_FILE}" || ! -f "${PASSPHRASE_FILE}" || ! -r "${PASSPHRASE_FILE}" ]]; then
|
||||
echo "DATA_BACKUP_PASSPHRASE_FILE 必须指向可读的独立密钥文件" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ "$(wc -c < "${PASSPHRASE_FILE}" | tr -d ' ')" -lt 32 ]]; then
|
||||
echo "备份加密口令文件内容不能少于 32 个字符" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ -z "${BACKUP_ROOT}" || "${BACKUP_ROOT}" == "/" ]]; then
|
||||
echo "拒绝使用不安全的备份目录" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
for command_name in docker gzip openssl; do
|
||||
command -v "${command_name}" >/dev/null 2>&1 || {
|
||||
echo "缺少命令:${command_name}" >&2
|
||||
exit 2
|
||||
}
|
||||
done
|
||||
|
||||
mkdir -p -- "${BACKUP_ROOT}"
|
||||
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
|
||||
archive_name="mysql-all-${timestamp}.sql.gz.enc"
|
||||
archive_path="${BACKUP_ROOT}/${archive_name}"
|
||||
temporary_path="${BACKUP_ROOT}/.${archive_name}.tmp"
|
||||
checksum_path="${archive_path}.sha256"
|
||||
manifest_path="${archive_path}.json"
|
||||
|
||||
cleanup() {
|
||||
rm -f -- "${temporary_path}"
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
cd -- "${PROJECT_DIR}"
|
||||
docker compose exec -T mysql sh -eu -c '
|
||||
MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysqldump \
|
||||
--user=root \
|
||||
--all-databases \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--routines \
|
||||
--events \
|
||||
--triggers \
|
||||
--hex-blob \
|
||||
--set-gtid-purged=OFF
|
||||
' | gzip -9 | openssl enc -aes-256-cbc -salt -pbkdf2 -iter 200000 \
|
||||
-pass "file:${PASSPHRASE_FILE}" -out "${temporary_path}"
|
||||
|
||||
test -s "${temporary_path}"
|
||||
mv -- "${temporary_path}" "${archive_path}"
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
checksum="$(sha256sum "${archive_path}" | awk '{print $1}')"
|
||||
else
|
||||
checksum="$(shasum -a 256 "${archive_path}" | awk '{print $1}')"
|
||||
fi
|
||||
printf '%s %s\n' "${checksum}" "${archive_name}" > "${checksum_path}"
|
||||
printf '{\n "created_at": "%s",\n "file": "%s",\n "sha256": "%s",\n "encrypted": true,\n "cipher": "AES-256-CBC/PBKDF2",\n "compression": "gzip"\n}\n' \
|
||||
"${timestamp}" "${archive_name}" "${checksum}" > "${manifest_path}"
|
||||
chmod 600 "${archive_path}" "${checksum_path}" "${manifest_path}"
|
||||
|
||||
echo "加密备份已生成:${archive_path}"
|
||||
echo "请将 .enc、.sha256 和 .json 同步到独立的异地存储。"
|
||||
Reference in new issue
Block a user