apache/cassandra · warning · java.lang.SecurityException

Access Denied

Error message

Access Denied

What it means

This is the terminal authorization failure: authorize(subject, methodName, args) returned false for the authenticated JMX client's operation, so the proxy throws SecurityException("Access Denied") at line 200. It means the calling role does not hold the JMX permission (e.g. READ/WRITE/EXECUTE on the target MBean) required by the configured IAuthorizer, or authorization is required but no matching permission was found.

Solutions

  1. Grant the role the needed JMX permission, e.g. GRANT EXECUTE ON MBEAN 'org.apache.cassandra.db:type=StorageService' TO role; (or READ/ WRITE as appropriate).
  2. Verify the authorizer: set authorizer: CassandraAuthorizer and jmx authorization on in cassandra.yaml; permissions may be cached — shorten permissions_validity_in_ms or run a fresh login to pick up new grants.
  3. Inspect the audit log entry emitted by listener.onFailure (JmxInvocationHandler/AuditLogManager) to see exactly which subject/method/target was denied, then grant precisely that permission.
  4. If the operation targets a pattern ObjectName, grant permissions on every matching MBean or narrow the query.

Example fix

// before: role with no grants — monitoring fails with Access Denied
// after (cqlsh):
GRANT SELECT ON ALL MBEANS TO monitoring_role;
// or narrower:
GRANT EXECUTE ON MBEANS 'org.apache.cassandra.net:type=FailureDetector' TO monitoring_role;
Defensive patterns

Strategy: validation

Validate before calling

// cqlsh pre-check for the role's grants before using the JMX role in tooling:
// LIST ALL PERMISSIONS OF monitoring_role;
// ensure the required permission (READ/WRITE/EXECUTE on the target MBEAN(S)) appears.

Try / catch

try {
    return connection.getAttribute(objectName, attribute);
} catch (SecurityException e) {
    logger.error("JMX access denied for " + objectName + "; check GRANT ... ON MBEAN(S) ... TO <role>", e);
    throw e; // retrying without a grant will never succeed
}

Prevention

When it happens

Trigger: An authenticated subject invokes any MBeanServerConnection method (getAttribute, setAttribute, invoke, queryNames, etc.) whose required JMX Permission — determined per Permissions/PermissionsMapping and the object name — is not granted to any of the subject's roles via LIST AUTHORIZED JMX / IAuthorizer permissions.

Common situations: Monitoring users (e.g. Prometheus JMX exporter) connected with a role lacking read grants on org.apache.cassandra.* MBeans; calling EXECUTE-style MBean methods (like repair or snapshot) with a read-only role; forgetting to GRANT JMX permissions after switching authorizer to CassandraAuthorizer; pattern ObjectName targets where none of the matching MBeans are authorized.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ff9290b45bacf10f. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/auth/jmx/AuthorizationProxy.java:200

                if (args[0] == null)
                    throw new IllegalArgumentException("Null MBeanServer");

                if (mbs != null)
                    throw new IllegalArgumentException("MBeanServer already initialized");

                mbs = (MBeanServer) args[0];
                return null;
            }

            if (authorize(subject, methodName, args))
            {
                Object invoke = invoke(method, args);
                listener.onInvocation(subject, method, args);
                return invoke;
            }

            throw new SecurityException("Access Denied");
        }
        catch (Exception e)
        {
            listener.onFailure(subject, method, args, e);
            throw e;
        }
    }

    /**
     * Performs the actual authorization of an identified subject to execute a remote method invocation.
     * @param subject The principal making the execution request. A null value represents a local invocation
     *                from the JMX connector itself
     * @param methodName Name of the method being invoked
     * @param args Array containing invocation argument. If the first element is an ObjectName instance, for
     *             authz purposes we consider this an invocation of an MBean method, otherwise it is treated
     *             as an invocation of a method on the MBeanServer.
     */
    @VisibleForTesting

View on GitHub (pinned to 88fd0f6a0e)