/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.audit.request;
import java.util.Set;
import org.apache.ambari.server.api.services.Request;
import org.apache.ambari.server.api.services.Result;
import org.apache.ambari.server.api.services.ResultStatus;
import org.apache.ambari.server.audit.AuditLogger;
import org.apache.ambari.server.audit.event.AuditEvent;
import org.apache.ambari.server.audit.request.eventcreator.RequestAuditEventCreator;
import org.apache.ambari.server.controller.spi.Resource;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* The purpose of this class is to create audit log entries for the HTTP requests
*/
@Singleton
public class RequestAuditLoggerImpl implements RequestAuditLogger {
/**
* Priorities for searching the proper creator
*/
private static final int REQUEST_TYPE_PRIORITY = 1;
private static final int RESULT_STATUS_PRIORITY = 2;
private static final int RESOURCE_TYPE_PRIORITY = 4;
/**
* Container for the {@link RequestAuditEventCreator}
*/
private Set<RequestAuditEventCreator> creators;
/**
* Audit logger that receives {@link AuditEvent}s and does the actual logging
*/
private AuditLogger auditLogger;
/**
* Injecting dependencies through the constructor
* @param auditLogger Audit Logger
* @param creatorSet Set of plugins that are registered for requests
*/
@Inject
public RequestAuditLoggerImpl(AuditLogger auditLogger, Set<RequestAuditEventCreator> creatorSet) {
this.auditLogger = auditLogger;
this.creators = creatorSet;
}
/**
* Finds the proper creator, then creates and logs and {@link AuditEvent}
* @param request
* @param result
*/
@Override
public void log(Request request, Result result) {
if(!auditLogger.isEnabled()) {
return;
}
Resource.Type resourceType = request.getResource().getResourceDefinition().getType();
Request.Type requestType = request.getRequestType();
ResultStatus resultStatus = result.getStatus();
RequestAuditEventCreator creator = selectCreator(resourceType, resultStatus, requestType);
if (creator != null) {
AuditEvent ae = creator.createAuditEvent(request, result);
if (ae != null) {
auditLogger.log(ae);
}
}
}
/**
* Select the proper creator. Priority order: resourceType > resultStatus > requestType
* The most matching creator is returned
* If there is no creator found, then null is returned.
* @param resourceType
* @param requestType
* @param resultStatus
* @return
*/
private RequestAuditEventCreator selectCreator(Resource.Type resourceType, ResultStatus resultStatus, Request.Type requestType) {
RequestAuditEventCreator selected = null;
Integer priority = -1;
for (RequestAuditEventCreator creator : creators) {
Integer creatorPriority = getPriority(creator, resourceType, resultStatus, requestType);
if (creatorPriority != null && priority < creatorPriority) {
priority = creatorPriority;
selected = creator;
}
}
return selected;
}
/**
* Calculates the creator priority for the actual resouce type, result status and request type
* @param creator
* @param resourceType
* @param resultStatus
* @param requestType
* @return
*/
private Integer getPriority(RequestAuditEventCreator creator, Resource.Type resourceType, ResultStatus resultStatus, Request.Type requestType) {
Integer priority = 0;
if (isIncompatible(creator, resourceType, resultStatus, requestType)) {
return null;
}
priority += creator.getRequestTypes() != null && creator.getRequestTypes().contains(requestType) ? REQUEST_TYPE_PRIORITY : 0;
priority += creator.getResultStatuses() != null && creator.getResultStatuses().contains(resultStatus.getStatus()) ? RESULT_STATUS_PRIORITY : 0;
priority += creator.getResourceTypes() != null && creator.getResourceTypes().contains(resourceType) ? RESOURCE_TYPE_PRIORITY : 0;
return priority;
}
/**
* Checks if the creator is a possible candidate for creating audit log event for the request
* @param creator
* @param resourceType
* @param resultStatus
* @param requestType
* @return
*/
private boolean isIncompatible(RequestAuditEventCreator creator, Resource.Type resourceType, ResultStatus resultStatus, Request.Type requestType) {
return creator.getRequestTypes() != null && !creator.getRequestTypes().contains(requestType) ||
creator.getResultStatuses() != null && !creator.getResultStatuses().contains(resultStatus.getStatus()) ||
creator.getResourceTypes() != null && !creator.getResourceTypes().contains(resourceType);
}
}