SOLR-13969: Clean up and document AuditEvent API (#1041)

This commit is contained in:
Jan Høydahl 2019-11-28 09:55:11 +01:00 committed by GitHub
parent cc4f3802ef
commit 9f78482295
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 142 additions and 18 deletions

View File

@ -152,6 +152,8 @@ Improvements
* SOLR-13961: When using partial/atomic updates to remove child documents, we now support setting to null or
an empty list as equivalent to the "remove" command. (Thomas Wöckinger)
* SOLR-13969: Clean up and document AuditEvent API (janhoy)
Optimizations
---------------------
(No changes)

View File

@ -29,6 +29,7 @@ import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.servlet.ServletUtils;
@ -48,7 +49,7 @@ import static org.apache.solr.security.AuditEvent.EventType.ERROR;
*/
public class AuditEvent {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private StringBuffer requestUrl;
private String baseUrl;
private String nodeName;
private String message;
private Level level;
@ -69,10 +70,10 @@ public class AuditEvent {
private EventType eventType;
private AuthorizationResponse autResponse;
private RequestType requestType;
private double QTime = -1;
private double qTime = -1;
private int status = -1;
private Throwable exception;
/* Predefined event types. Custom types can be made through constructor */
public enum EventType {
AUTHENTICATED("Authenticated", "User successfully authenticated", Level.INFO, -1),
@ -134,7 +135,7 @@ public class AuditEvent {
this.httpMethod = httpRequest.getMethod();
this.httpQueryString = httpRequest.getQueryString();
this.headers = getHeadersFromRequest(httpRequest);
this.requestUrl = httpRequest.getRequestURL();
this.baseUrl = httpRequest.getRequestURL().toString();
this.nodeName = MDC.get(ZkStateReader.NODE_NAME_PROP);
SolrRequestParsers.parseQueryString(httpQueryString).forEach(sp -> {
this.solrParams.put(sp.getKey(), Arrays.asList(sp.getValue()));
@ -222,75 +223,135 @@ public class AuditEvent {
}
}
}
/**
* The human readable message about this event
*/
public String getMessage() {
return message;
}
/**
* Level of this event. Can be INFO, WARN or ERROR
* @return {@link Level} enum
*/
public Level getLevel() {
return level;
}
/**
* Date that the event happened
*/
public Date getDate() {
return date;
}
/**
* Username of logged in user, or null if no authenticated user
*/
public String getUsername() {
return username;
}
/**
* Session identifier
*/
public String getSession() {
return session;
}
/**
* IP address of the client doing the request
*/
public String getClientIp() {
return clientIp;
}
/**
* A general purpose context map with potential extra information about the event
*/
public Map<String, Object> getContext() {
return context;
}
/**
* List of collection names involved in request
*/
public List<String> getCollections() {
return collections;
}
/**
* Identifies the resource being operated on. This is not the same as URL path.
* For queries the resource is relative to collection name, e.g. /select or /update.
* For other events the resource may be /api/node/health or /admin/collection
*/
public String getResource() {
return resource;
}
/**
* The HTTP method. E.g. GET, POST, PUT
*/
public String getHttpMethod() {
return httpMethod;
}
/**
* Query part of URL or null if query part
*/
public String getHttpQueryString() {
return httpQueryString;
}
/**
* EventType tells the outcome of the event such as REJECTED, UNAUTHORIZED or ERROR
* @return {@link EventType} enum
*/
public EventType getEventType() {
return eventType;
}
/**
* Host name of the Solr node logging the event
*/
public String getSolrHost() {
return solrHost;
}
/**
* IP address of the Solr node logging the event
*/
public String getSolrIp() {
return solrIp;
}
/**
* Port number of the Solr node logging the event
*/
public int getSolrPort() {
return solrPort;
}
/**
* Map of all HTTP request headers belonging to the request
*/
public Map<String, String> getHeaders() {
return headers;
}
/**
* Map of all Solr request parameters attached to the request. Pulled from url
*/
public Map<String, List<String>> getSolrParams() {
return solrParams;
}
/**
* Gets first value of a certain Solr request parameter
* @param key name of request parameter to retrieve
* @return String value of the first value, regardless of number of valies
*/
public String getSolrParamAsString(String key) {
List<String> v = getSolrParams().get(key);
if (v != null && v.size() > 0) {
@ -298,42 +359,84 @@ public class AuditEvent {
}
return null;
}
/**
* The authorization response object from authorization plugin, or null authz has not happened
*/
public AuthorizationResponse getAutResponse() {
return autResponse;
}
/**
* Node name of Solr node, on the internal format host:port_context, e.g. 10.0.0.1:8983_solr
*/
public String getNodeName() {
return nodeName;
}
/**
* Determines the type of request. Can be ADMIN, SEARCH, UPDATE, STREAMING, UNKNOWN
* @return {@link RequestType} enum
*/
public RequestType getRequestType() {
return requestType;
}
/**
* HTTP status code of event, i.e. 200 = OK, 401 = unauthorized
*/
public int getStatus() {
return status;
}
/**
* Request time in milliseconds for completed requests
*/
public double getQTime() {
return QTime;
return qTime;
}
/**
* In case of ERROR event, find the exception causing the error
*/
public Throwable getException() {
return exception;
}
/**
* Get baseUrl as StringBuffer for back compat with previous version
* @deprecated Please use {@link #getBaseUrl()} instead
* @return StringBuffer of the base url without query part
*/
@Deprecated
@JsonIgnore
public StringBuffer getRequestUrl() {
return requestUrl;
return new StringBuffer(baseUrl);
}
/**
* Full URL of the original request. This is {@link #baseUrl} + "?" + {@link #httpQueryString}.
* Returns null if not set
*/
public String getUrl() {
if (baseUrl == null) return null;
return baseUrl + (httpQueryString != null ? "?" + httpQueryString : "");
}
/**
* First part of URL of the request, but not including request parameters, or null if not set
*/
public String getBaseUrl() {
return baseUrl;
}
// Setters, builder style
public AuditEvent setRequestUrl(StringBuffer requestUrl) {
this.requestUrl = requestUrl;
public AuditEvent setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
return this;
}
public AuditEvent setSession(String session) {
this.session = session;
return this;
@ -429,8 +532,8 @@ public class AuditEvent {
return this;
}
public AuditEvent setQTime(double QTime) {
this.QTime = QTime;
public AuditEvent setQTime(double qTime) {
this.qTime = qTime;
return this;
}

View File

@ -38,6 +38,13 @@ public class AuditLoggerPluginTest extends SolrTestCaseJ4 {
.setMessage("Anonymous")
.setResource("/collection1")
.setDate(SAMPLE_DATE);
protected static final AuditEvent EVENT_WITH_URL = new AuditEvent(AuditEvent.EventType.ANONYMOUS)
.setHttpMethod("GET")
.setMessage("Anonymous")
.setResource("/collection1")
.setBaseUrl("http://myserver/mypath")
.setHttpQueryString("a=b&c=d")
.setDate(SAMPLE_DATE);
protected static final AuditEvent EVENT_ANONYMOUS_REJECTED = new AuditEvent(AuditEvent.EventType.ANONYMOUS_REJECTED)
.setHttpMethod("GET")
.setMessage("Anonymous rejected")
@ -194,6 +201,18 @@ public class AuditLoggerPluginTest extends SolrTestCaseJ4 {
plugin.formatter.formatEvent(EVENT_ANONYMOUS));
assertEquals("{\"message\":\"Authenticated\",\"level\":\"INFO\",\"date\":" + SAMPLE_DATE.getTime() + ",\"username\":\"Jan\",\"solrParams\":{},\"solrPort\":0,\"resource\":\"/collection1\",\"httpMethod\":\"GET\",\"eventType\":\"AUTHENTICATED\",\"status\":-1,\"qtime\":-1.0}",
plugin.formatter.formatEvent(EVENT_AUTHENTICATED));
}
}
@Test
public void getBaseUrl() {
assertEquals("http://myserver/mypath", EVENT_WITH_URL.getBaseUrl());
// Deprecated
assertEquals("http://myserver/mypath", EVENT_WITH_URL.getRequestUrl().toString());
}
@Test
public void getUrl() {
assertEquals("http://myserver/mypath?a=b&c=d",
EVENT_WITH_URL.getUrl());
}
}