Skip to content

Conversation

@aratno
Copy link
Contributor

@aratno aratno commented Dec 6, 2024

@aratno aratno force-pushed the CASSANDRA-20128-trunk branch 3 times, most recently from 8b8d068 to f8ac711 Compare December 18, 2024 15:30
Copy link
Contributor

@JeetKunDoug JeetKunDoug left a comment

Choose a reason for hiding this comment

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

Some questions/suggestions, but glad to see the audit logging applied to JMX as well. Thanks!

@aratno aratno force-pushed the CASSANDRA-20128-trunk branch from f8ac711 to 86f6015 Compare December 18, 2024 17:58
{
private static String user(Subject subject)
{
return String.format("%s", subject == null ? null : subject.getPrincipals().stream().map(Objects::toString).collect(Collectors.joining(", ")));
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand this is not a hot path, but following the decision on this thread, we may want to stay away from streams in non test code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch - especially given that I wrote myself on that thread "+1 to forbidding Stream usage entirely".

if (args[0] == null)
throw new IllegalArgumentException("Null MBeanServer");
// Corresponds to MBeanServer.invoke
if (methodName.equals("invoke") && args.length == 4)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: "invoke".equals(methodName) for consistency with others?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the only real change here is that we wrap the existing code in a try/catch block so we can propagate the success/failure event . The code is exactly the same as before, so I think it's fine to keep. The only actual behavior change is that we are doing

AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);

before we do the first two checks. I think that's fine

Copy link
Contributor

@frankgh frankgh left a comment

Choose a reason for hiding this comment

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

Looks good overall, I have some general comments. Let me know what you think

import java.lang.reflect.Method;
import javax.security.auth.Subject;

public interface JmxInvocationListener
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add javadocs on public interfaces and methods ?

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// See AuthorizationProxy.invoke
if (("setMBeanServer").equals(method.getName()))
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: remove redundant unnecessary parentheses

Suggested change
if (("setMBeanServer").equals(method.getName()))
if ("setMBeanServer".equals(method.getName()))

default void onInvocation(Subject subject, Method method, Object[] args)
{}

default void onFailure(Subject subject, Method method, Object[] args, String reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

should we pass the cause here instead of the string reason? The idea is so we can add the cause to the log entry during failure , i.e. log(entry, cause);

Copy link
Contributor Author

@aratno aratno Dec 23, 2024

Choose a reason for hiding this comment

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

How do you want failures to be presented in AuditLogEntry? Full stack trace, or just a string reason (or something in the middle, like class: message)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll use the existing org.apache.cassandra.audit.AuditLogManager#log(org.apache.cassandra.audit.AuditLogEntry, java.lang.Exception) entrypoint

Comment on lines 506 to 507
final InvocationHandler handler = new JmxHandler();
final Class<?>[] interfaces = { MBeanServerForwarder.class };
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid using final for variables

Suggested change
final InvocationHandler handler = new JmxHandler();
final Class<?>[] interfaces = { MBeanServerForwarder.class };
InvocationHandler handler = new JmxHandler();
Class<?>[] interfaces = { MBeanServerForwarder.class };

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can do, this was copied from JMXServerUtils

if (args[0] == null)
throw new IllegalArgumentException("Null MBeanServer");
// Corresponds to MBeanServer.invoke
if (methodName.equals("invoke") && args.length == 4)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the only real change here is that we wrap the existing code in a try/catch block so we can propagate the success/failure event . The code is exactly the same as before, so I think it's fine to keep. The only actual behavior change is that we are doing

AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);

before we do the first two checks. I think that's fine

public void testJMXAuditLogs() throws Throwable
{
// Need to use distinct ports, otherwise would get RMI registry object ID collision, even with server shutdown between
testJMXAuditLogs(false, getAutomaticallyAllocatedPort(InetAddress.getLoopbackAddress()));
Copy link
Contributor

Choose a reason for hiding this comment

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

I was going to suggest using SocketUtils.findAvailablePort but it looks like it always requires a fall back port number. Maybe we can change the signature of that method to take an Integer object instead of the primitive, and reuse the same code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the benefit of findAvailablePort? Looks like getAutomaticallyAllocatedPort has more similar usage within test code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the benefit is that the code already exists under the test code, and that we avoid duplication. However since the existing method doesn't fit exactly the requirement, I think it's fine to keep the new method.

LOGIN_SUCCESS(AuditLogEntryCategory.AUTH),
LIST_SUPERUSERS(AuditLogEntryCategory.DCL);
LIST_SUPERUSERS(AuditLogEntryCategory.DCL),
JMX(AuditLogEntryCategory.JMX);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking we should split this into JMX_SUCCESS and JMX_ERROR. I can see use cases where you might only be interested in audit logs for failed JMX operations. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd rather start with a basic on / off flag for now, and we can make this more refined once it gets used. There's room for more specific inclusion / exclusion criteria, like excluding "boilerplate" GetClassLoader calls made by the JMX client, etc.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's reasonable. We can enhance it later as needed.

Copy link
Contributor

@frankgh frankgh left a comment

Choose a reason for hiding this comment

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

+1

Copy link
Contributor

@bbotella bbotella left a comment

Choose a reason for hiding this comment

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

+1! (nb)

@frankgh
Copy link
Contributor

frankgh commented Jan 2, 2025

Closed via c853eff

@frankgh frankgh closed this Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants