apache/pulsar · warning · RestException

Unauthorized to validateBothTenantOperationAndSuperUser for

Error message

Unauthorized to validateBothTenantOperationAndSuperUser for originalPrincipal [${originalPrincipal}] and clientAppId [${clientAppId}] about operation [${operation}] 

What it means

HTTP 401 UNAUTHORIZED raised by validateBothSuperUserAndTenantOperation when the caller is neither a superuser (originalPrincipal fails superuser validation) nor authorized for the requested tenant operation (tenant admin role check fails). Both validation paths failed, so the tenancy API call is denied.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java:370

                    }
                    Throwable superUserValidationException = null;
                    try {
                        superUserValidationFuture.join();
                    } catch (Throwable ex) {
                        superUserValidationException = FutureUtil.unwrapCompletionException(ex);
                    }
                    Throwable tenantOperationValidationException = null;
                    try {
                        tenantOperationValidationFuture.join();
                    } catch (Throwable ex) {
                        tenantOperationValidationException = FutureUtil.unwrapCompletionException(ex);
                    }
                    log.debug().attr("originalPrincipal", originalPrincipal())
                            .attr("operation", operation.toString())
                            .attr("superuserValidationError", superUserValidationException)
                            .attr("tenantOperationValidationError", tenantOperationValidationException)
                            .log("validateBothTenantOperationAndSuperUser failed");
                    throw new RestException(Status.UNAUTHORIZED,
                            String.format("Unauthorized to validateBothTenantOperationAndSuperUser for"
                                          + " originalPrincipal [%s] and clientAppId [%s] "
                                          + "about operation [%s] ",
                                    originalPrincipal(), clientAppId(), operation.toString()));
                });
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Grant the role: add it to superUserRoles in broker.conf (restart or dynamic config) for cluster-wide admin, or
  2. Add the role to the tenant's adminRoles via PUT /admin/v2/tenants/{tenant} if it should only manage this tenant.
  3. Verify authentication is mapping the expected role: check clientAppId/originalPrincipal in the message against the credentials presented.
  4. If behind a proxy, ensure the proxy forwards the original principal (authenticateOriginalAuthData=true) so authorization evaluates the right user.
  5. Confirm the operation name in the message matches what the client intends; a wrong endpoint may require higher privileges.

Example fix

// broker.conf before
superUserRoles=admin
// after: grant the client role
superUserRoles=admin,my-admin-client
// or, tenant-scoped:
// after
TenantInfo info = admin.tenants().getTenant("my-tenant");
info.getAdminRoles().add("my-tenant-admin");
admin.tenants().updateTenant("my-tenant", info);
Defensive patterns

Strategy: try-catch

Validate before calling

// Caller-side pre-check
boolean isSuperUser = brokerConfig.getSuperUserRoles().contains(myRole);
boolean isTenantAdmin = tenantInfo.getAdminRoles().contains(myRole);
if (!isSuperUser && !isTenantAdmin) {
    throw new SecurityException("Role " + myRole + " cannot perform tenant operation");
}

Try / catch

try {
    admin.tenants().getTenants();
} catch (PulsarAdminException e) {
    if (e.getStatusCode() == 401) {
        // insufficient privileges: request superuser role or tenant adminRoles grant
        throw new SecurityException("Not authorized for tenant operation; need superuser or adminRoles", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: GET/PUT/DELETE /admin/v2/tenants* endpoints (getTenants, getTenantAdmin, createTenant, updateTenant, deleteTenant) invoked by a principal lacking superuser role and not listed in the tenant's adminRoles; common with authenticated clients whose role is not mapped in superUserRoles or the tenant policy.

Common situations: Client authenticated with a role certificate/token but superUserRoles in broker.conf doesn't include it; tenant adminRoles not updated after team changes; proxy/stripped original principal (originalPrincipal not propagated through proxy authentication); use of admin API key without tenant-level grants.

Understand the failure class

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/860f565327789ee5. Report an issue: GitHub.