commit 22431d5541e6198e20ee7efce4e804e316d228b8 Author: Vassiliy Yegorov Date: Sun Oct 26 12:34:36 2025 +0700 init diff --git a/.env b/.env new file mode 100644 index 0000000..6aee548 --- /dev/null +++ b/.env @@ -0,0 +1,12 @@ +MINIO_ROOT_USER="admin" +MINIO_ROOT_PASSWORD="minioadmin" +MINIO_VOLUMES="/storage" + +# Minio server region +MINIO_SITE_REGION="" + +# Minio server URL +# MINIO_SERVER_URL="https://s3-nsk.bildme.ru" + +# Minio console URL +# MINIO_BROWSER_REDIRECT_URL="https://s3-nsk.bildme.ru/minio/ui/" diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml new file mode 100644 index 0000000..6be4655 --- /dev/null +++ b/.gitea/workflows/docker-build.yml @@ -0,0 +1,39 @@ +name: docker-build + +on: + push: + tags: + - "*" + +permissions: + contents: read + packages: write + +jobs: + build: + name: Build image + runs-on: ubuntu-22.04 + container: catthehacker/ubuntu:act-latest + env: + REGISTRY: git.realmanual.ru + IMAGE_NAME: ${{ gitea.repository }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.PUSH_TOKEN }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ gitea.ref_name }} + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa780e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +storage diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..521f7ea --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +ARG RELEASE=RELEASE.2025-10-17T06-17-41Z +FROM quay.io/minio/aistor/minio:${RELEASE} AS minio + +FROM python:3.13-alpine AS patcher +RUN apk add openssl +WORKDIR /patcher +COPY requirements.txt requirements.txt +RUN pip3 install -r requirements.txt +COPY . . +COPY --from=minio /bin/minio minio +RUN sh generate-keys.sh +RUN python3 replace-key.py minio minio-patched new-public.pem +RUN python3 generate-license.py new-private.pem minio.license + +FROM quay.io/minio/aistor/minio:${RELEASE} +COPY --from=patcher /patcher/minio-patched /bin/minio +RUN chmod +x /bin/minio +COPY --from=patcher /patcher/minio.license /minio.license +ENV MINIO_LICENSE=/minio.license diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f5ed01 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +# MinIO Patcher + +Инструмент для патчинга MinIO бинарного файла с целью замены встроенного публичного ключа лицензии на собственный и генерации соответствующей лицензии. + +## Описание + +Проект позволяет: +- Заменить встроенный публичный ключ лицензии в бинарном файле MinIO +- Сгенерировать собственную пару ключей (приватный/публичный) +- Создать лицензионный файл с использованием нового приватного ключа +- Запустить модифицированный MinIO с собственной лицензией + +## Структура проекта + +``` +minio-patcher/ +├── Dockerfile # Многоэтапная сборка для патчинга MinIO +├── docker-compose.yaml # Конфигурация для запуска сервиса +├── generate-keys.sh # Скрипт генерации ключей ECDSA P-384 +├── generate-license.py # Генератор JWT лицензии +├── replace-key.py # Замена публичного ключа в бинарном файле +├── requirements.txt # Python зависимости +└── storage/ # Директория для данных MinIO +``` + +## Компоненты + +### generate-keys.sh +Генерирует пару ECDSA ключей с кривой secp384r1: +- `new-private.pem` - приватный ключ +- `new-public.pem` - публичный ключ + +### replace-key.py +Заменяет встроенный публичный ключ MinIO на новый: +- Загружает оригинальный публичный ключ с subnet.min.io +- Находит и заменяет его в бинарном файле MinIO +- Создает патченый бинарный файл + +### generate-license.py +Создает JWT лицензию с параметрами: +- Организация: "acme" +- План: "STANDARD" +- Емкость: 1GB +- Срок действия: до 2033 года +- Алгоритм подписи: ES384 + +## Использование + +### Docker Compose (рекомендуется) + +```bash +docker-compose up -d +``` + +Сервис будет доступен на: +- API: http://localhost:9000 +- Web UI: http://localhost:9001 + +### Ручная сборка + +```bash +# Сборка образа +docker build -t minio-patcher . + +# Запуск контейнера +docker run -d \ + -p 9000:9000 \ + -p 9001:9001 \ + -v ./storage:/storage \ + minio-patcher server /storage +``` + +### Локальное выполнение + +```bash +# Установка зависимостей +pip install -r requirements.txt + +# Генерация ключей +./generate-keys.sh + +# Патчинг MinIO (требуется оригинальный бинарный файл) +python3 replace-key.py minio minio-patched new-public.pem + +# Генерация лицензии +python3 generate-license.py new-private.pem minio.license + +# Запуск с лицензией +MINIO_LICENSE=./minio.license ./minio-patched server ./storage +``` + +## Требования + +- Docker и Docker Compose +- Python 3.13+ (для локального запуска) +- OpenSSL (для генерации ключей) + +## Безопасность + +⚠️ **Внимание**: Данный инструмент предназначен исключительно для образовательных и тестовых целей. Использование в продакшене может нарушать лицензионные соглашения MinIO. + +## Лицензия + +Проект предоставляется "как есть" без каких-либо гарантий. diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..95ac000 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,18 @@ +services: + minio: + build: . + restart: always + container_name: minio + command: server --console-address ":9001" /storage + env_file: + - .env + volumes: + - "./storage:/storage" + ports: + - 9000:9000 + - 9001:9001 + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 5 diff --git a/generate-keys.sh b/generate-keys.sh new file mode 100644 index 0000000..eefb244 --- /dev/null +++ b/generate-keys.sh @@ -0,0 +1,3 @@ +#!/bin/sh +openssl ecparam -genkey -name secp384r1 -noout -out new-private.pem +openssl ec -in new-private.pem -pubout -out new-public.pem diff --git a/generate-license.py b/generate-license.py new file mode 100644 index 0000000..b75421a --- /dev/null +++ b/generate-license.py @@ -0,0 +1,33 @@ +import sys +import jwcrypto.jwk +import jwcrypto.jwt + +if len(sys.argv) < 3: + print(f"Usage: ./{sys.argv[0]} ") + exit(1) + +private_key_path = sys.argv[1] +output_license_file = sys.argv[2] + +with open(private_key_path, "rb") as f: + private_key = jwcrypto.jwk.JWK.from_pem(f.read()) + +jwt_data = { + "sub": "acme@min.io", + "exp": 2000000000, + "iss": "subnet@min.io", + "iat": 0, + "aid": 1337, + "org": "acme", + "cap": 1000000000, + "plan": "STANDARD" +} + +license_jwt = jwcrypto.jwt.JWT(claims=jwt_data, header={ + "alg": "ES384", + "typ": "JWT" +}) +license_jwt.make_signed_token(private_key) + +with open(sys.argv[2], "w") as f: + f.write(license_jwt.serialize()) diff --git a/replace-key.py b/replace-key.py new file mode 100644 index 0000000..5d1d38b --- /dev/null +++ b/replace-key.py @@ -0,0 +1,37 @@ +import sys +import urllib.request + +def get_minio_public_key(): + f = urllib.request.urlopen("https://subnet.min.io/downloads/license-pubkey.pem") + public_key = f.read() + if public_key[0:27] != b'-----BEGIN PUBLIC KEY-----\n': + raise ValueError("wrong public key prefix") + if public_key[-26:] != b'\n-----END PUBLIC KEY-----\n': + raise ValueError("wrong public key suffix") + return public_key[0:-1] + +if len(sys.argv) < 4: + print(f"Usage: ./{sys.argv[0]} ") + exit(1) + +original_minio_binary_path = sys.argv[1] +new_minio_binary_path = sys.argv[2] +new_public_key_path = sys.argv[3] + +with open(original_minio_binary_path, "rb") as f: + minio_binary = f.read() + +original_public_key = get_minio_public_key() + +with open(new_public_key_path, "r") as f: + new_public_key = f.read().strip().encode("ascii") + +if len(new_public_key) != len(original_public_key): + raise ValueError(f"wrong new public key length: {len(new_public_key)} != {len(original_public_key)}") + +new_minio_binary = minio_binary.replace(original_public_key, new_public_key) +if new_minio_binary == minio_binary: + raise ValueError(f"could not replace old public key") + +with open(new_minio_binary_path, "wb") as f: + f.write(new_minio_binary) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3e7b26e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +jwcrypto