Skip to content

Conversation

@shirady
Copy link
Contributor

@shirady shirady commented Nov 13, 2025

Describe the Problem

Add a step in s3_rest to authorize requests for IAM users according to the IAM user inline policy.

Explain the Changes

  1. Add the function authorize_request_iam_policy and call it from authorize_request.
  2. Add properties that I need for this step in account_info (owner and iam_user_policies).

Issues:

List of GAPs:

  1. The tests are only manual at this point; there is a plan to add automated tests after we have the design change.
  2. I might want to refactor the code so that s3_bucket_policy_utils.js so the terms will be policy in general and can be used for bucket policy and IAM policy.
  3. I might want to move the created function somewhere else (perhaps iam_rest) so the thrown error will be amError.AccessDeniedException instead of S3Error.AccessDenied

Design Decisions:

  • When there is no IAM user policy, it is authorized for this step (didn't want to change default behavior).
  • The IAM policy authorization is done in parallel - I had the option to do it sequentially, meaning policy after policy - get the resolved promise answer and work on it (DENY throws an error), but I decided to do it in parallel, assuming that the total user policy is limited. If I were to do it sequentially, I would need to wait for every policy check, instead of running all the checks and waiting for all the promises to be resolved and work on the result (DENY, ALLOW, IMPLICIT_DENY). I also decided to check in parallel to the bucket policy, and I had the option to do it after, as in the case where there is an IAM user policy with DENY, we would like it to be thrown as part of the calculation.

Testing Instructions:

  1. Build the images and install NooBaa system on Rancher Desktop (see guide).
    Note: nb is an alias that runs the local operator from build/_output/bin (alias created by devenv).
  2. Wait for the default backing store pod to be in state Ready before starting the tests: kubectl wait --for=condition=available backingstore/noobaa-default-backing-store --timeout=6m -n test1
  3. I'm using port-forward (in a different tab):
  • S3 kubectl port-forward -n test1 service/s3 12443:443
  • IAM kubectl port-forward -n test1 service/iam 14443:443
  1. Create the alias for the admin - first, need to get the credentials: nb status --show-secrets -n test1 and then:
    alias admin-s3='AWS_ACCESS_KEY=<access-key> AWS_SECRET_ACCESS_KEY=<secret-key> aws --no-verify-ssl --endpoint-url https://localhost:12443'
    alias admin-iam='AWS_ACCESS_KEY=<access-key> AWS_SECRET_ACCESS_KEY=<secret-key> aws --no-verify-ssl --endpoint-url https://localhost:14443'
  2. Check the connection to the endpoint:
  • try to list the users (should be an empty list): admin-iam iam list-users; echo $?
  • try to list the buckets (should be first.bucket): admin-iam s3 ls; echo $?
  1. Create a user: admin-iam iam create-user --user-name Robert
    Note: To validate user creation, you can rerun admin-iam iam list-users and expect 1 user in the list
  2. Create access keys: admin-iam iam create-access-keys --user-name Robert
  3. Create the alias for the user (like in step 4 with alias user-2-s3).
  4. The case with no bucket policy, no IAM policy - the user will not be restricted from S3 operation, for example:
  • The user creates a bucket: user-2-s3 s3 mb s3://mybucket (should work).
  • The user put an object in that bucket: echo 'test_data' | user-2-s3 s3 cp - s3://first.bucket/test_object.txt (should work).
  1. The admin adds an inline policy so he cannot create a bucket, but can put an object.
    policy_deny_create_bucket_allow_put_object.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "s3:CreateBucket"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "*"
        }
    ]
}
  1. admin-iam iam put-user-policy --user-name Robert --policy-name policy_deny_create_bucket_allow_put_object --policy-document file://policy_deny_create_bucket_allow_put_object.json
  2. Repeat step 10:
  • The user put an object in that bucket: echo 'test_data' | user-2-s3 s3 cp - s3://first.bucket/test_object2.txt (should work).
  • The user creates a bucket: user-2-s3 mb mybucket2 (should throw AccessDenied error).

Code changes for testing:

  1. To see the account (of a user) in the cache after changes, src/sdk/object_sdk.js uses cache expiry of 1 millisecond.
