mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-02 11:29:17 +00:00
da6fc5314d
* docs(kms): correct the static backend's MinIO compatibility claim `StaticConfig` claimed the backend derives DEKs via "HMAC-SHA256 + AES-256-GCM, matching the MinIO builtin/static KMS wire format". Neither half holds: the configured key is used directly as the AES-256-GCM key with no derivation step, and wrapped DEKs are serialized as RustFS's own `DataKeyEnvelope` JSON. MinIO's KMS ciphertext uses a different shape, which `is_data_key_envelope` explicitly classifies as foreign (see the `minio_legacy` case in encryption/dek.rs). The claim as written tells a migrating operator that MinIO-written ciphertext will open here, which it will not. Restate what the backend actually does and point at rustfs/backlog#1638 for the real interop work. Also refresh the neighbouring ciphertext-format note in static_kms.rs, which still described a raw `ciphertext || nonce` layout that the JSON envelope replaced. * ci(minio-interop): fix the dead test selector and guard against empty runs The job selected its tests with `-p rustfs-ecstore -E 'binary(minio_generated_read_test)'`. #5435 moved those reader tests from crates/ecstore/tests/minio_generated_read_test.rs into the `rustfs` crate as a `#[cfg(test)] mod`, which removed that test binary; the selector has selected zero interop tests since. Point it at the tests where they now live, verified locally: cargo nextest list --run-ignored all -p rustfs --features rio-v2 \ -E 'test(minio_generated_read_test::)' # 4 tests, was 0 Add a guard step in front of the run. The old `binary(...)` form happened to fail loudly once its binary disappeared, but the name-based form that replaces it is a valid filterset even when it matches nothing, so a later rename would silently reduce this job to a pass that asserts nothing. The guard counts the selection and fails with an explicit reason; the count comes from `filter-match.status`, since the JSON's top-level `test-count` is the package total and ignores `-E`. `--no-tests=fail` on the run step covers the same case if the guard is ever dropped. Also record in the header what this job does and does not prove: MinIO wrapped-DEK envelopes are still rejected by both envelope parsers, and that work is tracked in rustfs/backlog#1638.
120 lines
5.6 KiB
YAML
120 lines
5.6 KiB
YAML
# Copyright 2024 RustFS Team
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# MinIO on-disk interop: prove RustFS reads MinIO-written erasure-coded SSE
|
|
# objects with byte-identical data and correct logical size.
|
|
#
|
|
# This is NOT a PR gate. The fixtures are real MinIO backend trees generated on
|
|
# the fly (they are gitignored, never committed), so the job regenerates them
|
|
# each run with Docker and then runs the `#[ignore]` reader tests in
|
|
# rustfs/src/storage/minio_generated_read_test.rs.
|
|
#
|
|
# Scope: end-to-end MinIO-to-RustFS SSE interop is NOT implemented yet. Both
|
|
# envelope parsers reject MinIO's own wrapped-DEK shape — see
|
|
# `is_data_key_envelope` in crates/kms/src/encryption/dek.rs and the
|
|
# `deny_unknown_fields` `LocalSseDekEnvelope` in rustfs/src/storage/sse.rs — and
|
|
# closing that gap is tracked in rustfs/backlog#1638. Treat this job as the
|
|
# harness for #1638, not as standing evidence that a MinIO migration reads back.
|
|
#
|
|
# Runner: GitHub-hosted `ubuntu-latest`. It reliably ships Docker + Python,
|
|
# unlike the self-hosted fleet, whose pods drift in Docker/pip availability
|
|
# (see the infra note in e2e-s3tests.yml). Nightly + manual only.
|
|
# DISABLED. This workflow is switched off in the repository's Actions settings
|
|
# (state: disabled_manually) and does not run on any trigger, including its cron
|
|
# and workflow_dispatch. That state lives in GitHub's UI and is invisible when
|
|
# reading this file, which has already misled at least one audit — hence this
|
|
# banner. Re-enabling is a UI action; anyone doing so should first check that the
|
|
# workflow still matches the current CI layout. See rustfs/backlog#1603.
|
|
#
|
|
name: minio-interop
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
schedule:
|
|
# Nightly at 03:17 UTC (offset from other nightly jobs).
|
|
- cron: "17 3 * * *"
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
minio-interop:
|
|
name: MinIO interop (EC + SSE read parity)
|
|
# Skip on forks: needs the repo's runners and is not a contributor gate.
|
|
if: github.repository == 'rustfs/rustfs'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 40
|
|
env:
|
|
# Fixed 32-byte test KMS key baked into the fixture lab; not a secret.
|
|
RUSTFS_MINIO_STATIC_KMS_KEY_B64: IyqsU3kMFloCNup4BsZtf/rmfHVcTgznO2F25CkEH1g=
|
|
# Single definition of "the interop tests", shared by the guard step and
|
|
# the run step so the two cannot drift apart.
|
|
#
|
|
# These used to live in crates/ecstore/tests/minio_generated_read_test.rs
|
|
# and were selected with `-p rustfs-ecstore -E
|
|
# 'binary(minio_generated_read_test)'`. #5435 moved them into the `rustfs`
|
|
# crate as a `#[cfg(test)] mod`, which deleted that test binary; the
|
|
# selector was never updated and has selected zero interop tests ever
|
|
# since (cargo-nextest 0.9.140 now rejects it outright: "operator didn't
|
|
# match any binary names", exit 94).
|
|
INTEROP_PACKAGE: rustfs
|
|
INTEROP_FEATURES: rio-v2
|
|
INTEROP_FILTER: "test(minio_generated_read_test::)"
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup Rust environment
|
|
uses: ./.github/actions/setup
|
|
with:
|
|
rust-version: stable
|
|
cache-shared-key: ci-minio-interop
|
|
cache-save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
|
|
- name: Generate real MinIO fixtures via Docker
|
|
run: bash crates/rio-v2/tests/minio_fixture_lab/capture_via_docker.sh
|
|
|
|
# `binary(...)` at least dies loudly when nothing matches, but `test(...)`
|
|
# is a perfectly valid filterset that matches zero tests, so the next
|
|
# rename or module move would leave this job selecting nothing and
|
|
# reporting success without executing a single interop assertion. Count
|
|
# the selection and fail with a reason instead.
|
|
#
|
|
# Count only `filter-match.status == "matches"`: the top-level
|
|
# `test-count` in the JSON is the package total and ignores `-E` entirely.
|
|
- name: Assert the interop selector still matches tests
|
|
run: |
|
|
set -euo pipefail
|
|
count="$(cargo nextest list --run-ignored all \
|
|
-p "$INTEROP_PACKAGE" --features "$INTEROP_FEATURES" \
|
|
-E "$INTEROP_FILTER" --message-format json \
|
|
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(sum(1 for s in d.get("rust-suites", {}).values() for t in s.get("testcases", {}).values() if t.get("filter-match", {}).get("status") == "matches"))')"
|
|
echo "interop tests selected: ${count}"
|
|
if [ "${count}" -eq 0 ]; then
|
|
echo "::error::Selector '${INTEROP_FILTER}' in package '${INTEROP_PACKAGE}' matched 0 tests. The MinIO interop reader tests have moved or been renamed again; fix the selector instead of letting this job pass without running them. Context: rustfs/backlog#1638."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Run MinIO interop reader tests
|
|
run: |
|
|
cargo nextest run --run-ignored ignored-only --no-tests=fail \
|
|
-p "$INTEROP_PACKAGE" --features "$INTEROP_FEATURES" \
|
|
-E "$INTEROP_FILTER"
|