{"record":{"id":"7124ab4088444dd7","repo":"apache/cassandra","slug":"only-superusers-can-remove-identity-bindings-from","errorCode":null,"errorMessage":"Only superusers can remove identity bindings from a role with superuser status","messagePattern":"Only superusers can remove identity bindings from a role with superuser status","errorType":"validation","errorClass":"UnauthorizedException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/DropIdentityStatement.java","lineNumber":70,"sourceCode":"        String roleForIdentity = DatabaseDescriptor.getRoleManager().roleForIdentity(identity);\n\n        if (roleForIdentity == null)\n        {\n            checkPermission(state, Permission.DROP, RoleResource.root());\n        }\n        else\n        {\n            // Check permission for the target role, i.e. we were granted permission to DROP ROLE\n            // for the target identity, this should allow us to drop the identity to role mapping\n            checkPermission(state, Permission.DROP, RoleResource.role(roleForIdentity));\n\n            if (!state.getUser().isSuper())\n            {\n                // If the current user is a regular user and the target role is an admin role\n                // we disallow the operation. Only a superuser can remove an identity bound to\n                // a role with superuser status\n                if (Roles.hasSuperuserStatus(RoleResource.role(roleForIdentity)))\n                    throw new UnauthorizedException(\"Only superusers can remove identity bindings from a role with superuser status\");\n            }\n        }\n    }\n\n    @Override\n    public void validate(ClientState state)\n    {\n        state.ensureNotAnonymous();\n\n        if (!ifExists && !DatabaseDescriptor.getRoleManager().isExistingIdentity(identity))\n        {\n            throw new InvalidRequestException(String.format(\"identity '%s' doesn't exist\", identity));\n        }\n    }\n\n    @Override\n    public AuditLogContext getAuditLogContext()\n    {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/DropIdentityStatement.java#L52-L88","documentation":"DropIdentityStatement.authorize prevents non-superusers from detaching an identity (e.g., an mTLS identity/authorization identity) that is bound to a role carrying superuser status, to avoid regular admins weakening superuser authentication. It throws UnauthorizedException when Roles.hasSuperuserStatus on the target role is true and the caller is not a superuser.","triggerScenarios":"A non-superuser executes DROP IDENTITY <identity> where the identity is bound (roleForIdentity) to a role whose superuser status is true, as resolved before the check.","commonSituations":"Security teams rotating certificates/identities with an admin account that is not a superuser; automation with scoped credentials attempting identity cleanup; confusion between role-admin permissions and superuser-only identity operations.","solutions":["Perform the DROP IDENTITY as a superuser.","First (as superuser) demote the target role: ALTER ROLE <role> WITH SUPERUSER = false, then remove the identity with the regular admin.","Re-scope the automation to use a superuser credential only for identity-management operations."],"exampleFix":"// before (non-superuser)\nDROP IDENTITY 'CN=svc,OU=sec';\n// after (as superuser)\nDROP IDENTITY 'CN=svc,OU=sec';\n// or, as superuser first:\nALTER ROLE svc_role WITH SUPERUSER = false; -- then non-superuser admin may drop the identity","handlingStrategy":"try-catch","validationCode":"// pre-check (as caller): only attempt identity drops with a superuser connection\nif (!currentUserIsSuperuser(session) && identityBoundToSuperuserRole(identity)) throw new IllegalStateException('requires superuser');","typeGuard":null,"tryCatchPattern":"try { session.execute(dropIdentityCql); } catch (UnauthorizedException e) { if (e.getMessage().contains(\"Only superusers can remove identity bindings\")) { /* escalate to superuser connection or demote target role first */ } else throw e; }","preventionTips":["Route identity-management operations through superuser credentials","Demote a role's SUPERUSER status before removing its identities with a regular admin account","Document identity/role bindings in provisioning automation to avoid surprises"],"tags":["authz","identity","permission-denied"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}