const account_cache = new LRUCache({
    name: 'AccountCache',
-    expiry_ms: config.OBJECT_SDK_ACCOUNT_CACHE_EXPIRY_MS,
+   expiry_ms: 1, //SDSD 
  1. (temporarily) Not to be blocked on authorization by bucket policy src/endpoint/s3/s3_rest.js in the if (!s3_policy) { remove the error thrown as currently owner_account in NC deployment and is undefined. rest of the code in else condition.

Notes:

  • In step 1 - deploying the system, I used --use-standalone-db for simplicity (fewer steps for the system in Ready status).

  • I used the admin account, but for IAM operations, there is no difference between a created account and an admin account. I tested with the admin only because it saves steps (I have the admin account upon system creation and a bucket).

  • Doc added/updated

  • Tests added

Summary by CodeRabbit

  • New Features
    • Accounts can include an owner field and associated IAM user policies surfaced in account info.
    • S3 authorization now evaluates IAM user inline policies in parallel with existing bucket/account policies.
    • Bucket permission checks honor public-access restrictions when evaluating permissions.

@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Walkthrough

Adds iam_user_policies and owner to account_info; extends bucket policy evaluation APIs to accept { disallow_public_access, should_pass_principal } and allow skipping principal checks; integrates IAM user inline policy evaluation into S3 authorization flow running in parallel with existing checks.

Changes

Cohort / File(s) Summary
Account Schema Extension
src/api/account_api.js
Adds iam_user_policies (array of common_api#/definitions/iam_user_policy) and owner (string) to definitions.account_info.
Account Info Output
src/server/system_services/account_server.js
get_account_info now conditionally includes iam_user_policies and owner when present on the account.
Bucket Policy Utils (signature changes)
src/endpoint/s3/s3_bucket_policy_utils.js
Function signatures updated to accept an options object: has_bucket_policy_permission(..., { disallow_public_access = false, should_pass_principal = true } = {}), is_statement_fit_of_method_array(..., { ... } = {}), and _is_statements_fit(..., { ... } = {}); should_pass_principal can bypass principal checks when false.
S3 Authorization Flow
src/endpoint/s3/s3_rest.js
Adds authorize_request_iam_policy(req) to evaluate IAM user inline policies (DENY short-circuits, any ALLOW permits); authorize_request(req) now runs IAM policy checks in parallel with account and bucket policy checks; existing calls now pass { disallow_public_access: ... } wrappers.
SDK Permission Calls
src/sdk/bucketspace_fs.js
Calls updated to pass { disallow_public_access: bucket.public_access_block?.restrict_public_buckets } to bucket permission checks instead of a raw boolean.

Sequence Diagram(s)

sequenceDiagram
    participant Req as S3 Request
    participant Auth as authorize_request
    participant Acc as account policy check
    participant BP as bucket policy check
    participant IAM as IAM user policy check
    participant Utils as bucket policy utils

    Req->>Auth: incoming S3 operation
    Auth->>Acc: run account-level check
    Auth->>BP: run bucket policy check
    Auth->>IAM: run IAM user inline policy check (new, parallel)

    alt IAM user inline policy present
        IAM->>Utils: evaluate iam_user_policies (passes {disallow_public_access, should_pass_principal})
        Utils-->>IAM: DENY / ALLOW / none
        alt DENY
            IAM-->>Auth: DENY (short-circuit)
        else ALLOW
            IAM-->>Auth: ALLOW (can permit)
        else none
            IAM-->>Auth: no decision
        end
    else no IAM user policies or anonymous
        IAM-->>Auth: skipped
    end

    alt any DENY
        Auth-->>Req: Access Denied
    else any ALLOW and no DENY
        Auth-->>Req: Access Granted
    else no decision
        Auth-->>Req: Access Denied (default)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review authorization short-circuiting and Promise.all error handling in src/endpoint/s3/s3_rest.js.
  • Verify should_pass_principal behavior in src/endpoint/s3/s3_bucket_policy_utils.js cannot be misused to bypass required principal validation.
  • Check all call sites updated to the options object shape (e.g., src/sdk/bucketspace_fs.js) for consistency.

Possibly related PRs

Suggested reviewers

  • aayushchouhan09
  • liranmauda
  • dannyzaken

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: adding IAM user inline policy authorization for S3 requests, which is the primary feature across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd19105 and 55850a2.

📒 Files selected for processing (5)
  • src/api/account_api.js (1 hunks)
  • src/endpoint/s3/s3_bucket_policy_utils.js (2 hunks)
  • src/endpoint/s3/s3_rest.js (3 hunks)
  • src/sdk/bucketspace_fs.js (2 hunks)
  • src/server/system_services/account_server.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/endpoint/s3/s3_rest.js
  • src/server/system_services/account_server.js
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-08T13:08:38.361Z
Learnt from: naveenpaul1
Repo: noobaa/noobaa-core PR: 9182
File: src/server/system_services/bucket_server.js:1324-1327
Timestamp: 2025-08-08T13:08:38.361Z
Learning: In src/server/system_services/bucket_server.js, the update_all_buckets_default_pool(req) handler expects req.rpc_params.pool_name to be a plain string (not a SensitiveString wrapper), so calling .unwrap() is not needed there.

Applied to files:

  • src/sdk/bucketspace_fs.js
📚 Learning: 2025-11-12T04:55:42.193Z
Learnt from: naveenpaul1
Repo: noobaa/noobaa-core PR: 9277
File: src/endpoint/s3/s3_rest.js:258-261
Timestamp: 2025-11-12T04:55:42.193Z
Learning: In the context of S3 REST requests (src/endpoint/s3/s3_rest.js), the account.owner field from req.object_sdk.requesting_account is already a string (account ID) because it comes from RPC serialization where owner._id.toString() is applied in account_server.js. No additional .toString() or ._id extraction is needed when passing account.owner to IAM utility functions.

Applied to files:

  • src/api/account_api.js
📚 Learning: 2025-11-13T07:56:23.620Z
Learnt from: shirady
Repo: noobaa/noobaa-core PR: 9281
File: src/server/system_services/account_server.js:1053-1058
Timestamp: 2025-11-13T07:56:23.620Z
Learning: In noobaa-core, account_server.js is only used in containerized deployments, not in NSFS/NC deployments. NSFS/NC deployments have separate account management code in src/manage_nsfs/ directory. Therefore, account_server.js only processes accounts from account_schema.js where owner is an objectid reference, never from nsfs_account_schema.js where owner is a string.

Applied to files:

  • src/api/account_api.js
🧬 Code graph analysis (1)
src/endpoint/s3/s3_bucket_policy_utils.js (1)
src/endpoint/s3/s3_rest.js (10)
  • account (256-256)
  • account (329-329)
  • method (248-248)
  • method (334-334)
  • method (461-461)
  • arn_path (247-247)
  • arn_path (393-393)
  • req (238-244)
  • req (405-405)
  • _ (4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: run-jest-unit-tests
  • GitHub Check: run-package-lock-validation
  • GitHub Check: Build Noobaa Image
🔇 Additional comments (8)
src/sdk/bucketspace_fs.js (2)

954-954: LGTM! Correct adaptation to the new options object pattern.

The change from passing a raw boolean to an options object { disallow_public_access: bucket.public_access_block?.restrict_public_buckets } correctly aligns with the updated has_bucket_policy_permission signature in s3_bucket_policy_utils.js. The should_pass_principal parameter defaults to true, which is appropriate for bucket policy evaluation.


966-966: LGTM! Consistent with the permission_by_id path.

The same options object pattern is correctly applied here for the permission_by_name evaluation path.

src/endpoint/s3/s3_bucket_policy_utils.js (5)

152-153: LGTM! Well-designed options pattern.

The function signature correctly adopts the options object pattern with sensible defaults. The disallow_public_access = false and should_pass_principal = true defaults preserve existing behavior for callers that don't provide these options.


160-165: LGTM! Correct handling for deny statements.

Explicitly setting disallow_public_access: false for deny statements is appropriate—deny rules should not be restricted by public access blocks. The should_pass_principal is correctly forwarded.


169-173: LGTM! Consistent options forwarding for allow statements.

Both options are correctly forwarded to the allow evaluation path, maintaining the intended behavior distinctions between deny and allow statement processing.


228-231: LGTM! Consistent API through the call chain.

The options object pattern is consistently propagated through is_statement_fit_of_method_array to _is_statements_fit, maintaining a clean and predictable API.


234-240: LGTM! Clear logic for bypassing principal checks.

The implementation correctly handles the IAM user inline policy use case where no Principal field exists. When should_pass_principal is false, principal_fit is set to true, effectively bypassing the principal check. The comment clearly explains the rationale.

src/api/account_api.js (1)

753-761: Schema definition verified—changes approved.

The iam_user_policy definition exists in src/api/common_api.js (lines 563–572) and is correctly structured with required fields policy_name and policy_document. The reference in src/api/account_api.js (line 756) is valid and consistent with usage elsewhere in the codebase.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed6b491 and ee065ea.

📒 Files selected for processing (4)
  • src/api/account_api.js (1 hunks)
  • src/endpoint/s3/s3_bucket_policy_utils.js (2 hunks)
  • src/endpoint/s3/s3_rest.js (2 hunks)
  • src/server/system_services/account_server.js (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-12T04:55:42.171Z
Learnt from: naveenpaul1
Repo: noobaa/noobaa-core PR: 9277
File: src/endpoint/s3/s3_rest.js:258-261
Timestamp: 2025-11-12T04:55:42.171Z
Learning: In the context of S3 REST requests (src/endpoint/s3/s3_rest.js), the account.owner field from req.object_sdk.requesting_account is already a string (account ID) because it comes from RPC serialization where owner._id.toString() is applied in account_server.js. No additional .toString() or ._id extraction is needed when passing account.owner to IAM utility functions.

Applied to files:

  • src/endpoint/s3/s3_rest.js
  • src/server/system_services/account_server.js
  • src/api/account_api.js
🧬 Code graph analysis (3)
src/endpoint/s3/s3_rest.js (3)
src/endpoint/s3/s3_bucket_policy_utils.js (2)
  • account (283-283)
  • dbg (5-5)
src/endpoint/iam/iam_rest.js (2)
  • method (217-217)
  • dbg (4-4)
src/endpoint/sts/sts_rest.js (3)
  • method (137-137)
  • method (165-165)
  • dbg (5-5)
src/server/system_services/account_server.js (2)
src/util/account_util.js (6)
  • account (32-44)
  • account (198-198)
  • account (306-306)
  • account (331-331)
  • account (370-370)
  • account (645-645)
src/server/system_services/bucket_server.js (1)
  • info (1483-1530)
src/endpoint/s3/s3_bucket_policy_utils.js (1)
src/endpoint/s3/s3_rest.js (10)
  • account (256-256)
  • account (322-322)
  • method (248-248)
  • method (327-327)
  • method (451-451)
  • arn_path (247-247)
  • arn_path (383-383)
  • req (238-244)
  • req (395-395)
  • _ (4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-jest-unit-tests
  • GitHub Check: run-package-lock-validation

@shirady shirady self-assigned this Nov 13, 2025
@shirady shirady force-pushed the iam-user-policy-rest-s3 branch from a1d02e4 to 48d50d3 Compare November 17, 2025 07:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/endpoint/s3/s3_rest.js (1)

221-231: IAM inline policy hook and evaluation logic look sound; consider minor refinements

  • Adding authorize_request_iam_policy(req) into the existing Promise.all([...]) preserves the “all checks must pass” semantics and keeps load_requesting_account() serialized ahead of all checks, which is good.
  • In authorize_request_iam_policy the short‑circuiting for anonymous requests, non‑IAM accounts (account.owner === undefined), and missing/empty iam_user_policies correctly preserves the previous behavior when no IAM user policy is present.
  • Reusing has_bucket_policy_permission with should_pass_principal = false is a reasonable way to leverage existing evaluation logic for IAM inline (identity‑based) policies that lack a Principal element.
  • The DENY/ALLOW reduction over permission_result matches IAM semantics (any explicit DENY wins; any ALLOW with no DENY allows). The current loop is fine; if you want, you could micro‑optimize by returning immediately upon the first "DENY" and short‑circuiting once has_allow_permission is true and no later "DENY" is possible, but this is purely optional.

One small nit: the debug log "user have inline policies..." is slightly misleading because non‑matching could be due to resource or conditions, not only “method”; if you touch this again, consider including the action and ARN or rephrasing the message, but it’s not a blocker.

Also applies to: 321-355

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1d02e4 and 48d50d3.

📒 Files selected for processing (4)
  • src/api/account_api.js (1 hunks)
  • src/endpoint/s3/s3_bucket_policy_utils.js (2 hunks)
  • src/endpoint/s3/s3_rest.js (2 hunks)
  • src/server/system_services/account_server.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/api/account_api.js
  • src/server/system_services/account_server.js
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-12T04:55:42.193Z
Learnt from: naveenpaul1
Repo: noobaa/noobaa-core PR: 9277
File: src/endpoint/s3/s3_rest.js:258-261
Timestamp: 2025-11-12T04:55:42.193Z
Learning: In the context of S3 REST requests (src/endpoint/s3/s3_rest.js), the account.owner field from req.object_sdk.requesting_account is already a string (account ID) because it comes from RPC serialization where owner._id.toString() is applied in account_server.js. No additional .toString() or ._id extraction is needed when passing account.owner to IAM utility functions.

Applied to files:

  • src/endpoint/s3/s3_rest.js
🧬 Code graph analysis (1)
src/endpoint/s3/s3_bucket_policy_utils.js (1)
src/endpoint/s3/s3_rest.js (10)
  • account (256-256)
  • account (326-326)
  • method (248-248)
  • method (331-331)
  • method (455-455)
  • arn_path (247-247)
  • arn_path (387-387)
  • req (238-244)
  • req (399-399)
  • _ (4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-package-lock-validation
  • GitHub Check: run-jest-unit-tests
🔇 Additional comments (1)
src/endpoint/s3/s3_bucket_policy_utils.js (1)

152-171: All call sites are backward compatible; no issues found

Verification confirms that all eight call sites of has_bucket_policy_permission remain fully compatible:

  • Five call sites pass 5 arguments, relying on both new defaults
  • Three additional call sites pass 6 arguments (the existing disallow_public_access), relying on the new should_pass_principal default
  • One call site (s3_rest.js:339) explicitly passes 7 arguments, correctly passing should_pass_principal=false for the IAM inline-policy path

The parameter signature extension preserves backward compatibility and is correctly wired throughout the codebase.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/endpoint/s3/s3_bucket_policy_utils.js (1)

238-238: Consider adding a clarifying comment.

The conditional principal check correctly bypasses validation when should_pass_principal is false, which is used for IAM user inline policies that don't have a Principal field. However, a brief comment explaining this use case would improve code clarity for future maintainers.

Example:

+        // When evaluating IAM user inline policies, should_pass_principal is false since these policies
+        // don't have a Principal field (the principal is implicitly the user the policy is attached to)
         const principal_fit = should_pass_principal ? _is_principal_fit(account, statement, disallow_public_access) : true;
src/endpoint/s3/s3_rest.js (1)

341-341: Fix minor grammar issue in comment.

Apply this diff:

-        // We reusing the bucket policy util function as it is checks the policy document
+        // We are reusing the bucket policy util function as it checks the policy document
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48d50d3 and cd19105.

📒 Files selected for processing (3)
  • src/endpoint/s3/s3_bucket_policy_utils.js (2 hunks)
  • src/endpoint/s3/s3_rest.js (3 hunks)
  • src/sdk/bucketspace_fs.js (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-12T04:55:42.193Z
Learnt from: naveenpaul1
Repo: noobaa/noobaa-core PR: 9277
File: src/endpoint/s3/s3_rest.js:258-261
Timestamp: 2025-11-12T04:55:42.193Z
Learning: In the context of S3 REST requests (src/endpoint/s3/s3_rest.js), the account.owner field from req.object_sdk.requesting_account is already a string (account ID) because it comes from RPC serialization where owner._id.toString() is applied in account_server.js. No additional .toString() or ._id extraction is needed when passing account.owner to IAM utility functions.

Applied to files:

  • src/endpoint/s3/s3_rest.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: run-package-lock-validation
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-jest-unit-tests
🔇 Additional comments (5)
src/sdk/bucketspace_fs.js (1)

954-954: LGTM!

The updated calls correctly pass the disallow_public_access flag wrapped in an options object, aligning with the extended has_bucket_policy_permission signature that now accepts an options parameter.

Also applies to: 966-966

src/endpoint/s3/s3_bucket_policy_utils.js (1)

152-153: LGTM!

The options object approach with default parameter values maintains backwards compatibility while supporting the new IAM policy evaluation flow. Setting disallow_public_access: false specifically for DENY statement evaluation (line 162) is appropriate since public access restrictions aren't needed when evaluating denials.

Also applies to: 161-164, 170-173, 228-229, 231-231, 234-235

src/endpoint/s3/s3_rest.js (3)

227-230: LGTM! Clear parallel authorization flow.

The addition of IAM policy checks alongside bucket policy checks is well-structured. The comments clearly distinguish that bucket policy checks affect owners (with explicit DENY overrides) while IAM policy checks apply only to IAM users.


304-306: LGTM! Consistent refactoring to options object.

The change from passing a boolean disallow_public_access parameter to an options object { disallow_public_access: ... } is applied consistently across all call sites and improves extensibility for additional options.

Also applies to: 313-314, 365-367


324-359: LGTM! Solid IAM policy evaluation logic.

The implementation correctly:

  • Filters for authenticated IAM users only
  • Preserves default behavior when no IAM policies exist (line 336 early return)
  • Evaluates policies in parallel for performance
  • Enforces explicit DENY precedence (immediate failure on line 351)
  • Requires at least one ALLOW to succeed
  • Handles IMPLICIT DENY correctly (no ALLOW → AccessDenied)

The reuse of s3_bucket_policy_utils.has_bucket_policy_permission with { should_pass_principal: false } is appropriate for IAM inline policies that don't contain a Principal element. The should_pass_principal parameter correctly skips principal validation when set to false (line 238 of s3_bucket_policy_utils.js), which is the intended behavior for IAM inline policies.

…olicy

Signed-off-by: shirady <57721533+shirady@users.noreply.github.com>
@shirady shirady force-pushed the iam-user-policy-rest-s3 branch from cd19105 to 55850a2 Compare November 17, 2025 14:38
@liranmauda liranmauda merged commit 45fe1e7 into noobaa:master Nov 17, 2025
15 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants