Skip to content

Commit

Permalink
Add logging implementation for AuditManager and audit more endpoints (a…
Browse files Browse the repository at this point in the history
…pache#15480)

Changes
- Add `log` implementation for `AuditManager` alongwith `SQLAuditManager`
- `LoggingAuditManager` simply logs the audit event. Thus, it returns empty for
all `fetchAuditHistory` calls.
- Add new config `druid.audit.manager.type` which can take values `log`, `sql` (default)
- Add new config `druid.audit.manager.logLevel` which can take values `DEBUG`, `INFO`, `WARN`.
This gets activated only if `type` is `log`.
- Remove usage of `ConfigSerde` from `AuditManager` as audit is not just limited to configs
- Add `AuditSerdeHelper` for a single implementation of serialization/deserialization of
audit payload and other utility methods.
  • Loading branch information
kfaraz authored Dec 19, 2023
1 parent e373f62 commit 9f56885
Show file tree
Hide file tree
Showing 54 changed files with 1,830 additions and 1,295 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
import com.fasterxml.jackson.jaxrs.smile.SmileMediaTypes;
import com.google.inject.Inject;
import com.sun.jersey.spi.container.ResourceFilters;
import org.apache.druid.audit.AuditEntry;
import org.apache.druid.audit.AuditManager;
import org.apache.druid.guice.LazySingleton;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.security.basic.BasicSecurityResourceFilter;
import org.apache.druid.security.basic.authentication.entity.BasicAuthenticatorCredentialUpdate;
import org.apache.druid.server.security.AuthValidator;
import org.apache.druid.server.security.AuthorizationUtils;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
Expand All @@ -45,15 +49,18 @@ public class BasicAuthenticatorResource
{
private final BasicAuthenticatorResourceHandler handler;
private final AuthValidator authValidator;
private final AuditManager auditManager;

@Inject
public BasicAuthenticatorResource(
BasicAuthenticatorResourceHandler handler,
AuthValidator authValidator
AuthValidator authValidator,
AuditManager auditManager
)
{
this.handler = handler;
this.authValidator = authValidator;
this.auditManager = auditManager;
}

/**
Expand Down Expand Up @@ -151,7 +158,11 @@ public Response createUser(
)
{
authValidator.validateAuthenticatorName(authenticatorName);
return handler.createUser(authenticatorName, userName);

final Response response = handler.createUser(authenticatorName, userName);
performAuditIfSuccess(authenticatorName, req, response, "Create user[%s]", userName);

return response;
}

/**
Expand All @@ -174,7 +185,10 @@ public Response deleteUser(
)
{
authValidator.validateAuthenticatorName(authenticatorName);
return handler.deleteUser(authenticatorName, userName);
final Response response = handler.deleteUser(authenticatorName, userName);
performAuditIfSuccess(authenticatorName, req, response, "Delete user[%s]", userName);

return response;
}

/**
Expand All @@ -198,7 +212,10 @@ public Response updateUserCredentials(
)
{
authValidator.validateAuthenticatorName(authenticatorName);
return handler.updateUserCredentials(authenticatorName, userName, update);
final Response response = handler.updateUserCredentials(authenticatorName, userName, update);
performAuditIfSuccess(authenticatorName, req, response, "Update credentials for user[%s]", userName);

return response;
}

/**
Expand Down Expand Up @@ -237,4 +254,35 @@ public Response authenticatorUpdateListener(
authValidator.validateAuthenticatorName(authenticatorName);
return handler.authenticatorUserUpdateListener(authenticatorName, serializedUserMap);
}

private boolean isSuccess(Response response)
{
if (response == null) {
return false;
}

int responseCode = response.getStatus();
return responseCode >= 200 && responseCode < 300;
}

private void performAuditIfSuccess(
String authenticatorName,
HttpServletRequest request,
Response response,
String payloadFormat,
Object... payloadArgs
)
{
if (isSuccess(response)) {
auditManager.doAudit(
AuditEntry.builder()
.key(authenticatorName)
.type("basic.authenticator")
.auditInfo(AuthorizationUtils.buildAuditInfo(request))
.request(AuthorizationUtils.buildRequestInfo("coordinator", request))
.payload(StringUtils.format(payloadFormat, payloadArgs))
.build()
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
import com.fasterxml.jackson.jaxrs.smile.SmileMediaTypes;
import com.google.inject.Inject;
import com.sun.jersey.spi.container.ResourceFilters;
import org.apache.druid.audit.AuditEntry;
import org.apache.druid.audit.AuditManager;
import org.apache.druid.guice.LazySingleton;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.security.basic.BasicSecurityResourceFilter;
import org.apache.druid.security.basic.authorization.entity.BasicAuthorizerGroupMapping;
import org.apache.druid.server.security.AuthValidator;
import org.apache.druid.server.security.AuthorizationUtils;
import org.apache.druid.server.security.ResourceAction;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -48,15 +52,18 @@ public class BasicAuthorizerResource
{
private final BasicAuthorizerResourceHandler resourceHandler;
private final AuthValidator authValidator;
private final AuditManager auditManager;

@Inject
public BasicAuthorizerResource(
BasicAuthorizerResourceHandler resourceHandler,
AuthValidator authValidator
AuthValidator authValidator,
AuditManager auditManager
)
{
this.resourceHandler = resourceHandler;
this.authValidator = authValidator;
this.auditManager = auditManager;
}

/**
Expand Down Expand Up @@ -198,7 +205,11 @@ public Response createUser(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.createUser(authorizerName, userName);

final Response response = resourceHandler.createUser(authorizerName, userName);
performAuditIfSuccess(authorizerName, req, response, "Create user[%s]", userName);

return response;
}

/**
Expand All @@ -221,7 +232,11 @@ public Response deleteUser(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.deleteUser(authorizerName, userName);

final Response response = resourceHandler.deleteUser(authorizerName, userName);
performAuditIfSuccess(authorizerName, req, response, "Delete user[%s]", userName);

return response;
}

/**
Expand All @@ -245,10 +260,21 @@ public Response createGroupMapping(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.createGroupMapping(
final Response response = resourceHandler.createGroupMapping(
authorizerName,
new BasicAuthorizerGroupMapping(groupMappingName, groupMapping.getGroupPattern(), groupMapping.getRoles())
);
performAuditIfSuccess(
authorizerName,
req,
response,
"Create groupMapping[%s] with pattern[%s], roles[%s]",
groupMappingName,
groupMapping.getGroupPattern(),
groupMapping.getRoles()
);

return response;
}

/**
Expand All @@ -271,7 +297,11 @@ public Response deleteGroupMapping(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.deleteGroupMapping(authorizerName, groupMappingName);

final Response response = resourceHandler.deleteGroupMapping(authorizerName, groupMappingName);
performAuditIfSuccess(authorizerName, req, response, "Delete groupMapping[%s]", groupMappingName);

return response;
}

/**
Expand Down Expand Up @@ -338,7 +368,11 @@ public Response createRole(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.createRole(authorizerName, roleName);

final Response response = resourceHandler.createRole(authorizerName, roleName);
performAuditIfSuccess(authorizerName, req, response, "Create role[%s]", roleName);

return response;
}

/**
Expand All @@ -361,7 +395,11 @@ public Response deleteRole(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.deleteRole(authorizerName, roleName);

final Response response = resourceHandler.deleteRole(authorizerName, roleName);
performAuditIfSuccess(authorizerName, req, response, "Delete role[%s]", roleName);

return response;
}

/**
Expand All @@ -386,7 +424,11 @@ public Response assignRoleToUser(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.assignRoleToUser(authorizerName, userName, roleName);

final Response response = resourceHandler.assignRoleToUser(authorizerName, userName, roleName);
performAuditIfSuccess(authorizerName, req, response, "Assign role[%s] to user[%s]", roleName, userName);

return response;
}

/**
Expand All @@ -411,7 +453,11 @@ public Response unassignRoleFromUser(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.unassignRoleFromUser(authorizerName, userName, roleName);

final Response response = resourceHandler.unassignRoleFromUser(authorizerName, userName, roleName);
performAuditIfSuccess(authorizerName, req, response, "Unassign role[%s] from user[%s]", roleName, userName);

return response;
}

/**
Expand All @@ -436,7 +482,12 @@ public Response assignRoleToGroupMapping(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.assignRoleToGroupMapping(authorizerName, groupMappingName, roleName);
final Response response = resourceHandler.assignRoleToGroupMapping(authorizerName, groupMappingName, roleName);

String msgFormat = "Assign role[%s] to groupMapping[%s]";
performAuditIfSuccess(authorizerName, req, response, msgFormat, roleName, groupMappingName);

return response;
}

/**
Expand All @@ -461,7 +512,12 @@ public Response unassignRoleFromGroupMapping(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.unassignRoleFromGroupMapping(authorizerName, groupMappingName, roleName);

final Response response = resourceHandler.unassignRoleFromGroupMapping(authorizerName, groupMappingName, roleName);
String msgFormat = "Unassign role[%s] from groupMapping[%s]";
performAuditIfSuccess(authorizerName, req, response, msgFormat, roleName, groupMappingName);

return response;
}

/**
Expand All @@ -486,7 +542,11 @@ public Response setRolePermissions(
)
{
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.setRolePermissions(authorizerName, roleName, permissions);

final Response response = resourceHandler.setRolePermissions(authorizerName, roleName, permissions);
performAuditIfSuccess(authorizerName, req, response, "Set permissions[%s] for role[%s]", permissions, roleName);

return response;
}

/**
Expand Down Expand Up @@ -607,4 +667,35 @@ public Response authorizerGroupMappingUpdateListener(
authValidator.validateAuthorizerName(authorizerName);
return resourceHandler.authorizerGroupMappingUpdateListener(authorizerName, serializedGroupMappingAndRoleMap);
}

private boolean isSuccess(Response response)
{
if (response == null) {
return false;
}

int responseCode = response.getStatus();
return responseCode >= 200 && responseCode < 300;
}

private void performAuditIfSuccess(
String authorizerName,
HttpServletRequest request,
Response response,
String msgFormat,
Object... args
)
{
if (isSuccess(response)) {
auditManager.doAudit(
AuditEntry.builder()
.key(authorizerName)
.type("basic.authorizer")
.auditInfo(AuthorizationUtils.buildAuditInfo(request))
.request(AuthorizationUtils.buildRequestInfo("coordinator", request))
.payload(StringUtils.format(msgFormat, args))
.build()
);
}
}
}
Loading

0 comments on commit 9f56885

Please sign in to comment.