273 lines
8.7 KiB
Bash
273 lines
8.7 KiB
Bash
#!/bin/bash
|
|
# Wine CSP Service Entrypoint
|
|
#
|
|
# Initializes Wine environment and starts the WineCspService under Wine.
|
|
# For TEST VECTOR GENERATION ONLY - not for production signing.
|
|
|
|
set -euo pipefail
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Configuration
|
|
# ------------------------------------------------------------------------------
|
|
WINE_CSP_PORT="${WINE_CSP_PORT:-5099}"
|
|
WINE_CSP_MODE="${WINE_CSP_MODE:-limited}"
|
|
WINE_CSP_INSTALLER_PATH="${WINE_CSP_INSTALLER_PATH:-/opt/cryptopro/csp-installer.msi}"
|
|
WINE_CSP_LOG_LEVEL="${WINE_CSP_LOG_LEVEL:-Information}"
|
|
WINE_PREFIX="${WINEPREFIX:-$HOME/.wine}"
|
|
DISPLAY="${DISPLAY:-:99}"
|
|
CSP_DOWNLOAD_MARKER="${WINE_CSP_INSTALLER_PATH}.downloaded"
|
|
CRYPTOPRO_DOWNLOAD_DIR="${CRYPTOPRO_DOWNLOAD_DIR:-/opt/cryptopro/downloads}"
|
|
CRYPTOPRO_DOWNLOAD_MARKER="${CRYPTOPRO_DOWNLOAD_MARKER:-${CRYPTOPRO_DOWNLOAD_DIR}/.downloaded}"
|
|
CRYPTOPRO_FETCH_ON_START="${CRYPTOPRO_FETCH_ON_START:-1}"
|
|
|
|
# Marker files
|
|
CSP_INSTALLED_MARKER="${WINE_PREFIX}/.csp_installed"
|
|
WINE_INITIALIZED_MARKER="${WINE_PREFIX}/.wine_initialized"
|
|
|
|
# Log prefix for structured logging
|
|
log() {
|
|
echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] [entrypoint] $*"
|
|
}
|
|
|
|
log_error() {
|
|
echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] [entrypoint] [ERROR] $*" >&2
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Virtual Framebuffer Management
|
|
# ------------------------------------------------------------------------------
|
|
start_xvfb() {
|
|
if ! pgrep -x Xvfb > /dev/null; then
|
|
log "Starting Xvfb virtual framebuffer on display ${DISPLAY}"
|
|
Xvfb "${DISPLAY}" -screen 0 1024x768x24 &
|
|
sleep 2
|
|
fi
|
|
}
|
|
|
|
stop_xvfb() {
|
|
if pgrep -x Xvfb > /dev/null; then
|
|
log "Stopping Xvfb"
|
|
pkill -x Xvfb || true
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Wine Initialization
|
|
# ------------------------------------------------------------------------------
|
|
initialize_wine() {
|
|
if [[ -f "${WINE_INITIALIZED_MARKER}" ]]; then
|
|
log "Wine prefix already initialized"
|
|
return 0
|
|
fi
|
|
|
|
log "Initializing Wine prefix at ${WINE_PREFIX}"
|
|
|
|
start_xvfb
|
|
|
|
# Initialize Wine prefix
|
|
wine64 wineboot --init 2>/dev/null || true
|
|
wineserver --wait
|
|
|
|
# Set Windows version for CryptoPro compatibility
|
|
wine64 reg add "HKCU\\Software\\Wine\\Version" /v Windows /d "win10" /f 2>/dev/null || true
|
|
wineserver --wait
|
|
|
|
# Create marker
|
|
touch "${WINE_INITIALIZED_MARKER}"
|
|
log "Wine prefix initialized successfully"
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# CryptoPro Linux Downloads (Playwright-driven)
|
|
# ------------------------------------------------------------------------------
|
|
download_linux_packages() {
|
|
if [[ "${CRYPTOPRO_FETCH_ON_START}" == "0" ]]; then
|
|
log "Skipping CryptoPro Linux fetch (CRYPTOPRO_FETCH_ON_START=0)"
|
|
return 0
|
|
fi
|
|
|
|
if [[ -f "${CRYPTOPRO_DOWNLOAD_MARKER}" && "${CRYPTOPRO_FORCE_DOWNLOAD:-0}" != "1" ]]; then
|
|
log "CryptoPro download marker present at ${CRYPTOPRO_DOWNLOAD_MARKER}; skipping fetch"
|
|
return 0
|
|
fi
|
|
|
|
log "Ensuring CryptoPro Linux packages via Playwright (dry-run unless CRYPTOPRO_DRY_RUN=0)"
|
|
export CRYPTOPRO_DOWNLOAD_MARKER
|
|
export CRYPTOPRO_OUTPUT_DIR="${CRYPTOPRO_DOWNLOAD_DIR}"
|
|
export CRYPTOPRO_UNPACK="${CRYPTOPRO_UNPACK:-1}"
|
|
|
|
if /usr/local/bin/download-cryptopro.sh; then
|
|
if [[ "${CRYPTOPRO_DRY_RUN:-1}" != "0" ]]; then
|
|
log "CryptoPro downloader ran in dry-run mode; set CRYPTOPRO_DRY_RUN=0 to fetch binaries"
|
|
else
|
|
[[ -f "${CRYPTOPRO_DOWNLOAD_MARKER}" ]] || touch "${CRYPTOPRO_DOWNLOAD_MARKER}"
|
|
log "CryptoPro Linux artifacts staged in ${CRYPTOPRO_DOWNLOAD_DIR}"
|
|
fi
|
|
else
|
|
log_error "CryptoPro Playwright download failed"
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# CryptoPro CSP Installation
|
|
# ------------------------------------------------------------------------------
|
|
install_cryptopro() {
|
|
# Check if already installed
|
|
if [[ -f "${CSP_INSTALLED_MARKER}" ]]; then
|
|
log "CryptoPro CSP already installed"
|
|
return 0
|
|
fi
|
|
|
|
# Attempt to download installer if missing (dry-run by default)
|
|
if [[ ! -f "${WINE_CSP_INSTALLER_PATH}" ]]; then
|
|
log "CryptoPro CSP installer not found at ${WINE_CSP_INSTALLER_PATH}; attempting crawl/download (dry-run unless CRYPTOPRO_DRY_RUN=0)."
|
|
if ! CRYPTOPRO_OUTPUT="${WINE_CSP_INSTALLER_PATH}" /usr/local/bin/fetch-cryptopro.py; then
|
|
log_error "CryptoPro CSP download failed; continuing without CSP (limited mode)"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Check if installer is available
|
|
if [[ ! -f "${WINE_CSP_INSTALLER_PATH}" ]]; then
|
|
log "CryptoPro CSP installer not found at ${WINE_CSP_INSTALLER_PATH}"
|
|
log "Service will run in limited mode without CSP"
|
|
return 0
|
|
fi
|
|
|
|
log "Installing CryptoPro CSP from ${WINE_CSP_INSTALLER_PATH}"
|
|
|
|
start_xvfb
|
|
|
|
# Run the CSP installation script
|
|
if /usr/local/bin/install-csp.sh; then
|
|
touch "${CSP_INSTALLED_MARKER}"
|
|
log "CryptoPro CSP installed successfully"
|
|
else
|
|
log_error "CryptoPro CSP installation failed"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Service Configuration
|
|
# ------------------------------------------------------------------------------
|
|
configure_service() {
|
|
log "Configuring Wine CSP service"
|
|
log " Mode: ${WINE_CSP_MODE}"
|
|
log " Port: ${WINE_CSP_PORT}"
|
|
log " Log Level: ${WINE_CSP_LOG_LEVEL}"
|
|
|
|
# Configure Wine debug output based on log level
|
|
case "${WINE_CSP_LOG_LEVEL}" in
|
|
Trace|Debug)
|
|
export WINEDEBUG="warn+all"
|
|
;;
|
|
Information)
|
|
export WINEDEBUG="-all"
|
|
;;
|
|
Warning|Error|Critical)
|
|
export WINEDEBUG="-all"
|
|
;;
|
|
*)
|
|
export WINEDEBUG="-all"
|
|
;;
|
|
esac
|
|
|
|
# Set ASP.NET Core environment
|
|
export ASPNETCORE_URLS="http://+:${WINE_CSP_PORT}"
|
|
export ASPNETCORE_ENVIRONMENT="${ASPNETCORE_ENVIRONMENT:-Production}"
|
|
export Logging__LogLevel__Default="${WINE_CSP_LOG_LEVEL}"
|
|
|
|
# Check if CSP is available
|
|
if [[ -f "${CSP_INSTALLED_MARKER}" ]]; then
|
|
export WINE_CSP_CSP_AVAILABLE="true"
|
|
log "CryptoPro CSP is available"
|
|
else
|
|
export WINE_CSP_CSP_AVAILABLE="false"
|
|
log "Running without CryptoPro CSP (limited mode)"
|
|
fi
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Startup Validation
|
|
# ------------------------------------------------------------------------------
|
|
validate_environment() {
|
|
log "Validating environment"
|
|
|
|
# Check Wine is available
|
|
if ! command -v wine64 &> /dev/null; then
|
|
log_error "wine64 not found in PATH"
|
|
exit 1
|
|
fi
|
|
|
|
# Check application exists
|
|
if [[ ! -f "/app/WineCspService.exe" ]]; then
|
|
log_error "WineCspService.exe not found at /app/"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify Wine prefix is writable
|
|
if [[ ! -w "${WINE_PREFIX}" ]]; then
|
|
log_error "Wine prefix ${WINE_PREFIX} is not writable"
|
|
exit 1
|
|
fi
|
|
|
|
log "Environment validation passed"
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Signal Handlers
|
|
# ------------------------------------------------------------------------------
|
|
cleanup() {
|
|
log "Received shutdown signal, cleaning up..."
|
|
|
|
# Stop Wine server gracefully
|
|
wineserver -k 15 2>/dev/null || true
|
|
sleep 2
|
|
wineserver -k 9 2>/dev/null || true
|
|
|
|
stop_xvfb
|
|
|
|
log "Cleanup complete"
|
|
exit 0
|
|
}
|
|
|
|
trap cleanup SIGTERM SIGINT SIGQUIT
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Main Entry Point
|
|
# ------------------------------------------------------------------------------
|
|
main() {
|
|
log "=========================================="
|
|
log "Wine CSP Service Entrypoint"
|
|
log "=========================================="
|
|
log "WARNING: For TEST VECTOR GENERATION ONLY"
|
|
log "=========================================="
|
|
|
|
validate_environment
|
|
download_linux_packages
|
|
initialize_wine
|
|
|
|
# Only attempt CSP installation in full mode
|
|
if [[ "${WINE_CSP_MODE}" == "full" ]]; then
|
|
install_cryptopro
|
|
fi
|
|
|
|
configure_service
|
|
|
|
# Start Xvfb for the main process
|
|
start_xvfb
|
|
|
|
log "Starting WineCspService..."
|
|
log "Listening on port ${WINE_CSP_PORT}"
|
|
|
|
# Execute the command passed to the container (or default)
|
|
if [[ $# -gt 0 ]]; then
|
|
exec "$@"
|
|
else
|
|
exec wine64 /app/WineCspService.exe
|
|
fi
|
|
}
|
|
|
|
main "$@"
|