Files
git.stella-ops.org/ops/wine-csp/Dockerfile
StellaOps Bot bc0762e97d up
2025-12-09 00:20:52 +02:00

194 lines
7.6 KiB
Docker

# syntax=docker/dockerfile:1.7
# Wine CSP Service - GOST cryptographic operations via Wine-hosted CryptoPro CSP
#
# WARNING: For TEST VECTOR GENERATION ONLY - not for production signing
#
# Build:
# docker buildx build -f ops/wine-csp/Dockerfile -t wine-csp:latest .
#
# Run:
# docker run -p 5099:5099 -e WINE_CSP_MODE=limited wine-csp:latest
# ==============================================================================
# Stage 1: Build .NET application for Windows x64
# ==============================================================================
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:10.0-preview-bookworm-slim
FROM ${SDK_IMAGE} AS build
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \
DOTNET_NOLOGO=1 \
DOTNET_ROLL_FORWARD=LatestMajor \
SOURCE_DATE_EPOCH=1704067200
WORKDIR /src
# Copy solution files and NuGet configuration
COPY Directory.Build.props Directory.Build.rsp NuGet.config ./
# Copy local NuGet packages if available
COPY local-nugets/ ./local-nugets/
# Copy Wine CSP Service source
COPY src/__Tools/WineCspService/ ./src/__Tools/WineCspService/
# Copy GostCryptography fork dependency
COPY third_party/forks/AlexMAS.GostCryptography/ ./third_party/forks/AlexMAS.GostCryptography/
# Restore and publish for Windows x64 (runs under Wine)
RUN --mount=type=cache,target=/root/.nuget/packages \
dotnet restore src/__Tools/WineCspService/WineCspService.csproj && \
dotnet publish src/__Tools/WineCspService/WineCspService.csproj \
-c Release \
-r win-x64 \
--self-contained true \
-o /app/publish \
/p:PublishSingleFile=true \
/p:EnableCompressionInSingleFile=true \
/p:DebugType=none \
/p:DebugSymbols=false
# ==============================================================================
# Stage 2: Runtime with Wine and CryptoPro CSP support
# ==============================================================================
FROM ubuntu:22.04 AS runtime
# OCI Image Labels
LABEL org.opencontainers.image.title="StellaOps Wine CSP Service" \
org.opencontainers.image.description="GOST cryptographic test vector generation via Wine-hosted CryptoPro CSP" \
org.opencontainers.image.vendor="StellaOps" \
org.opencontainers.image.source="https://git.stella-ops.org/stellaops/router" \
com.stellaops.component="wine-csp" \
com.stellaops.security.production-signing="false" \
com.stellaops.security.test-vectors-only="true"
# Wine CSP service configuration
ARG WINE_CSP_PORT=5099
ARG APP_USER=winecsp
ARG APP_UID=10001
ARG APP_GID=10001
ENV DEBIAN_FRONTEND=noninteractive \
# Wine configuration
WINEDEBUG=-all \
WINEPREFIX=/home/${APP_USER}/.wine \
WINEARCH=win64 \
# Service configuration
WINE_CSP_PORT=${WINE_CSP_PORT} \
ASPNETCORE_URLS=http://+:${WINE_CSP_PORT} \
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 \
# CSP configuration
WINE_CSP_MODE=limited \
WINE_CSP_INSTALLER_PATH=/opt/cryptopro/csp-installer.msi \
WINE_CSP_LOG_LEVEL=Information \
NODE_PATH=/usr/local/lib/node_modules \
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
# Display for Wine (headless)
DISPLAY=:99
# Install Wine and dependencies
# Using WineHQ stable repository for consistent Wine version
RUN set -eux; \
dpkg --add-architecture i386; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
curl \
gnupg2 \
software-properties-common \
wget \
xvfb \
cabextract \
p7zip-full \
procps; \
# Add WineHQ repository key
mkdir -pm755 /etc/apt/keyrings; \
wget -O /etc/apt/keyrings/winehq-archive.key \
https://dl.winehq.org/wine-builds/winehq.key; \
# Add WineHQ repository
wget -NP /etc/apt/sources.list.d/ \
https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources; \
apt-get update; \
# Install Wine stable
apt-get install -y --no-install-recommends \
winehq-stable; \
# Install winetricks for runtime dependencies
wget -O /usr/local/bin/winetricks \
https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks; \
chmod +x /usr/local/bin/winetricks; \
# Cleanup
apt-get clean; \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install Node.js + Playwright (headless Chromium) for CryptoPro downloader
RUN set -eux; \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -; \
apt-get update; \
apt-get install -y --no-install-recommends \
nodejs \
rpm2cpio \
cpio; \
npm install -g --no-progress playwright-chromium@1.48.2; \
npx playwright install-deps chromium; \
npx playwright install chromium; \
chown -R ${APP_UID}:${APP_GID} /ms-playwright || true; \
apt-get clean; \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Create non-root user for Wine service
# Note: Wine requires writable home directory for prefix
RUN groupadd -r -g ${APP_GID} ${APP_USER} && \
useradd -r -u ${APP_UID} -g ${APP_GID} -m -d /home/${APP_USER} -s /bin/bash ${APP_USER} && \
mkdir -p /app /opt/cryptopro /var/log/wine-csp /var/run/wine-csp && \
chown -R ${APP_UID}:${APP_GID} /app /home/${APP_USER} /opt/cryptopro /var/log/wine-csp /var/run/wine-csp
WORKDIR /app
# Copy application from build stage
COPY --from=build --chown=${APP_UID}:${APP_GID} /app/publish/ ./
# Copy supporting scripts
COPY --chown=${APP_UID}:${APP_GID} ops/wine-csp/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=${APP_UID}:${APP_GID} ops/wine-csp/healthcheck.sh /usr/local/bin/healthcheck.sh
COPY --chown=${APP_UID}:${APP_GID} ops/wine-csp/install-csp.sh /usr/local/bin/install-csp.sh
COPY --chown=${APP_UID}:${APP_GID} ops/wine-csp/fetch-cryptopro.py /usr/local/bin/fetch-cryptopro.py
COPY --chown=${APP_UID}:${APP_GID} ops/wine-csp/download-cryptopro.sh /usr/local/bin/download-cryptopro.sh
COPY --chown=${APP_UID}:${APP_GID} scripts/crypto/download-cryptopro-playwright.cjs /usr/local/bin/download-cryptopro-playwright.cjs
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/healthcheck.sh /usr/local/bin/install-csp.sh /usr/local/bin/fetch-cryptopro.py /usr/local/bin/download-cryptopro.sh /usr/local/bin/download-cryptopro-playwright.cjs
# Switch to non-root user for Wine prefix initialization
USER ${APP_UID}:${APP_GID}
# Initialize Wine prefix (creates .wine directory with Windows environment)
# This must run as the app user to set correct ownership
# Using xvfb-run for headless Wine initialization
RUN set -eux; \
# Start virtual framebuffer and initialize Wine
xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" \
wine64 wineboot --init; \
wineserver --wait; \
# Install Visual C++ 2019 runtime via winetricks (required for .NET)
xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" \
winetricks -q vcrun2019 || true; \
wineserver --wait; \
# Set Windows version to Windows 10 for compatibility
wine64 reg add "HKCU\\Software\\Wine\\Version" /v Windows /d "win10" /f || true; \
wineserver --wait; \
# Cleanup Wine temp files
rm -rf /home/${APP_USER}/.cache/winetricks /tmp/.X* /tmp/winetricks* || true
EXPOSE ${WINE_CSP_PORT}
# Health check using custom script that probes /health endpoint
# Extended start_period due to Wine initialization time
HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \
CMD /usr/local/bin/healthcheck.sh
# Volumes for persistence and CSP installer
# - Wine prefix: stores CSP installation, certificates, keys
# - CSP installer: mount customer-provided CryptoPro MSI here
# - Logs: service logs
VOLUME ["/home/${APP_USER}/.wine", "/opt/cryptopro", "/var/log/wine-csp"]
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["wine64", "/app/WineCspService.exe"]