mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
feat: add admin route policy inventory (#3286)
* feat: add admin route policy inventory * fix: align table route policy actions * fix: align load table route policy action
This commit is contained in:
Generated
+1
@@ -9105,6 +9105,7 @@ dependencies = [
|
||||
"rustfs-s3select-api",
|
||||
"rustfs-s3select-query",
|
||||
"rustfs-scanner",
|
||||
"rustfs-security-governance",
|
||||
"rustfs-signer",
|
||||
"rustfs-targets",
|
||||
"rustfs-tls-runtime",
|
||||
|
||||
@@ -5,15 +5,17 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
## Current Context
|
||||
|
||||
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
||||
- Branch: `overtrue/arch-security-governance-policy-types`
|
||||
- Baseline: `upstream/main` at `7a9bf707ee66e779f85e6e00cedfaa10ec2af4c2`
|
||||
- Branch: `overtrue/arch-admin-route-policy`
|
||||
- Baseline: `origin/main` at `3d0e6ce0da93de0f4618beb194ae2241df71f344`
|
||||
- PR type for this branch: `contract`
|
||||
- Runtime behavior changes: none
|
||||
- Rust code changes: add redaction, serde policy, and artifact integrity
|
||||
contract modules to the pure rustfs-security-governance crate, with typed
|
||||
validation errors and unit tests.
|
||||
- Rust code changes: add `rustfs/src/admin/route_policy.rs` as a pure
|
||||
admin-route policy inventory backed by `rustfs-security-governance` route
|
||||
contract types, with explicit deferred entries for routes that need
|
||||
contextual, S3-action, multi-action, credential-only, or not-implemented
|
||||
contract support.
|
||||
- CI/script changes: none
|
||||
- Docs changes: record the Phase 1 policy contract handoff.
|
||||
- Docs changes: record the S-006 route policy handoff.
|
||||
|
||||
## Phase 0 Tasks
|
||||
|
||||
@@ -88,52 +90,57 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
errors model digest, signature, and provenance requirements without changing
|
||||
release or CI behavior.
|
||||
- Verification: `cargo test -p rustfs-security-governance`.
|
||||
- [ ] `S-006` Add `rustfs/src/admin/route_policy.rs` backed by these contract
|
||||
- [x] `S-006` Add `rustfs/src/admin/route_policy.rs` backed by these contract
|
||||
types, without changing route registration or auth behavior.
|
||||
- Acceptance: direct `AdminRouteSpec` entries cover routes with a single
|
||||
stable admin policy action, deferred inventory records routes that need
|
||||
richer contract support, and tests prove the combined inventory covers every
|
||||
registered admin route.
|
||||
|
||||
## Next PRs
|
||||
|
||||
1. `contract`: add an admin route policy table that consumes the new admin
|
||||
route matrix types while preserving route registration and auth behavior.
|
||||
2. `contract`: add initial policy inventory tables for redaction, serde, or
|
||||
1. `contract`: add initial policy inventory tables for redaction, serde, or
|
||||
supply-chain governance only after the contract shape remains stable.
|
||||
|
||||
## Pre-Push Review Log
|
||||
|
||||
| Expert | Status | Notes |
|
||||
|---|---|---|
|
||||
| Quality/architecture | pass | Confirmed the staged diff includes the new modules, keeps a pure `contract` design, uses clear API names and typed errors, and does not introduce runtime/admin/router/auth/startup/storage/config/global-state integration |
|
||||
| Migration preservation | pass | Confirmed this PR only completes `S-003` through `S-005`, does not shift away from backlog #660, does not touch storage hot paths or global-state migration, and does not need compatibility markers |
|
||||
| Testing/verification | pass | Confirmed focused contract tests assert valid and invalid policy behavior, production logic was not changed to satisfy tests, focused checks passed, and full `make pre-commit` passed |
|
||||
| Quality/architecture | pass | Pure contract inventory module; no runtime route registration, alias canonicalization, or handler auth mutation. Names and deferred reasons are explicit and avoid false policy precision. |
|
||||
| Migration preservation | pass | Aligns with backlog #660: directory and contract boundary first, no global-state migration, no crate split, and no storage hot-path behavior drift. |
|
||||
| Testing/verification | pass | Route-policy tests cover validation, public exceptions, table-catalog scope, deferred contextual routes, and every registered admin route. Focused checks, guard scripts, and full pre-commit pass. |
|
||||
|
||||
## Verification Notes
|
||||
|
||||
Passed:
|
||||
- `cargo check -p rustfs-security-governance`
|
||||
- `cargo test -p rustfs-security-governance`
|
||||
- `cargo test -p rustfs admin::route_policy`
|
||||
- `cargo fmt --all`
|
||||
- `cargo fmt --all --check`
|
||||
- `cargo tree -p rustfs-security-governance --edges normal`
|
||||
- `cargo check -p rustfs`
|
||||
- `./scripts/check_architecture_migration_rules.sh`
|
||||
- `./scripts/check_layer_dependencies.sh`
|
||||
- `./scripts/check_metrics_migration_refs.sh`
|
||||
- `./scripts/check_layer_dependencies.sh`
|
||||
- `git diff --check`
|
||||
- Rust quality scans for production `unwrap`/`expect`, narrowing casts,
|
||||
string errors, boxed dynamic errors, debug printing, and relaxed atomics in
|
||||
`rustfs/src/admin/route_policy.rs`
|
||||
- `make pre-commit`
|
||||
|
||||
Notes:
|
||||
- `cargo test -p rustfs-security-governance` passed 20 unit tests.
|
||||
- `make pre-commit` passed, including 5513 nextest tests, 105 skipped tests,
|
||||
and workspace doctests.
|
||||
- `cargo test -p rustfs admin::route_policy` passed 7 route-policy tests.
|
||||
- `make pre-commit` passed all checks, including 5526 nextest tests and
|
||||
workspace doctests.
|
||||
|
||||
## Handoff Notes
|
||||
|
||||
- Keep this Phase 1 branch as a pure `contract` PR. Do not add
|
||||
`rustfs/src/admin` integration, route registration changes, auth enforcement,
|
||||
Config moves, Storage API moves, Runtime moves, or ECStore moves.
|
||||
- The new crate is allowed to depend on generic Rust libraries such as
|
||||
`thiserror`, but must stay independent from implementation crates and runtime
|
||||
state.
|
||||
- Keep this S-006 branch as a pure `contract` PR. Do not change
|
||||
admin route registration, `/minio/admin` alias canonicalization, handler auth
|
||||
enforcement, Config moves, Storage API moves, Runtime moves, or ECStore moves.
|
||||
- `rustfs` may depend on `rustfs-security-governance` for contract metadata;
|
||||
the security-governance crate must stay independent from implementation
|
||||
crates and runtime state.
|
||||
- Do not add temporary compatibility code without a matching
|
||||
`RUSTFS_COMPAT_TODO(<task-id>)` marker and cleanup-register entry.
|
||||
- The next admin route policy PR may consume the contract types, but must
|
||||
preserve current route registration, alias canonicalization, public
|
||||
exceptions, and handler-level authorization behavior.
|
||||
- Deferred route policy entries must remain explicit until the contract crate
|
||||
gains richer support for contextual owner checks, S3 actions, multiple
|
||||
accepted actions, credential-only gates, and not-implemented routes.
|
||||
|
||||
@@ -82,6 +82,7 @@ rustfs-protos = { workspace = true }
|
||||
rustfs-rio.workspace = true
|
||||
rustfs-s3-types = { workspace = true }
|
||||
rustfs-s3-ops = { workspace = true }
|
||||
rustfs-security-governance = { workspace = true }
|
||||
rustfs-data-usage = { workspace = true }
|
||||
rustfs-s3select-api = { workspace = true }
|
||||
rustfs-s3select-query = { workspace = true }
|
||||
|
||||
@@ -16,6 +16,9 @@ mod auth;
|
||||
pub mod console;
|
||||
pub mod handlers;
|
||||
mod plugin_contract;
|
||||
// Contract inventory is validated by tests before later runtime integration.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) mod route_policy;
|
||||
pub mod router;
|
||||
pub mod service;
|
||||
pub mod site_replication_identity;
|
||||
|
||||
@@ -0,0 +1,879 @@
|
||||
// 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.
|
||||
|
||||
use rustfs_security_governance::{
|
||||
AdminActionRef, AdminRouteMatrixError, AdminRouteSpec, HttpMethod, PublicRouteKind, RouteRiskLevel,
|
||||
validate_admin_route_specs,
|
||||
};
|
||||
|
||||
const ALL_ADMIN: AdminActionRef = AdminActionRef::new("AllAdminActions");
|
||||
const ADD_USER_TO_GROUP: AdminActionRef = AdminActionRef::new("AddUserToGroupAdminAction");
|
||||
const ATTACH_POLICY: AdminActionRef = AdminActionRef::new("AttachPolicyAdminAction");
|
||||
const CONFIG_UPDATE: AdminActionRef = AdminActionRef::new("ConfigUpdateAdminAction");
|
||||
const COMMIT_TABLE: AdminActionRef = AdminActionRef::new("CommitTableAction");
|
||||
const CREATE_POLICY: AdminActionRef = AdminActionRef::new("CreatePolicyAdminAction");
|
||||
const CREATE_SERVICE_ACCOUNT: AdminActionRef = AdminActionRef::new("CreateServiceAccountAdminAction");
|
||||
const CREATE_TABLE: AdminActionRef = AdminActionRef::new("CreateTableAction");
|
||||
const DECOMMISSION: AdminActionRef = AdminActionRef::new("DecommissionAdminAction");
|
||||
const DELETE_POLICY: AdminActionRef = AdminActionRef::new("DeletePolicyAdminAction");
|
||||
const DELETE_TABLE: AdminActionRef = AdminActionRef::new("DeleteTableAction");
|
||||
const DELETE_TABLE_NAMESPACE: AdminActionRef = AdminActionRef::new("DeleteTableNamespaceAction");
|
||||
const DELETE_USER: AdminActionRef = AdminActionRef::new("DeleteUserAdminAction");
|
||||
const ENABLE_GROUP: AdminActionRef = AdminActionRef::new("EnableGroupAdminAction");
|
||||
const ENABLE_USER: AdminActionRef = AdminActionRef::new("EnableUserAdminAction");
|
||||
const EXPORT_BUCKET_METADATA: AdminActionRef = AdminActionRef::new("ExportBucketMetadataAction");
|
||||
const EXPORT_IAM: AdminActionRef = AdminActionRef::new("ExportIAMAction");
|
||||
const GET_BUCKET_TARGET: AdminActionRef = AdminActionRef::new("GetBucketTargetAction");
|
||||
const GET_GROUP: AdminActionRef = AdminActionRef::new("GetGroupAdminAction");
|
||||
const GET_POLICY: AdminActionRef = AdminActionRef::new("GetPolicyAdminAction");
|
||||
const GET_REPLICATION_METRICS: AdminActionRef = AdminActionRef::new("GetReplicationMetricsAction");
|
||||
const GET_TABLE: AdminActionRef = AdminActionRef::new("GetTableAction");
|
||||
const GET_TABLE_CATALOG: AdminActionRef = AdminActionRef::new("GetTableCatalogAction");
|
||||
const GET_TABLE_METADATA: AdminActionRef = AdminActionRef::new("GetTableMetadataAction");
|
||||
const GET_TABLE_NAMESPACE: AdminActionRef = AdminActionRef::new("GetTableNamespaceAction");
|
||||
const HEAL: AdminActionRef = AdminActionRef::new("HealAdminAction");
|
||||
const IMPORT_BUCKET_METADATA: AdminActionRef = AdminActionRef::new("ImportBucketMetadataAction");
|
||||
const IMPORT_IAM: AdminActionRef = AdminActionRef::new("ImportIAMAction");
|
||||
const KMS_CREATE_KEY: AdminActionRef = AdminActionRef::new("KMSCreateKeyAdminAction");
|
||||
const KMS_KEY_STATUS: AdminActionRef = AdminActionRef::new("KMSKeyStatusAdminAction");
|
||||
const LIST_GROUPS: AdminActionRef = AdminActionRef::new("ListGroupsAdminAction");
|
||||
const LIST_TEMPORARY_ACCOUNTS: AdminActionRef = AdminActionRef::new("ListTemporaryAccountsAdminAction");
|
||||
const LIST_TIER: AdminActionRef = AdminActionRef::new("ListTierAction");
|
||||
const LIST_USER_POLICIES: AdminActionRef = AdminActionRef::new("ListUserPoliciesAdminAction");
|
||||
const LIST_USERS: AdminActionRef = AdminActionRef::new("ListUsersAdminAction");
|
||||
const PROFILING: AdminActionRef = AdminActionRef::new("ProfilingAdminAction");
|
||||
const REBALANCE: AdminActionRef = AdminActionRef::new("RebalanceAdminAction");
|
||||
const REGISTER_TABLE: AdminActionRef = AdminActionRef::new("RegisterTableAction");
|
||||
const REMOVE_USER_FROM_GROUP: AdminActionRef = AdminActionRef::new("RemoveUserFromGroupAdminAction");
|
||||
const SERVER_INFO: AdminActionRef = AdminActionRef::new("ServerInfoAdminAction");
|
||||
const SET_BUCKET_QUOTA: AdminActionRef = AdminActionRef::new("SetBucketQuotaAdminAction");
|
||||
const SET_BUCKET_TARGET: AdminActionRef = AdminActionRef::new("SetBucketTargetAction");
|
||||
const SET_TABLE: AdminActionRef = AdminActionRef::new("SetTableAction");
|
||||
const SET_TABLE_NAMESPACE: AdminActionRef = AdminActionRef::new("SetTableNamespaceAction");
|
||||
const SET_TIER: AdminActionRef = AdminActionRef::new("SetTierAction");
|
||||
const SITE_REPLICATION_ADD: AdminActionRef = AdminActionRef::new("SiteReplicationAddAction");
|
||||
const SITE_REPLICATION_INFO: AdminActionRef = AdminActionRef::new("SiteReplicationInfoAction");
|
||||
const SITE_REPLICATION_OPERATION: AdminActionRef = AdminActionRef::new("SiteReplicationOperationAction");
|
||||
const SITE_REPLICATION_REMOVE: AdminActionRef = AdminActionRef::new("SiteReplicationRemoveAction");
|
||||
const SITE_REPLICATION_RESYNC: AdminActionRef = AdminActionRef::new("SiteReplicationResyncAction");
|
||||
const STORAGE_INFO: AdminActionRef = AdminActionRef::new("StorageInfoAdminAction");
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum DeferredRoutePolicyReason {
|
||||
ContextualAuthorization,
|
||||
CredentialOnly,
|
||||
MultipleActions,
|
||||
NotImplemented,
|
||||
S3Action,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct DeferredAdminRoutePolicy {
|
||||
method: HttpMethod,
|
||||
path: &'static str,
|
||||
reason: DeferredRoutePolicyReason,
|
||||
}
|
||||
|
||||
impl DeferredAdminRoutePolicy {
|
||||
pub const fn new(method: HttpMethod, path: &'static str, reason: DeferredRoutePolicyReason) -> Self {
|
||||
Self { method, path, reason }
|
||||
}
|
||||
|
||||
pub const fn method(self) -> HttpMethod {
|
||||
self.method
|
||||
}
|
||||
|
||||
pub const fn path(self) -> &'static str {
|
||||
self.path
|
||||
}
|
||||
|
||||
pub const fn reason(self) -> DeferredRoutePolicyReason {
|
||||
self.reason
|
||||
}
|
||||
}
|
||||
|
||||
pub const ADMIN_ROUTE_POLICY_SPECS: &[AdminRouteSpec] = &[
|
||||
public(HttpMethod::Get, "/health", PublicRouteKind::Health, RouteRiskLevel::Normal),
|
||||
public(HttpMethod::Head, "/health", PublicRouteKind::Health, RouteRiskLevel::Normal),
|
||||
public(HttpMethod::Get, "/health/ready", PublicRouteKind::Health, RouteRiskLevel::Normal),
|
||||
public(HttpMethod::Head, "/health/ready", PublicRouteKind::Health, RouteRiskLevel::Normal),
|
||||
public(HttpMethod::Post, "/", PublicRouteKind::StsFormPost, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/profile/cpu", PROFILING, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/profile/memory", PROFILING, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/is-admin", ALL_ADMIN, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/list-users", LIST_USERS, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Delete, "/rustfs/admin/v3/remove-user", DELETE_USER, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/set-user-status", ENABLE_USER, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/groups", LIST_GROUPS, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/group", GET_GROUP, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/group/{group}",
|
||||
REMOVE_USER_FROM_GROUP,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/set-group-status", ENABLE_GROUP, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/update-group-members",
|
||||
ADD_USER_TO_GROUP,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/temporary-account-info",
|
||||
LIST_TEMPORARY_ACCOUNTS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/add-service-accounts",
|
||||
CREATE_SERVICE_ACCOUNT,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/add-service-account",
|
||||
CREATE_SERVICE_ACCOUNT,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/export-iam", EXPORT_IAM, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/import-iam", IMPORT_IAM, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/list-canned-policies",
|
||||
LIST_USER_POLICIES,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/info-canned-policy",
|
||||
GET_POLICY,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/add-canned-policy", CREATE_POLICY, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/remove-canned-policy",
|
||||
DELETE_POLICY,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/set-user-or-group-policy",
|
||||
ATTACH_POLICY,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/set-policy", ATTACH_POLICY, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/idp/builtin/policy/attach",
|
||||
ATTACH_POLICY,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/idp/builtin/policy/detach",
|
||||
ATTACH_POLICY,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/target/list",
|
||||
GET_BUCKET_TARGET,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/target/{target_type}/{target_name}",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/target/{target_type}/{target_name}/reset",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/target/arns",
|
||||
GET_BUCKET_TARGET,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/info", SERVER_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/storageinfo", STORAGE_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/pools/decommission",
|
||||
DECOMMISSION,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/pools/cancel", DECOMMISSION, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/rebalance/start", REBALANCE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/rebalance/status", REBALANCE, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/rebalance/stop", REBALANCE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/heal/", HEAL, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/heal/{bucket}", HEAL, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/heal/{bucket}/{prefix}", HEAL, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/background-heal/status", HEAL, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/tier", LIST_TIER, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/tier-stats", LIST_TIER, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/tier/{tier}", LIST_TIER, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Delete, "/rustfs/admin/v3/tier/{tiername}", SET_TIER, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/tier", SET_TIER, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/tier/{tiername}", SET_TIER, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/tier/clear", SET_TIER, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/set-bucket-quota",
|
||||
SET_BUCKET_QUOTA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/quota/{bucket}", SET_BUCKET_QUOTA, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/quota/{bucket}",
|
||||
SET_BUCKET_QUOTA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/export-bucket-metadata",
|
||||
EXPORT_BUCKET_METADATA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/export-bucket-metadata",
|
||||
EXPORT_BUCKET_METADATA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/import-bucket-metadata",
|
||||
IMPORT_BUCKET_METADATA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/import-bucket-metadata",
|
||||
IMPORT_BUCKET_METADATA,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/get-config-kv", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/set-config-kv", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Delete, "/rustfs/admin/v3/del-config-kv", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/help-config-kv", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/list-config-history-kv",
|
||||
CONFIG_UPDATE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/clear-config-history-kv",
|
||||
CONFIG_UPDATE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/restore-config-history-kv",
|
||||
CONFIG_UPDATE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/config", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/config", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/scanner/status", SERVER_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/audit/target/list",
|
||||
GET_BUCKET_TARGET,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/audit/target/{target_type}/{target_name}",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/audit/target/{target_type}/{target_name}/reset",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/module-switches",
|
||||
SERVER_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(HttpMethod::Put, "/rustfs/admin/v3/module-switches", CONFIG_UPDATE, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v4/plugins/catalog",
|
||||
SERVER_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v4/plugins/instances",
|
||||
GET_BUCKET_TARGET,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v4/plugins/instances/{id}",
|
||||
GET_BUCKET_TARGET,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v4/plugins/instances/{id}",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v4/plugins/instances/{id}",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/replicationmetrics",
|
||||
GET_REPLICATION_METRICS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/set-remote-target",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/remove-remote-target",
|
||||
SET_BUCKET_TARGET,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/add",
|
||||
SITE_REPLICATION_ADD,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/remove",
|
||||
SITE_REPLICATION_REMOVE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/site-replication/info",
|
||||
SITE_REPLICATION_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/site-replication/metainfo",
|
||||
SITE_REPLICATION_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/site-replication/status",
|
||||
SITE_REPLICATION_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/site-replication/devnull",
|
||||
SITE_REPLICATION_INFO,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/site-replication/netperf",
|
||||
SITE_REPLICATION_INFO,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/join",
|
||||
SITE_REPLICATION_ADD,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/bucket-ops",
|
||||
SITE_REPLICATION_OPERATION,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/iam-item",
|
||||
SITE_REPLICATION_OPERATION,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/bucket-meta",
|
||||
SITE_REPLICATION_OPERATION,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/site-replication/peer/idp-settings",
|
||||
SITE_REPLICATION_ADD,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/edit",
|
||||
SITE_REPLICATION_ADD,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/edit",
|
||||
SITE_REPLICATION_ADD,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/peer/remove",
|
||||
SITE_REPLICATION_REMOVE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/resync/op",
|
||||
SITE_REPLICATION_RESYNC,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/site-replication/state/edit",
|
||||
SITE_REPLICATION_OPERATION,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/debug/pprof/profile", PROFILING, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/debug/pprof/status", PROFILING, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/debug/tls/status", PROFILING, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/create-key", KMS_CREATE_KEY, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/key/create", KMS_CREATE_KEY, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/kms/describe-key",
|
||||
KMS_KEY_STATUS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/kms/key/status",
|
||||
KMS_KEY_STATUS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/kms/list-keys",
|
||||
KMS_KEY_STATUS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/kms/generate-data-key",
|
||||
SERVER_INFO,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/kms/status", SERVER_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/status", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/kms/config", SERVER_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/clear-cache", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/configure", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/start", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/stop", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/kms/service-status",
|
||||
SERVER_INFO,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/reconfigure", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/kms/keys", KMS_CREATE_KEY, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Delete, "/rustfs/admin/v3/kms/keys/delete", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/kms/keys/cancel-deletion",
|
||||
SERVER_INFO,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/kms/keys", KMS_KEY_STATUS, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/kms/keys/{key_id}",
|
||||
KMS_KEY_STATUS,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
public(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/oidc/providers",
|
||||
PublicRouteKind::OidcBootstrap,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
public(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/oidc/authorize/{provider_id}",
|
||||
PublicRouteKind::OidcBootstrap,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
public(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/oidc/callback/{provider_id}",
|
||||
PublicRouteKind::OidcBootstrap,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
public(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/oidc/logout",
|
||||
PublicRouteKind::OidcBootstrap,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(HttpMethod::Get, "/rustfs/admin/v3/oidc/config", SERVER_INFO, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/oidc/config/{provider_id}",
|
||||
CONFIG_UPDATE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/oidc/config/{provider_id}",
|
||||
CONFIG_UPDATE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(HttpMethod::Post, "/rustfs/admin/v3/oidc/validate", SERVER_INFO, RouteRiskLevel::High),
|
||||
admin(HttpMethod::Get, "/iceberg/v1/config", GET_TABLE_CATALOG, RouteRiskLevel::Sensitive),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/iceberg/v1/{warehouse}/namespaces",
|
||||
GET_TABLE_NAMESPACE,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/iceberg/v1/{warehouse}/namespaces",
|
||||
SET_TABLE_NAMESPACE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}",
|
||||
GET_TABLE_NAMESPACE,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}",
|
||||
DELETE_TABLE_NAMESPACE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables",
|
||||
GET_TABLE,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables",
|
||||
CREATE_TABLE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/register",
|
||||
REGISTER_TABLE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Get,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}",
|
||||
GET_TABLE_METADATA,
|
||||
RouteRiskLevel::Sensitive,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Post,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}",
|
||||
COMMIT_TABLE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
admin(
|
||||
HttpMethod::Delete,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}",
|
||||
DELETE_TABLE,
|
||||
RouteRiskLevel::High,
|
||||
),
|
||||
];
|
||||
|
||||
pub const DEFERRED_ADMIN_ROUTE_POLICIES: &[DeferredAdminRoutePolicy] = &[
|
||||
deferred(HttpMethod::Get, "/rustfs/admin/v3/accountinfo", DeferredRoutePolicyReason::S3Action),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/user-info",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Put,
|
||||
"/rustfs/admin/v3/add-user",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/update-service-account",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/info-service-account",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/info-access-key",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/list-service-accounts",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/list-access-keys-bulk",
|
||||
DeferredRoutePolicyReason::MultipleActions,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/delete-service-accounts",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Delete,
|
||||
"/rustfs/admin/v3/delete-service-account",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/idp/builtin/policy-entities",
|
||||
DeferredRoutePolicyReason::MultipleActions,
|
||||
),
|
||||
deferred(HttpMethod::Post, "/rustfs/admin/v3/service", DeferredRoutePolicyReason::NotImplemented),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/inspect-data",
|
||||
DeferredRoutePolicyReason::NotImplemented,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/inspect-data",
|
||||
DeferredRoutePolicyReason::NotImplemented,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/datausageinfo",
|
||||
DeferredRoutePolicyReason::MultipleActions,
|
||||
),
|
||||
deferred(HttpMethod::Get, "/rustfs/admin/v3/metrics", DeferredRoutePolicyReason::CredentialOnly),
|
||||
deferred(HttpMethod::Get, "/rustfs/admin/v3/pools/list", DeferredRoutePolicyReason::MultipleActions),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/pools/status",
|
||||
DeferredRoutePolicyReason::MultipleActions,
|
||||
),
|
||||
deferred(HttpMethod::Get, "/rustfs/admin/v3/get-bucket-quota", DeferredRoutePolicyReason::S3Action),
|
||||
deferred(HttpMethod::Get, "/rustfs/admin/v3/quota/{bucket}", DeferredRoutePolicyReason::S3Action),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/quota-stats/{bucket}",
|
||||
DeferredRoutePolicyReason::S3Action,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Post,
|
||||
"/rustfs/admin/v3/quota-check/{bucket}",
|
||||
DeferredRoutePolicyReason::S3Action,
|
||||
),
|
||||
deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/list-remote-targets",
|
||||
DeferredRoutePolicyReason::CredentialOnly,
|
||||
),
|
||||
];
|
||||
|
||||
pub fn validate_admin_route_policy_specs() -> Result<(), AdminRouteMatrixError> {
|
||||
validate_admin_route_specs(ADMIN_ROUTE_POLICY_SPECS)
|
||||
}
|
||||
|
||||
const fn admin(method: HttpMethod, path: &'static str, action: AdminActionRef, risk_level: RouteRiskLevel) -> AdminRouteSpec {
|
||||
AdminRouteSpec::admin(method, path, action, risk_level)
|
||||
}
|
||||
|
||||
const fn public(method: HttpMethod, path: &'static str, kind: PublicRouteKind, risk_level: RouteRiskLevel) -> AdminRouteSpec {
|
||||
AdminRouteSpec::public(method, path, kind, risk_level)
|
||||
}
|
||||
|
||||
const fn deferred(method: HttpMethod, path: &'static str, reason: DeferredRoutePolicyReason) -> DeferredAdminRoutePolicy {
|
||||
DeferredAdminRoutePolicy::new(method, path, reason)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::admin::router::{AdminOperation, S3Router};
|
||||
use hyper::Method;
|
||||
use serial_test::serial;
|
||||
use std::collections::BTreeSet;
|
||||
use temp_env::with_var;
|
||||
|
||||
#[test]
|
||||
fn admin_route_policy_specs_validate() {
|
||||
assert!(validate_admin_route_policy_specs().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn route_policy_inventory_has_no_internal_overlap() {
|
||||
let mut seen = BTreeSet::new();
|
||||
|
||||
for spec in ADMIN_ROUTE_POLICY_SPECS {
|
||||
let key = route_key(spec.method(), spec.path());
|
||||
assert!(seen.insert(key), "duplicate direct route policy for {}", spec.path());
|
||||
}
|
||||
|
||||
for policy in DEFERRED_ADMIN_ROUTE_POLICIES {
|
||||
let key = route_key(policy.method(), policy.path());
|
||||
assert!(seen.insert(key), "deferred route overlaps direct policy for {}", policy.path());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn route_policy_inventory_covers_registered_routes() {
|
||||
let router = with_var(rustfs_config::ENV_HEALTH_ENDPOINT_ENABLE, Some("true"), || {
|
||||
let mut router = S3Router::<AdminOperation>::new(false);
|
||||
super::super::register_admin_routes(&mut router).expect("register production admin routes");
|
||||
router
|
||||
});
|
||||
|
||||
let registered = router.registered_routes().iter().cloned().collect::<BTreeSet<_>>();
|
||||
let inventory = route_policy_inventory_keys();
|
||||
|
||||
assert_eq!(inventory, registered, "admin route policy inventory must cover every registered route");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn route_policy_keeps_public_exceptions_explicit() {
|
||||
assert_public(HttpMethod::Get, "/health", PublicRouteKind::Health);
|
||||
assert_public(HttpMethod::Head, "/health/ready", PublicRouteKind::Health);
|
||||
assert_public(HttpMethod::Post, "/", PublicRouteKind::StsFormPost);
|
||||
assert_public(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/oidc/authorize/{provider_id}",
|
||||
PublicRouteKind::OidcBootstrap,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn route_policy_keeps_table_catalog_outside_admin_prefix() {
|
||||
let table_specs = ADMIN_ROUTE_POLICY_SPECS
|
||||
.iter()
|
||||
.filter(|spec| spec.path().starts_with("/iceberg/v1"));
|
||||
assert_eq!(table_specs.count(), 11);
|
||||
assert_action(HttpMethod::Get, "/iceberg/v1/{warehouse}/namespaces", GET_TABLE_NAMESPACE);
|
||||
assert_action(HttpMethod::Post, "/iceberg/v1/{warehouse}/namespaces/{namespace}/tables", CREATE_TABLE);
|
||||
assert_action(
|
||||
HttpMethod::Get,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}",
|
||||
GET_TABLE_METADATA,
|
||||
);
|
||||
assert_action(
|
||||
HttpMethod::Post,
|
||||
"/iceberg/v1/{warehouse}/namespaces/{namespace}/tables/{table}",
|
||||
COMMIT_TABLE,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn route_policy_keeps_contextual_auth_deferred() {
|
||||
assert_deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/info-service-account",
|
||||
DeferredRoutePolicyReason::ContextualAuthorization,
|
||||
);
|
||||
assert_deferred(
|
||||
HttpMethod::Get,
|
||||
"/rustfs/admin/v3/datausageinfo",
|
||||
DeferredRoutePolicyReason::MultipleActions,
|
||||
);
|
||||
assert_deferred(HttpMethod::Get, "/rustfs/admin/v3/accountinfo", DeferredRoutePolicyReason::S3Action);
|
||||
}
|
||||
|
||||
fn route_policy_inventory_keys() -> BTreeSet<String> {
|
||||
ADMIN_ROUTE_POLICY_SPECS
|
||||
.iter()
|
||||
.map(|spec| route_key(spec.method(), spec.path()))
|
||||
.chain(
|
||||
DEFERRED_ADMIN_ROUTE_POLICIES
|
||||
.iter()
|
||||
.map(|policy| route_key(policy.method(), policy.path())),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn route_key(method: HttpMethod, path: &str) -> String {
|
||||
format!("{}|{}", method.as_str(), path)
|
||||
}
|
||||
|
||||
fn assert_action(method: HttpMethod, path: &str, action: AdminActionRef) {
|
||||
let spec = ADMIN_ROUTE_POLICY_SPECS
|
||||
.iter()
|
||||
.find(|spec| spec.method() == method && spec.path() == path)
|
||||
.expect("expected direct route policy");
|
||||
assert_eq!(spec.access().admin_action(), Some(action));
|
||||
}
|
||||
|
||||
fn assert_public(method: HttpMethod, path: &str, kind: PublicRouteKind) {
|
||||
let spec = ADMIN_ROUTE_POLICY_SPECS
|
||||
.iter()
|
||||
.find(|spec| spec.method() == method && spec.path() == path)
|
||||
.expect("expected public route policy");
|
||||
assert_eq!(spec.access().public_kind(), Some(kind));
|
||||
}
|
||||
|
||||
fn assert_deferred(method: HttpMethod, path: &str, reason: DeferredRoutePolicyReason) {
|
||||
let policy = DEFERRED_ADMIN_ROUTE_POLICIES
|
||||
.iter()
|
||||
.find(|policy| policy.method() == method && policy.path() == path)
|
||||
.expect("expected deferred route policy");
|
||||
assert_eq!(policy.reason(), reason);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn method_mapping_matches_registered_route_format() {
|
||||
assert_eq!(route_key(HttpMethod::Get, "/health"), Method::GET.as_str().to_string() + "|/health");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user