Skip to content

Adding Enforcement checks for Directiveshandler and RecipeHandler - #1041

Open
sahusanket wants to merge 1 commit into
developfrom
enforcement_wrangler_handlers
Open

Adding Enforcement checks for Directiveshandler and RecipeHandler#1041
sahusanket wants to merge 1 commit into
developfrom
enforcement_wrangler_handlers

Conversation

@sahusanket

Copy link
Copy Markdown
Contributor

No description provided.

@sahusanket
sahusanket requested a review from vsethi09 September 2, 2026 10:22
@sahusanket sahusanket self-assigned this Sep 2, 2026
@sahusanket sahusanket added the build Triggers unit test build label Sep 2, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces authorization enforcement checks across various endpoints in DirectivesHandler and RecipeHandler when the WRANGLER_WORKSPACE_AUTH_CHECK feature flag is enabled. It utilizes ContextAccessEnforcer to enforce permissions such as CREATE, LIST, DELETE, GET, USE, and UPDATE on workspace and recipe entities. The review feedback highlights a few issues with the implementation: first, the respond helper method does not catch UnauthorizedException, which will result in a 500 Internal Server Error instead of a 401/403 status code; second, the upload endpoint should dynamically enforce CREATE or UPDATE permissions depending on whether the workspace already exists; and third, the uploadData endpoint should enforce UPDATE instead of CREATE since it operates on an existing workspace.

Comment on lines +181 to +183
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.CREATE);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The respond overload used in DirectivesHandler (defined in AbstractWranglerHandler.java as protected <T> void respond(HttpServiceRequest request, HttpServiceResponder responder, String namespace, NamespacedResponder<T> callable)) does not catch UnauthorizedException.\n\nAs a result, any authorization enforcement failure (which throws UnauthorizedException) will fall through to the generic catch (Throwable t) block, returning a 500 Internal Server Error instead of the correct 403 Forbidden or 401 Unauthorized status code.\n\nPlease update the respond overload in AbstractWranglerHandler.java to catch and handle UnauthorizedException properly, similar to how it is handled in the other respond overload.

Comment on lines +397 to +399
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id.getId()), StandardPermission.CREATE);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

The upload endpoint can either create a new workspace or overwrite/update an existing one if a workspace with the same name already exists.\n\nBy only enforcing StandardPermission.CREATE, a user who has permission to create workspaces but not update existing ones could overwrite and modify an existing workspace. Conversely, a user who has UPDATE permission but not CREATE permission would be blocked from updating an existing workspace via this endpoint.\n\nConsider checking if the workspace exists inside the transaction, and dynamically enforcing StandardPermission.UPDATE or StandardPermission.CREATE based on its existence:\n\njava\n return TransactionRunners.run(getContext(), context -> {\n WorkspaceDataset ws = WorkspaceDataset.get(context);\n if (authEnforcementEnabled) {\n StandardPermission permission = ws.hasWorkspace(id) ? StandardPermission.UPDATE : StandardPermission.CREATE;\n contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id.getId()), permission);\n }\n

Comment on lines +489 to +491
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.CREATE);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The uploadData endpoint is used to upload data to an existing workspace and does not create a new one (it throws WorkspaceNotFoundException if the workspace is not found). Therefore, it should enforce StandardPermission.UPDATE instead of StandardPermission.CREATE.

Suggested change
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.CREATE);
}
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.UPDATE);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be USE or UPDATE?

See similar patterns used in CDAP.

@PathParam("context") String namespace, @PathParam("id") String id) {
respond(request, responder, namespace, ns -> {
if (authEnforcementEnabled) {
contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.GET);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be USE or UPDATE?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

USE

*/

package io.cdap.wrangler.service.directive;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Revert removal of line.

* Service for managing workspaces and also application of directives on to the workspace.
*/
@Deprecated
public class DirectivesHandler extends AbstractDirectiveHandler {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Add checks for all Methods, including directives config.

super.initialize(context);
recipeStore = new RecipeStore(context);
contextAccessEnforcer = context.getContextAccessEnforcer();
authEnforcementEnabled = Feature.WRANGLER_WORKSPACE_AUTH_CHECK.isEnabled(context);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same feature flag should not be used for Recipes resource.

@PathParam("recipe-name") String recipeName) {
respond(responder, namespace, ns -> {
responder.sendJson(recipeStore.getRecipeByName(ns, recipeName));
Recipe recipe = recipeStore.getRecipeByName(ns, recipeName);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Auth check should happen before any store reads / writes.

import io.cdap.wrangler.dataset.recipe.RecipePageRequest;
import io.cdap.wrangler.dataset.recipe.RecipeRow;
import io.cdap.wrangler.proto.BadRequestException;
import io.cdap.wrangler.proto.id.RecipeEntityId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this class exist? I can't find it.

@PathParam("id") String id, @QueryParam("name") String name,
@QueryParam("scope") @DefaultValue(WorkspaceDataset.DEFAULT_SCOPE) String scope) {
respond(request, responder, namespace, ns -> {
if (authEnforcementEnabled) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is a repeated pattern of code, which can be improved:

      if (authEnforcementEnabled) {
        contextAccessEnforcer.enforce(new WorkspaceEntityId(ns.getName(), id), StandardPermission.CREATE);
      }

@sahusanket
sahusanket force-pushed the enforcement_wrangler_handlers branch from 665d9bd to acf1c4e Compare September 3, 2026 12:59
@sahusanket
sahusanket force-pushed the enforcement_wrangler_handlers branch from acf1c4e to ce5c626 Compare September 3, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Triggers unit test build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants