From 640cdd3774cae5042430ce2a0f4ae85f0d1b241c Mon Sep 17 00:00:00 2001 From: shirady <57721533+shirady@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:46:36 +0200 Subject: [PATCH] IAM | No Bucket Policy Authorization for Users Signed-off-by: shirady <57721533+shirady@users.noreply.github.com> --- src/api/bucket_api.js | 3 +++ src/endpoint/s3/s3_rest.js | 13 +++++++++---- src/sdk/object_sdk.js | 3 ++- src/server/common_services/auth_server.js | 8 +++++++- src/server/system_services/bucket_server.js | 1 + 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/api/bucket_api.js b/src/api/bucket_api.js index 069b4a8e91..8689c17d76 100644 --- a/src/api/bucket_api.js +++ b/src/api/bucket_api.js @@ -1207,6 +1207,9 @@ module.exports = { bucket_owner: { $ref: 'common_api#/definitions/email' }, + bucket_owner_id: { + type: 'string' + }, website: { $ref: 'common_api#/definitions/bucket_website' }, diff --git a/src/endpoint/s3/s3_rest.js b/src/endpoint/s3/s3_rest.js index a24d52373d..b3f93cc21a 100755 --- a/src/endpoint/s3/s3_rest.js +++ b/src/endpoint/s3/s3_rest.js @@ -238,6 +238,7 @@ async function authorize_request_policy(req) { s3_policy, system_owner, bucket_owner, + bucket_owner_id, owner_account, public_access_block, } = await req.object_sdk.read_bucket_sdk_policy_info(req.params.bucket); @@ -253,8 +254,9 @@ async function authorize_request_policy(req) { } const account = req.object_sdk.requesting_account; - const account_identifier_name = req.object_sdk.nsfs_config_root ? account.name.unwrap() : account.email.unwrap(); - const account_identifier_id = req.object_sdk.nsfs_config_root ? account._id : undefined; + const is_nc_deployment = req.object_sdk.nsfs_config_root; + const account_identifier_name = is_nc_deployment ? account.name.unwrap() : account.email.unwrap(); + const account_identifier_id = is_nc_deployment ? account._id : undefined; const account_identifier_arn = s3_bucket_policy_utils.get_bucket_policy_principal_arn(account); // deny delete_bucket permissions from bucket_claim_owner accounts (accounts that were created by OBC from openshift\k8s) @@ -286,8 +288,11 @@ async function authorize_request_policy(req) { if (!s3_policy) { // in case we do not have bucket policy // we allow IAM account to access a bucket that is owned by their root account - const is_iam_account_and_same_root_account_owner = account.owner !== undefined && - owner_account && account.owner === owner_account.id; + let is_iam_account_and_same_root_account_owner = false; + if (account.owner !== undefined) { + const owner_account_to_compare = is_nc_deployment ? (owner_account && owner_account.id) : bucket_owner_id; + is_iam_account_and_same_root_account_owner = account.owner === owner_account_to_compare; + } if (is_owner || is_iam_account_and_same_root_account_owner) return; throw new S3Error(S3Error.AccessDenied); } diff --git a/src/sdk/object_sdk.js b/src/sdk/object_sdk.js index 9044241cb6..a109c7c5e6 100644 --- a/src/sdk/object_sdk.js +++ b/src/sdk/object_sdk.js @@ -218,7 +218,8 @@ class ObjectSDK { s3_policy: bucket.s3_policy, system_owner: bucket.system_owner, // note that bucketspace_fs currently doesn't return system_owner bucket_owner: bucket.bucket_owner, - owner_account: bucket.owner_account, // in NC NSFS this is the account id that owns the bucket + bucket_owner_id: bucket.bucket_owner_id, // in containerized this is the account id that owns the bucket + owner_account: bucket.owner_account, // in NC NSFS this is an object of account id and name that owns the bucket public_access_block: bucket.public_access_block, }; return policy_info; diff --git a/src/server/common_services/auth_server.js b/src/server/common_services/auth_server.js index 24330b3549..5c2116f0ce 100644 --- a/src/server/common_services/auth_server.js +++ b/src/server/common_services/auth_server.js @@ -545,7 +545,13 @@ async function has_bucket_action_permission(bucket, account, action, req_query, (account.bucket_claim_owner && account.bucket_claim_owner.name.unwrap() === bucket.name.unwrap()); const bucket_policy = bucket.s3_policy; - if (!bucket_policy) return is_owner; + if (!bucket_policy) { + // in case we do not have bucket policy + // we allow IAM account to access a bucket that that is owned by their root account + const is_iam_and_same_root_account_owner = account.owner !== undefined && + account.owner._id.toString() === bucket.owner_account._id.toString(); + return is_owner || is_iam_and_same_root_account_owner; + } if (!action) { throw new Error('has_bucket_action_permission: action is required'); } diff --git a/src/server/system_services/bucket_server.js b/src/server/system_services/bucket_server.js index d4593cd9df..e336e4e9d6 100644 --- a/src/server/system_services/bucket_server.js +++ b/src/server/system_services/bucket_server.js @@ -733,6 +733,7 @@ async function read_bucket_sdk_info(req) { s3_policy: bucket.s3_policy, system_owner: bucket.system.owner.email, bucket_owner: bucket.owner_account.email, + bucket_owner_id: bucket.owner_account._id.toString(), bucket_info: await P.map_props({ bucket, nodes_aggregate_pool: bucket.tiering && nodes_client.instance().aggregate_nodes_by_pool(pool_names, system._id),