فهرست منبع

AMBARI-15241. Basic Operational Audit Logging. (Daniel Gergely via stoader)

Toader, Sebastian 9 سال پیش
والد
کامیت
46a34ccdee
100فایلهای تغییر یافته به همراه10323 افزوده شده و 31 حذف شده
  1. 6 1
      ambari-project/pom.xml
  2. 14 0
      ambari-server/conf/unix/log4j.properties
  3. 14 0
      ambari-server/conf/windows/log4j.properties
  4. 5 1
      ambari-server/pom.xml
  5. 14 0
      ambari-server/src/main/conf/log4j.properties
  6. 125 0
      ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
  7. 15 1
      ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java
  8. 23 1
      ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
  9. 26 2
      ambari-server/src/main/java/org/apache/ambari/server/api/services/LogoutService.java
  10. 19 13
      ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java
  11. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/AsyncAuditLogger.java
  12. 39 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLogger.java
  13. 77 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLoggerDefaultImpl.java
  14. 94 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLoggerModule.java
  15. 148 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/AbstractAuditEvent.java
  16. 92 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/AbstractUserAuditEvent.java
  17. 97 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/AccessUnauthorizedAuditEvent.java
  18. 56 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/AuditEvent.java
  19. 126 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/LoginAuditEvent.java
  20. 67 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/LogoutAuditEvent.java
  21. 108 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/OperationStatusAuditEvent.java
  22. 148 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/TaskStatusAuditEvent.java
  23. 87 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/AbstractKerberosAuditEvent.java
  24. 118 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/ChangeSecurityStateKerberosAuditEvent.java
  25. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/CreateKeyTabKerberosAuditEvent.java
  26. 73 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/CreatePrincipalKerberosAuditEvent.java
  27. 80 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/DestroyPrincipalKerberosAuditEvent.java
  28. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ActivateUserRequestAuditEvent.java
  29. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddAlertGroupRequestAuditEvent.java
  30. 167 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddAlertTargetRequestAuditEvent.java
  31. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddBlueprintRequestAuditEvent.java
  32. 98 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddComponentToHostRequestAuditEvent.java
  33. 122 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddCredentialRequestAuditEvent.java
  34. 86 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddHostRequestAuditEvent.java
  35. 134 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRepositoryRequestAuditEvent.java
  36. 153 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRepositoryVersionRequestAuditEvent.java
  37. 98 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRequestRequestAuditEvent.java
  38. 111 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java
  39. 98 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUserToGroupRequestAuditEvent.java
  40. 134 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddViewInstanceRequestAuditEvent.java
  41. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AdminUserRequestAuditEvent.java
  42. 72 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/BlueprintExportRequestAuditEvent.java
  43. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeAlertGroupRequestAuditEvent.java
  44. 134 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeAlertTargetRequestAuditEvent.java
  45. 153 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeRepositoryVersionRequestAuditEvent.java
  46. 134 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeViewInstanceRequestAuditEvent.java
  47. 100 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClientConfigDownloadRequestAuditEvent.java
  48. 91 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClusterNameChangeRequestAuditEvent.java
  49. 126 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClusterPrivilegeChangeRequestAuditEvent.java
  50. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ConfigurationChangeRequestAuditEvent.java
  51. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/CreateGroupRequestAuditEvent.java
  52. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/CreateUserRequestAuditEvent.java
  53. 86 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteAlertGroupRequestAuditEvent.java
  54. 86 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteAlertTargetRequestAuditEvent.java
  55. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteBlueprintRequestAuditEvent.java
  56. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteGroupRequestAuditEvent.java
  57. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteHostRequestAuditEvent.java
  58. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteRepositoryVersionRequestAuditEvent.java
  59. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteServiceRequestAuditEvent.java
  60. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteUserRequestAuditEvent.java
  61. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteViewInstanceRequestAuditEvent.java
  62. 108 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/MembershipChangeRequestAuditEvent.java
  63. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/PrivilegeChangeRequestAuditEvent.java
  64. 98 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/RemoveUserFromGroupRequestAuditEvent.java
  65. 126 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/StartOperationRequestAuditEvent.java
  66. 134 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UpdateRepositoryRequestAuditEvent.java
  67. 111 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UpdateUpgradeItemRequestAuditEvent.java
  68. 88 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UserPasswordChangeRequestAuditEvent.java
  69. 163 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ViewPrivilegeChangeRequestAuditEvent.java
  70. 161 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditEvent.java
  71. 59 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditEventCreator.java
  72. 36 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditLogger.java
  73. 150 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditLoggerImpl.java
  74. 170 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/AlertGroupEventCreator.java
  75. 164 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/AlertTargetEventCreator.java
  76. 109 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/BlueprintEventCreator.java
  77. 94 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/BlueprintExportEventCreator.java
  78. 188 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ComponentEventCreator.java
  79. 150 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ConfigurationChangeEventCreator.java
  80. 111 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/CredentialEventCreator.java
  81. 89 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/DefaultEventCreator.java
  82. 124 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/GroupEventCreator.java
  83. 167 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java
  84. 175 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/MemberEventCreator.java
  85. 147 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/PrivilegeEventCreator.java
  86. 81 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RecommendationIgnoreEventCreator.java
  87. 132 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryEventCreator.java
  88. 215 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryVersionEventCreator.java
  89. 101 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RequestEventCreator.java
  90. 92 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceConfigDownloadEventCreator.java
  91. 179 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceEventCreator.java
  92. 86 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UnauthorizedEventCreator.java
  93. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
  94. 110 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeItemEventCreator.java
  95. 211 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UserEventCreator.java
  96. 81 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ValidationIgnoreEventCreator.java
  97. 149 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewInstanceEventCreator.java
  98. 145 0
      ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewPrivilegeEventCreator.java
  99. 24 0
      ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
  100. 29 12
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java

+ 6 - 1
ambari-project/pom.xml

@@ -407,7 +407,7 @@
       <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
-        <version>1.2.16</version>
+        <version>1.2.17</version>
         <exclusions>
           <exclusion>
             <groupId>com.sun.jdmk</groupId>
@@ -431,6 +431,11 @@
           </exclusion>
         </exclusions>
       </dependency>
+      <dependency>
+        <groupId>log4j</groupId>
+        <artifactId>apache-log4j-extras</artifactId>
+        <version>1.2.17</version>
+      </dependency>
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>

+ 14 - 0
ambari-server/conf/unix/log4j.properties

@@ -24,6 +24,7 @@ ambari.log.file=ambari-server.log
 ambari.config-changes.file=ambari-config-changes.log
 ambari.alerts.file=ambari-alerts.log
 ambari.eclipselink.file=ambari-eclipselink.log
+ambari.audit.file=ambari-audit.log
 ambari.dbcheck.file=ambari-server-check-database.log
 
 log4j.rootLogger=INFO,file
@@ -70,6 +71,19 @@ log4j.appender.eclipselink.MaxBackupIndex=10
 log4j.appender.eclipselink.layout=org.apache.log4j.PatternLayout
 log4j.appender.eclipselink.layout.ConversionPattern=%m%n
 
+# Audit logging
+log4j.logger.audit=INFO,audit
+log4j.additivity.audit=false
+log4j.appender.audit=org.apache.log4j.rolling.RollingFileAppender
+log4j.appender.audit.rollingPolicy=org.apache.log4j.rolling.FixedWindowRollingPolicy
+log4j.appender.audit.rollingPolicy.ActiveFileName=${ambari.log.dir}/${ambari.audit.file}
+log4j.appender.audit.rollingPolicy.FileNamePattern=${ambari.log.dir}/${ambari.audit.file}-%i.log.gz
+log4j.appender.audit.rollingPolicy.maxIndex=13
+log4j.appender.audit.triggeringPolicy=org.apache.log4j.rolling.SizeBasedTriggeringPolicy
+log4j.appender.audit.triggeringPolicy.maxFileSize=50000000
+log4j.appender.audit.layout=org.apache.log4j.PatternLayout
+log4j.appender.audit.layout.ConversionPattern=%m%n
+
 log4j.logger.org.apache.hadoop.yarn.client=WARN
 log4j.logger.org.apache.slider.common.tools.SliderUtils=WARN
 log4j.logger.org.apache.ambari.server.security.authorization=WARN

+ 14 - 0
ambari-server/conf/windows/log4j.properties

@@ -23,6 +23,7 @@ ambari.log.file=ambari-server.log
 ambari.config-changes.file=ambari-config-changes.log
 ambari.alerts.file=ambari-alerts.log
 ambari.eclipselink.file=ambari-eclipselink.log
+ambari.audit.file=ambari-audit.log
 ambari.dbcheck.file=ambari-server-check-database.log
 
 # Define the root logger to the system property "ambari.root.logger".
@@ -94,3 +95,16 @@ log4j.appender.eclipselink.MaxFileSize=50MB
 log4j.appender.eclipselink.MaxBackupIndex=10
 log4j.appender.eclipselink.layout=org.apache.log4j.PatternLayout
 log4j.appender.eclipselink.layout.ConversionPattern=%m%n
+
+# Audit logging
+log4j.logger.audit=INFO,audit
+log4j.additivity.audit=false
+log4j.appender.audit=org.apache.log4j.rolling.RollingFileAppender
+log4j.appender.audit.rollingPolicy=org.apache.log4j.rolling.FixedWindowRollingPolicy
+log4j.appender.audit.rollingPolicy.ActiveFileName=${ambari.log.dir}\${ambari.audit.file}
+log4j.appender.audit.rollingPolicy.FileNamePattern=${ambari.log.dir}\${ambari.audit.file}-%i.log.gz
+log4j.appender.audit.rollingPolicy.maxIndex=13
+log4j.appender.audit.triggeringPolicy=org.apache.log4j.rolling.SizeBasedTriggeringPolicy
+log4j.appender.audit.triggeringPolicy.maxFileSize=50000000
+log4j.appender.audit.layout=org.apache.log4j.PatternLayout
+log4j.appender.audit.layout.ConversionPattern=%m%n

+ 5 - 1
ambari-server/pom.xml

@@ -1057,6 +1057,10 @@
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
     </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>apache-log4j-extras</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.eclipse.persistence</groupId>
       <artifactId>eclipselink</artifactId>
@@ -1277,7 +1281,7 @@
           <groupId>c3p0</groupId>
           <artifactId>c3p0</artifactId>
         </exclusion>
-      </exclusions>      
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.quartz-scheduler</groupId>

+ 14 - 0
ambari-server/src/main/conf/log4j.properties

@@ -23,6 +23,7 @@ ambari.log.file=ambari-server.log
 ambari.config-changes.file=ambari-config-changes.log
 ambari.alerts.file=ambari-alerts.log
 ambari.eclipselink.file=ambari-eclipselink.log
+ambari.audit.file=ambari-audit.log
 ambari.dbcheck.file=ambari-server-check-database.log
 
 # Define the root logger to the system property "ambari.root.logger".
@@ -95,3 +96,16 @@ log4j.appender.eclipselink.MaxBackupIndex=10
 log4j.appender.eclipselink.layout=org.apache.log4j.PatternLayout
 log4j.appender.eclipselink.layout.ConversionPattern=%m%n
 
+# Audit logging
+log4j.logger.audit=INFO,audit
+log4j.additivity.audit=false
+log4j.appender.audit=org.apache.log4j.rolling.RollingFileAppender
+log4j.appender.audit.rollingPolicy=org.apache.log4j.rolling.FixedWindowRollingPolicy
+log4j.appender.audit.rollingPolicy.ActiveFileName=${ambari.log.dir}/${ambari.audit.file}
+log4j.appender.audit.rollingPolicy.FileNamePattern=${ambari.log.dir}/${ambari.audit.file}-%i.log.gz
+log4j.appender.audit.rollingPolicy.maxIndex=13
+log4j.appender.audit.triggeringPolicy=org.apache.log4j.rolling.SizeBasedTriggeringPolicy
+log4j.appender.audit.triggeringPolicy.maxFileSize=50000000
+log4j.appender.audit.layout=org.apache.log4j.PatternLayout
+log4j.appender.audit.layout.ConversionPattern=%m%n
+

+ 125 - 0
ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java

@@ -23,8 +23,13 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.ambari.annotations.Experimental;
@@ -35,7 +40,13 @@ import org.apache.ambari.annotations.TransactionalLock.LockType;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.agent.CommandReport;
 import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.audit.event.AuditEvent;
+import org.apache.ambari.server.audit.AuditLogger;
+import org.apache.ambari.server.audit.event.OperationStatusAuditEvent;
+import org.apache.ambari.server.audit.event.TaskStatusAuditEvent;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.internal.CalculatedStatus;
 import org.apache.ambari.server.events.HostRemovedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
@@ -117,6 +128,22 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
   @Inject
   Configuration configuration;
 
+  @Inject
+  AuditLogger auditLogger;
+
+  /**
+   * Caches to store current request and task statuses.
+   * It is used for avoiding audit log entry duplication
+   */
+  private Map<Long, HostRoleStatus> temporaryStatusCache = new HashMap<Long, HostRoleStatus>();
+  private Map<Long, HostRoleStatus> temporaryTaskStatusCache = new HashMap<Long, HostRoleStatus>();
+
+  /**
+   * Stores the host role command entities that are not completed for a request id
+   * It is used to calculate the summary state of the request for audit logging
+   */
+  private Map<Long, Map<Long, HostRoleStatus>> tasksForRequest = new HashMap<>();
+
   private Cache<Long, HostRoleCommand> hostRoleCommandCache;
   private long cacheLimit; //may be exceeded to store tasks from one request
 
@@ -198,6 +225,8 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
             + " requestId " + command.getRequestId()
             + " taskId " + command.getTaskId()
             + " stageId " + command.getStageId());
+
+        auditLog(command, requestId);
       }
     }
 
@@ -219,6 +248,8 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     for (HostRoleCommandEntity command : commands) {
       command.setStatus(command.isRetryAllowed() ? HostRoleStatus.HOLDING_TIMEDOUT : HostRoleStatus.TIMEDOUT);
       command.setEndTime(now);
+
+      auditLog(command, requestId);
     }
 
     // no need to merge if there's nothing to merge
@@ -448,6 +479,8 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     for (HostRoleCommandEntity commandEntity : commandEntities) {
       CommandReport report = taskReports.get(commandEntity.getTaskId());
 
+      boolean statusChanged = false;
+
       switch (commandEntity.getStatus()) {
         case ABORTED:
           // We don't want to overwrite statuses for ABORTED tasks with
@@ -467,6 +500,7 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
           }
 
           commandEntity.setStatus(status);
+          statusChanged = true;
           break;
       }
 
@@ -485,6 +519,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
         long stageId = requestStageIds[1];
         if (requestDAO.getLastStageId(requestId).equals(stageId)) {
           requestsToCheck.add(requestId);
+          if(statusChanged) {
+            auditLog(commandEntity, requestId); // wrong requestId !!!
+          }
         }
       }
     }
@@ -542,6 +579,8 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
         }
       }
       command.setExitcode(report.getExitCode());
+
+      auditLog(command, requestId);
     }
 
     // no need to merge if there's nothing to merge
@@ -607,6 +646,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
       entity.setLastAttemptTime(hostRoleCommand.getLastAttemptTime());
       entity.setStatus(hostRoleCommand.getStatus());
       entity.setAttemptCount(hostRoleCommand.getAttemptCount());
+
+      auditLog(entity, s.getRequestId());
+
       hostRoleCommandDAO.merge(entity);
     } else {
       throw new RuntimeException("HostRoleCommand is not persisted, cannot update:\n" + hostRoleCommand);
@@ -745,6 +787,8 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
       // Because it expects -1, RetryActionMonitor.java also had to set it to -1.
       task.setStartTime(-1L);
       task.setEndTime(-1L);
+
+      auditLog(task, task.getRequestId());
     }
 
     // no need to merge if there's nothing to merge
@@ -764,4 +808,85 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
     LOG.info("Invalidating HRC cache after receiveing {}", event);
     hostRoleCommandCache.invalidateAll();
   }
+
+  /**
+   * AuditLog operation status change
+   * @param requestId
+   */
+  private void auditLog(HostRoleCommandEntity commandEntity, Long requestId) {
+    if(!auditLogger.isEnabled()) {
+      return;
+    }
+
+    if(requestId != null) {
+
+      HostRoleStatus calculatedStatus = calculateStatus(commandEntity, requestId);
+
+      if (!temporaryStatusCache.containsKey(requestId) || temporaryStatusCache.get(requestId) != calculatedStatus) {
+        RequestEntity request = requestDAO.findByPK(requestId);
+        String context = request != null ? request.getRequestContext() : null;
+        AuditEvent auditEvent = OperationStatusAuditEvent.builder()
+          .withRequestId(String.valueOf(requestId))
+          .withStatus(String.valueOf(calculatedStatus))
+          .withRequestContext(context)
+          .withTimestamp(System.currentTimeMillis())
+          .build();
+        auditLogger.log(auditEvent);
+
+        temporaryStatusCache.put(requestId, calculatedStatus);
+      }
+    }
+    logTask(commandEntity, requestId);
+  }
+
+  /**
+   * Calculates summary status for the given request id for the new command entity status
+   * @param commandEntity
+   * @param requestId
+   * @return
+   */
+  private HostRoleStatus calculateStatus(HostRoleCommandEntity commandEntity, Long requestId) {
+    if(!tasksForRequest.containsKey(requestId)) {
+      tasksForRequest.put(requestId, new HashMap<Long, HostRoleStatus>());
+    }
+
+    tasksForRequest.get(requestId).put(commandEntity.getTaskId(), commandEntity.getStatus());
+
+    HostRoleStatus calculatedStatus = CalculatedStatus.calculateSummaryStatusOfStage(CalculatedStatus.calculateStatusCounts(tasksForRequest.get(requestId).values()), tasksForRequest.get(requestId).size(), false);
+
+    // if all task status is completed, we can remove it from the container
+    boolean hasInProgress = false;
+    for(HostRoleStatus hrcs : tasksForRequest.get(requestId).values()) {
+      if(!hrcs.isCompletedState()) {
+        hasInProgress = true;
+        break;
+      }
+    }
+    if(!hasInProgress) {
+      tasksForRequest.remove(requestId);
+    }
+    return calculatedStatus;
+  }
+
+  /**
+   * Logs task status change
+   * @param commandEntity
+   * @param requestId
+   */
+  private void logTask(HostRoleCommandEntity commandEntity, Long requestId) {
+    if(!temporaryTaskStatusCache.containsKey(commandEntity.getTaskId()) || temporaryTaskStatusCache.get(commandEntity.getTaskId()) != commandEntity.getStatus() ) {
+      AuditEvent taskEvent = TaskStatusAuditEvent.builder()
+        .withTaskId(String.valueOf(commandEntity.getTaskId()))
+        .withHostName(commandEntity.getHostName())
+        .withOperation(commandEntity.getRoleCommand().toString() + " " + commandEntity.getRole().toString())
+        .withDetails(commandEntity.getCommandDetail())
+        .withStatus(commandEntity.getStatus().toString())
+        .withRequestId(String.valueOf(requestId))
+        .withTimestamp(System.currentTimeMillis())
+        .build();
+
+      auditLogger.log(taskEvent);
+      temporaryTaskStatusCache.put(commandEntity.getTaskId(), commandEntity.getStatus());
+    }
+  }
 }

+ 15 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseRequest.java

@@ -18,7 +18,6 @@
 
 package org.apache.ambari.server.api.services;
 
-import com.sun.jersey.spi.container.ContainerRequest;
 import org.apache.ambari.server.api.handlers.RequestHandler;
 import org.apache.ambari.server.api.predicate.InvalidQueryException;
 import org.apache.ambari.server.api.predicate.PredicateCompiler;
@@ -33,8 +32,12 @@ import org.apache.ambari.server.controller.spi.PageRequest;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.SortRequestProperty;
 import org.apache.ambari.server.controller.spi.TemporalInfo;
+import org.apache.ambari.server.utils.RequestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
 import java.io.UnsupportedEncodingException;
@@ -70,6 +73,11 @@ public abstract class BaseRequest implements Request {
    */
   private RequestBody m_body;
 
+  /**
+   * Remote address
+   */
+  private String m_remoteAddress;
+
   /**
    * Query Predicate
    */
@@ -121,6 +129,7 @@ public abstract class BaseRequest implements Request {
     m_uriInfo     = uriInfo;
     m_resource    = resource;
     m_body        = body;
+    m_remoteAddress  = RequestUtils.getRemoteAddress();
   }
 
   @Override
@@ -375,4 +384,9 @@ public abstract class BaseRequest implements Request {
    * @return  the request handler
    */
   protected abstract RequestHandler getRequestHandler();
+
+  @Override
+  public String getRemoteAddress() {
+    return m_remoteAddress;
+  }
 }

+ 23 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java

@@ -27,6 +27,7 @@ import org.apache.ambari.server.api.services.parsers.RequestBodyParser;
 import org.apache.ambari.server.api.services.serializers.CsvSerializer;
 import org.apache.ambari.server.api.services.serializers.JsonSerializer;
 import org.apache.ambari.server.api.services.serializers.ResultSerializer;
+import org.apache.ambari.server.audit.request.RequestAuditLogger;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.utils.RetryHelper;
 import org.eclipse.jetty.util.ajax.JSON;
@@ -39,6 +40,8 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.inject.Inject;
+
 /**
  * Provides common functionality to all services.
  */
@@ -55,6 +58,11 @@ public abstract class BaseService {
    */
   private ResultSerializer m_serializer = new JsonSerializer();
 
+  protected static RequestAuditLogger requestAuditLogger;
+
+  public static void init(RequestAuditLogger instance) {
+    requestAuditLogger = instance;
+  }
 
   /**
    * Requests are funneled through this method so that common logic can be executed.
@@ -92,7 +100,12 @@ public abstract class BaseService {
                                    UriInfo uriInfo, Request.Type requestType,
                                    MediaType mediaType, ResourceInstance resource) {
 
+    // original request and initial result
+    RequestBody rb = new RequestBody();
+    rb.setBody(body);
+    Request request = getRequestFactory().createRequest(headers, rb, uriInfo, requestType, resource);
     Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
+
     try {
       Set<RequestBody> requestBodySet = getBodyParser().parse(body);
 
@@ -100,13 +113,22 @@ public abstract class BaseService {
       while (iterator.hasNext() && result.getStatus().getStatus().equals(ResultStatus.STATUS.OK)) {
         RequestBody requestBody = iterator.next();
 
-        Request request = getRequestFactory().createRequest(
+        request = getRequestFactory().createRequest(
             headers, requestBody, uriInfo, requestType, resource);
 
         result  = request.process();
+        requestAuditLogger.log(request, result);
+      }
+
+      if(requestBodySet.isEmpty() || !ResultStatus.STATUS.OK.equals(result.getStatus().getStatus())) {
+        requestAuditLogger.log(request, result);
       }
     } catch (BodyParseException e) {
       result =  new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
+      requestAuditLogger.log(request, result);
+    } catch (Throwable t) {
+      requestAuditLogger.log(request, new ResultImpl(new ResultStatus(ResultStatus.STATUS.SERVER_ERROR, t.getMessage())));
+      throw t;
     }
 
     ResultSerializer serializer = mediaType == null ? getResultSerializer() : getResultSerializer(mediaType);

+ 26 - 2
ambari-server/src/main/java/org/apache/ambari/server/api/services/LogoutService.java

@@ -17,8 +17,6 @@
  */
 package org.apache.ambari.server.api.services;
 
-import org.springframework.security.core.context.SecurityContextHolder;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -26,18 +24,44 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
+import org.apache.ambari.server.StaticallyInject;
+import org.apache.ambari.server.audit.AuditLogger;
+import org.apache.ambari.server.audit.event.LogoutAuditEvent;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.utils.RequestUtils;
+
+import com.google.inject.Inject;
+import org.springframework.security.core.context.SecurityContextHolder;
+
 /**
  * Service performing logout of current user
  */
+@StaticallyInject
 @Path("/logout")
 public class LogoutService {
 
+  @Inject
+  private static AuditLogger auditLogger;
+
   @GET
   @Produces("text/plain")
   public Response performLogout(@Context HttpServletRequest servletRequest) {
+    auditLog(servletRequest);
     SecurityContextHolder.clearContext();
     servletRequest.getSession().invalidate();
     return Response.status(Response.Status.OK).build();
   }
 
+  /**
+   * Creates and send and audit log event that the user has successfully logged out
+   * @param servletRequest
+   */
+  private void auditLog(HttpServletRequest servletRequest) {
+    LogoutAuditEvent logoutEvent = LogoutAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRemoteIp(RequestUtils.getRemoteAddress(servletRequest))
+      .withUserName(AuthorizationHelper.getAuthenticatedName())
+      .build();
+    auditLogger.log(logoutEvent);
+  }
 }

+ 19 - 13
ambari-server/src/main/java/org/apache/ambari/server/api/services/Request.java

@@ -37,7 +37,7 @@ public interface Request {
   /**
    * Enum of request types.
    */
-  public enum Type {
+  enum Type {
     GET,
     POST,
     PUT,
@@ -50,7 +50,7 @@ public interface Request {
    *
    * @return the result
    */
-  public Result process();
+  Result process();
 
   /**
    * Obtain the resource definition which corresponds to the resource being operated on by the request.
@@ -58,28 +58,28 @@ public interface Request {
    *
    * @return the associated {@link ResourceDefinition}
    */
-  public ResourceInstance getResource();
+  ResourceInstance getResource();
 
   /**
    * Obtain the URI of this request.
    *
    * @return the request uri
    */
-  public String getURI();
+  String getURI();
 
   /**
    * Obtain the http request type.  Type is one of {@link Type}.
    *
    * @return the http request type
    */
-  public Type getRequestType();
+  Type getRequestType();
 
   /**
    * Obtain the api version of the request.  The api version is specified in the request URI.
    *
    * @return the api version of the request
    */
-  public int getAPIVersion();
+  int getAPIVersion();
 
   /**
    * Obtain the query predicate that was built from the user provided predicate fields in the query string.
@@ -88,7 +88,7 @@ public interface Request {
    *
    * @return the user defined predicate
    */
-  public Predicate getQueryPredicate();
+  Predicate getQueryPredicate();
 
   /**
    * Obtain the partial response fields and associated temporal information which were provided
@@ -96,39 +96,45 @@ public interface Request {
    *
    * @return map of partial response propertyId to temporal information
    */
-  public Map<String, TemporalInfo> getFields();
+  Map<String, TemporalInfo> getFields();
 
   /**
    * Obtain the request body data.
    */
-  public RequestBody getBody();
+  RequestBody getBody();
 
   /**
    * Obtain the http headers associated with the request.
    *
    * @return the http headers
    */
-  public Map<String, List<String>> getHttpHeaders();
+  Map<String, List<String>> getHttpHeaders();
 
   /**
    * Obtain the pagination request information.
    *
    * @return the page request
    */
-  public PageRequest getPageRequest();
+  PageRequest getPageRequest();
 
   /**
    * Obtain information to order the results by.
    *
    * @return the order request
    */
-  public SortRequest getSortRequest();
+  SortRequest getSortRequest();
 
   /**
    * Obtain the renderer for the request.
    *
    * @return renderer instance
    */
-  public Renderer getRenderer();
+  Renderer getRenderer();
+
+  /**
+   * Returns the remote address for the request
+   * @return the remote address for the request
+   */
+  String getRemoteAddress();
 
 }

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/AsyncAuditLogger.java

@@ -0,0 +1,101 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
+
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.ambari.server.audit.event.AuditEvent;
+import org.apache.ambari.server.configuration.Configuration;
+
+import com.google.common.eventbus.AsyncEventBus;
+import com.google.common.eventbus.EventBus;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+/**
+ * This is a wrapper for an audit log implementation that uses {@link EventBus} to make audit logging asynchronous
+ */
+@Singleton
+class AsyncAuditLogger implements AuditLogger {
+  /**
+   * Name for guice injection
+   */
+  final static String InnerLogger = "AsyncAuditLogger";
+
+  /**
+   * Event bus that holds audit event objects
+   */
+  private EventBus eventBus;
+
+  /**
+   * Indicates if audit log feature is enabled
+   */
+  private final boolean isEnabled;
+
+  /**
+   * Constructor.
+   *
+   * @param auditLogger the audit logger to use
+   */
+  @Inject
+  public AsyncAuditLogger(@Named(InnerLogger) AuditLogger auditLogger, Configuration configuration) {
+    isEnabled = configuration.isAuditLogEnabled();
+    if(isEnabled) {
+      eventBus = new AsyncEventBus("AuditLoggerEventBus", new ThreadPoolExecutor(0, 1, 5L, TimeUnit.MINUTES,
+        new LinkedBlockingQueue<Runnable>(configuration.getAuditLoggerCapacity()), new AuditLogThreadFactory(),
+        new ThreadPoolExecutor.CallerRunsPolicy()));
+      eventBus.register(auditLogger);
+    }
+  }
+
+  @Override
+  public void log(AuditEvent event) {
+    if(isEnabled) {
+      eventBus.post(event);
+    }
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return isEnabled;
+  }
+
+  /**
+   * A custom {@link ThreadFactory} for the threads that logs audit events
+   */
+  private static final class AuditLogThreadFactory implements ThreadFactory {
+
+    private static final AtomicInteger nextId = new AtomicInteger(1);
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Thread newThread(Runnable runnable) {
+      Thread thread = new Thread(runnable, "auditlog-" + nextId.getAndIncrement());
+      thread.setDaemon(true);
+      return thread;
+    }
+  }
+}

+ 39 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLogger.java

@@ -0,0 +1,39 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
+
+import org.apache.ambari.server.audit.event.AuditEvent;
+
+/**
+ * Interface to handle audit log events
+ */
+public interface AuditLogger {
+
+  /**
+   * Logs audit log events
+   * @param event
+   */
+  void log(final AuditEvent event);
+
+  /**
+   * Returns if the feature is enabled
+   */
+  boolean isEnabled();
+
+}

+ 77 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLoggerDefaultImpl.java

@@ -0,0 +1,77 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.ambari.server.audit.event.AuditEvent;
+import org.apache.ambari.server.configuration.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * Default audit logger implementation, logs messages into log file
+ */
+@Singleton
+public class AuditLoggerDefaultImpl implements AuditLogger {
+
+  private static final Logger LOG = LoggerFactory.getLogger("audit");
+
+  /**
+   * Indicates if audit log feature is enabled
+   */
+  private final boolean isEnabled;
+
+  private ThreadLocal<DateFormat> dateFormatThreadLocal = new ThreadLocal<>();
+
+  @Inject
+  public AuditLoggerDefaultImpl(Configuration configuration) {
+    isEnabled = configuration.isAuditLogEnabled();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @Subscribe
+  public void log(AuditEvent event) {
+    if(!isEnabled) {
+      return;
+    }
+
+    if(dateFormatThreadLocal.get() == null) {
+      //2016-03-11T10:42:36.376Z
+      dateFormatThreadLocal.set(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"));
+    }
+
+    Date date = new Date(event.getTimestamp());
+    LOG.info("{}, {}", dateFormatThreadLocal.get().format(date), event.getAuditMessage());
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return isEnabled;
+  }
+}

+ 94 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/AuditLoggerModule.java

@@ -0,0 +1,94 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
+
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.audit.request.RequestAuditLogger;
+import org.apache.ambari.server.audit.request.RequestAuditLoggerImpl;
+import org.apache.ambari.server.audit.request.eventcreator.AlertGroupEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.AlertTargetEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.BlueprintEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.BlueprintExportEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ComponentEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ConfigurationChangeEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.CredentialEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.DefaultEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.GroupEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.HostEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.MemberEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.PrivilegeEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.RecommendationIgnoreEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.RepositoryEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.RepositoryVersionEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.RequestEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ServiceConfigDownloadEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ServiceEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.UnauthorizedEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.UpgradeEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.UpgradeItemEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.UserEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ValidationIgnoreEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ViewInstanceEventCreator;
+import org.apache.ambari.server.audit.request.eventcreator.ViewPrivilegeEventCreator;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+
+public class AuditLoggerModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    bind(AuditLogger.class).to(AsyncAuditLogger.class);
+
+    // set AuditLoggerDefaultImpl to be used by AsyncAuditLogger
+    bind(AuditLogger.class).annotatedWith(Names.named(AsyncAuditLogger.InnerLogger)).to(AuditLoggerDefaultImpl.class);
+
+    // binding for audit event creators
+    Multibinder<RequestAuditEventCreator> auditLogEventCreatorBinder = Multibinder.newSetBinder(binder(), RequestAuditEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(DefaultEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ComponentEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ServiceEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(UnauthorizedEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ConfigurationChangeEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(UserEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(GroupEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(MemberEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(PrivilegeEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(BlueprintExportEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ServiceConfigDownloadEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(BlueprintEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ViewInstanceEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ViewPrivilegeEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(RepositoryEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(RepositoryVersionEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(AlertGroupEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(AlertTargetEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(HostEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(UpgradeEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(UpgradeItemEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(RecommendationIgnoreEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(ValidationIgnoreEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(CredentialEventCreator.class);
+    auditLogEventCreatorBinder.addBinding().to(RequestEventCreator.class);
+
+    bind(RequestAuditLogger.class).to(RequestAuditLoggerImpl.class);
+
+  }
+}

+ 148 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/AbstractAuditEvent.java

@@ -0,0 +1,148 @@
+/*
+ * 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.event;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * Base class for concrete audit event types.
+ */
+public abstract class AbstractAuditEvent implements AuditEvent {
+
+  /**
+   * Timestamp for the audit event creation
+   */
+  private final Long timestamp;
+
+  /**
+   * Message to log
+   */
+  private final String auditMessage;
+
+  /**
+   * Base class for concrete audit event builders.
+   *
+   * @param <T>        the type of the concrete audit event built by this builder
+   * @param <TBuilder> the type of the concrete audit event builder.
+   */
+  protected static abstract class AbstractAuditEventBuilder<T extends AbstractAuditEvent, TBuilder extends AbstractAuditEventBuilder<T, TBuilder>>
+    implements AuditEventBuilder<T> {
+
+    private Long timestamp;
+    private String auditMessage;
+
+
+    /**
+     * Creates a new audit event instance from this builder.
+     *
+     * @return the build audit event instance.
+     */
+    protected abstract T newAuditEvent();
+
+    /**
+     * Appends details from this builder to the detailed description of the audit event.
+     *
+     * @param builder builder for the audit event details.
+     */
+    protected abstract void buildAuditMessage(StringBuilder builder);
+
+
+    /**
+     * The timestamp of the audit event.
+     *
+     * @param timestamp
+     * @return
+     */
+    public TBuilder withTimestamp(Long timestamp) {
+      this.timestamp = timestamp;
+
+      return (TBuilder) this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final T build() {
+      final StringBuilder auditMessageBuilder = new StringBuilder();
+
+      buildAuditMessage(auditMessageBuilder);
+      auditMessage = auditMessageBuilder.toString();
+
+      return newAuditEvent();
+    }
+
+  }
+
+
+  protected AbstractAuditEvent() {
+    this.timestamp = null;
+    this.auditMessage = null;
+  }
+
+  /**
+   * Constructor. Initializes fields using the provided builder.
+   *
+   * @param builder
+   */
+  protected AbstractAuditEvent(AbstractAuditEventBuilder<?, ?> builder) {
+    timestamp = builder.timestamp;
+    auditMessage = builder.auditMessage;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Long getTimestamp() {
+    return timestamp;
+  }
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getAuditMessage() {
+    return auditMessage;
+  }
+
+  @Override
+  public final boolean equals(Object o) {
+    if (this == o) return true;
+
+    if (!(o instanceof AbstractAuditEvent)) return false;
+
+    AbstractAuditEvent that = (AbstractAuditEvent) o;
+
+    return new EqualsBuilder()
+      .append(getTimestamp(), that.getTimestamp())
+      .append(getAuditMessage(), that.getAuditMessage())
+      .isEquals();
+  }
+
+  @Override
+  public final int hashCode() {
+    return new HashCodeBuilder(17, 37)
+      .append(getTimestamp())
+      .append(getAuditMessage())
+      .toHashCode();
+  }
+}

+ 92 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/AbstractUserAuditEvent.java

@@ -0,0 +1,92 @@
+/*
+ * 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.event;
+
+/**
+ * Base class for audit events which are result of user actions. It appends
+ * to audit event details the user name and remote ip of the host
+ * where user actions originates from.
+ */
+public abstract class AbstractUserAuditEvent extends AbstractAuditEvent {
+
+  public static abstract class AbstractUserAuditEventBuilder<T extends AbstractUserAuditEvent, TBuilder extends AbstractUserAuditEventBuilder<T, TBuilder>>
+    extends AbstractAuditEventBuilder<T, TBuilder> {
+
+    /**
+     * Name of the user started the operation
+     */
+    private String userName;
+
+    /**
+     * Ip of the user who started the operation. Note: remote ip might not be the original ip (proxies, routers can modify it)
+     */
+    private String remoteIp;
+
+    /**
+     * Appends to audit event details the user name and remote ip of the host
+     * where user actions originates from.
+     *
+     * @param builder builder for the audit message details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      builder
+        .append("User(")
+        .append(this.userName)
+        .append("), RemoteIp(")
+        .append(this.remoteIp)
+        .append(")");
+    }
+
+    /**
+     * Sets the user name of the user that initiated the audited action.
+     *
+     * @param userName
+     * @return the builder
+     */
+    public TBuilder withUserName(String userName) {
+      this.userName = userName;
+
+      return (TBuilder) this;
+    }
+
+    /**
+     * Sets the remote ip where the user action originated from.
+     *
+     * @param ip
+     * @return the builder
+     */
+    public TBuilder withRemoteIp(String ip) {
+      this.remoteIp = ip;
+
+      return (TBuilder) this;
+    }
+  }
+
+  protected AbstractUserAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AbstractUserAuditEvent(AbstractUserAuditEventBuilder<?, ?> builder) {
+    super(builder);
+  }
+
+}

+ 97 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/AccessUnauthorizedAuditEvent.java

@@ -0,0 +1,97 @@
+/*
+ * 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.event;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Access to given resource is not authorized.
+ */
+@Immutable
+public class AccessUnauthorizedAuditEvent extends AbstractUserAuditEvent {
+
+  public static class AccessUnauthorizedAuditEventBuilder
+    extends AbstractUserAuditEventBuilder<AccessUnauthorizedAuditEvent, AccessUnauthorizedAuditEventBuilder> {
+
+    /**
+     * Name of http method (PUT, POST, DELETE, etc...)
+     */
+    private String httpMethodName;
+
+    /**
+     * The resource path that is tried to be accessed
+     */
+    private String resourcePath;
+
+    /**
+     * Appends to the aduit event detail the list of the privileges
+     * possessed by the principal requesting access to a resource.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Operation(")
+        .append(httpMethodName)
+        .append("), ResourcePath(")
+        .append(resourcePath)
+        .append("), Status(Failed), Reason(Access not authorized)");
+    }
+
+    public AccessUnauthorizedAuditEventBuilder withHttpMethodName(String httpMethodName) {
+      this.httpMethodName = httpMethodName;
+      return this;
+    }
+
+    public AccessUnauthorizedAuditEventBuilder withResourcePath(String resourcePath) {
+      this.resourcePath = resourcePath;
+      return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected AccessUnauthorizedAuditEvent newAuditEvent() {
+      return new AccessUnauthorizedAuditEvent(this);
+    }
+  }
+
+  private AccessUnauthorizedAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private AccessUnauthorizedAuditEvent(AccessUnauthorizedAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AccessUnauthorizedAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AccessUnauthorizedAuditEventBuilder builder() {
+    return new AccessUnauthorizedAuditEventBuilder();
+  }
+}

+ 56 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/AuditEvent.java

@@ -0,0 +1,56 @@
+/*
+ * 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.event;
+
+/**
+ * Audit event that contains
+ * the details of an action/event
+ * that is subject to audit.
+ */
+public interface AuditEvent {
+
+  /**
+   * Builder for {@link AuditEvent}
+   *
+   * @param <T> the type of the concrete audit event.
+   */
+  interface AuditEventBuilder<T extends AuditEvent> {
+    /**
+     * Builds an audit event.
+     *
+     * @return audit event instance
+     */
+    T build();
+  }
+
+  /**
+   * Returns the timestamp of the audit event.
+   *
+   * @return timestamp of the audit event.
+   */
+  Long getTimestamp();
+
+  /**
+   * Returns the details of the audit event.
+   *
+   * @return detail of the audit event.
+   */
+  String getAuditMessage();
+
+}

+ 126 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/LoginAuditEvent.java

@@ -0,0 +1,126 @@
+/*
+ * 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.event;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Login audit event.
+ */
+@Immutable
+public class LoginAuditEvent extends AbstractUserAuditEvent {
+
+  public static class LoginAuditEventBuilder
+    extends AbstractUserAuditEventBuilder<LoginAuditEvent, LoginAuditEventBuilder> {
+
+    private LoginAuditEventBuilder() {
+    }
+
+    /**
+     * List of roles possessed by the principal requesting access to a resource.
+     * [ view name | cluster name | 'Ambari'] -> list of permissions
+     */
+    private Map<String, List<String>> roles;
+
+    /**
+     * Reason of failure, if it is not null, then the request status is consider as failed
+     */
+    private String reasonOfFailure;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Operation(User login), Roles(").append(System.lineSeparator());
+
+      if (roles != null && !roles.isEmpty()) {
+        List<String> lines = new LinkedList<>();
+        for (Map.Entry<String, List<String>> entry : roles.entrySet()) {
+          lines.add("    " + entry.getKey() + ": " + StringUtils.join(entry.getValue(), ", "));
+        }
+        builder.append(StringUtils.join(lines, System.lineSeparator()));
+        builder.append(System.lineSeparator());
+      }
+      builder.append("), Status(")
+        .append(reasonOfFailure == null ? "Success" : "Failed");
+
+      if (reasonOfFailure != null) {
+        builder.append("), Reason(")
+          .append(reasonOfFailure);
+      }
+      builder.append(")");
+    }
+
+    /**
+     * Sets the list of roles possessed by the principal requesting access to a resource.
+     *
+     * @param roles
+     * @return this builder
+     */
+    public LoginAuditEventBuilder withRoles(Map<String, List<String>> roles) {
+      this.roles = roles;
+
+      return this;
+    }
+
+    public LoginAuditEventBuilder withReasonOfFailure(String reasonOfFailure) {
+      this.reasonOfFailure = reasonOfFailure;
+      return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected LoginAuditEvent newAuditEvent() {
+      return new LoginAuditEvent(this);
+    }
+
+  }
+
+
+  private LoginAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private LoginAuditEvent(LoginAuditEventBuilder builder) {
+    super(builder);
+
+  }
+
+  /**
+   * Returns an builder for {@link LoginAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static LoginAuditEventBuilder builder() {
+    return new LoginAuditEventBuilder();
+  }
+}

+ 67 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/LogoutAuditEvent.java

@@ -0,0 +1,67 @@
+/*
+ * 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.event;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Logout audit event.
+ */
+@Immutable
+public class LogoutAuditEvent extends AbstractUserAuditEvent {
+  public static class LogoutAuditEventBuilder
+    extends AbstractUserAuditEventBuilder<LogoutAuditEvent, LogoutAuditEventBuilder> {
+
+    private LogoutAuditEventBuilder() {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+      builder.append(", Operation(Logout), Status(Success)");
+    }
+
+    @Override
+    protected LogoutAuditEvent newAuditEvent() {
+      return new LogoutAuditEvent(this);
+    }
+  }
+
+  private LogoutAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private LogoutAuditEvent(LogoutAuditEventBuilder builder) {
+    super(builder);
+
+  }
+
+  /**
+   * Returns an builder for {@link LogoutAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static LogoutAuditEventBuilder builder() {
+    return new LogoutAuditEventBuilder();
+  }
+}

+ 108 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/OperationStatusAuditEvent.java

@@ -0,0 +1,108 @@
+/*
+ * 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.event;
+
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Audit event for tracking operations
+ */
+@Immutable
+public class OperationStatusAuditEvent extends AbstractAuditEvent {
+
+  public static class OperationStatusAuditEventBuilder extends AbstractAuditEventBuilder<OperationStatusAuditEvent, OperationStatusAuditEventBuilder> {
+
+    /**
+     * Request identifier
+     */
+    private String requestId;
+
+    /**
+     * Status of the whole request
+     */
+    private String status;
+
+    /**
+     * Name of the operation
+     */
+    private String operation;
+
+    private OperationStatusAuditEventBuilder() {
+    }
+
+    @Override
+    protected OperationStatusAuditEvent newAuditEvent() {
+      return new OperationStatusAuditEvent(this);
+    }
+
+    /**
+     * Builds and audit log message based on the member variables
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      builder
+        .append("Operation(")
+        .append(this.operation)
+        .append("), Status(")
+        .append(this.status)
+        .append("), RequestId(")
+        .append(this.requestId)
+        .append(")");
+    }
+
+
+    public OperationStatusAuditEventBuilder withStatus(String status) {
+      this.status = status;
+      return this;
+    }
+
+    public OperationStatusAuditEventBuilder withRequestId(String requestId) {
+      this.requestId = requestId;
+      return this;
+    }
+
+    public OperationStatusAuditEventBuilder withRequestContext(String operation) {
+      this.operation = operation;
+      return this;
+    }
+  }
+
+  private OperationStatusAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private OperationStatusAuditEvent(OperationStatusAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link OperationStatusAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static OperationStatusAuditEventBuilder builder() {
+    return new OperationStatusAuditEventBuilder();
+  }
+
+}

+ 148 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/TaskStatusAuditEvent.java

@@ -0,0 +1,148 @@
+/*
+ * 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.event;
+
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Audit event for tracking task status
+ */
+@Immutable
+public class TaskStatusAuditEvent extends AbstractAuditEvent {
+
+  public static class TaskStatusAuditEventBuilder extends AbstractAuditEventBuilder<TaskStatusAuditEvent, TaskStatusAuditEventBuilder> {
+
+    /**
+     * Request identifier
+     */
+    private String requestId;
+
+    /**
+     * Task identifier
+     */
+    private String taskId;
+
+    /**
+     * Request identifier
+     */
+    private String hostName;
+
+    /**
+     * Status of the whole request
+     */
+    private String status;
+
+    /**
+     * Name of the operation
+     */
+    private String operation;
+
+    /**
+     * Task command details
+     */
+    private String details;
+
+    private TaskStatusAuditEventBuilder() {
+    }
+
+    @Override
+    protected TaskStatusAuditEvent newAuditEvent() {
+      return new TaskStatusAuditEvent(this);
+    }
+
+    /**
+     * Builds and audit log message based on the member variables
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      builder
+        .append("Operation(")
+        .append(this.operation);
+
+      if (details != null) {
+        builder.append("), Details(")
+          .append(this.details);
+      }
+
+      builder.append("), Status(")
+        .append(this.status)
+        .append("), RequestId(")
+        .append(this.requestId)
+        .append("), TaskId(")
+        .append(this.taskId)
+        .append("), Hostname(")
+        .append(this.hostName)
+        .append(")");
+    }
+
+
+    public TaskStatusAuditEventBuilder withStatus(String status) {
+      this.status = status;
+      return this;
+    }
+
+    public TaskStatusAuditEventBuilder withRequestId(String requestId) {
+      this.requestId = requestId;
+      return this;
+    }
+
+    public TaskStatusAuditEventBuilder withTaskId(String taskId) {
+      this.taskId = taskId;
+      return this;
+    }
+
+    public TaskStatusAuditEventBuilder withHostName(String hostName) {
+      this.hostName = hostName;
+      return this;
+    }
+
+    public TaskStatusAuditEventBuilder withOperation(String operation) {
+      this.operation = operation;
+      return this;
+    }
+
+    public TaskStatusAuditEventBuilder withDetails(String details) {
+      this.details = details;
+      return this;
+    }
+  }
+
+  private TaskStatusAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private TaskStatusAuditEvent(TaskStatusAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link TaskStatusAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static TaskStatusAuditEventBuilder builder() {
+    return new TaskStatusAuditEventBuilder();
+  }
+
+}

+ 87 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/AbstractKerberosAuditEvent.java

@@ -0,0 +1,87 @@
+/*
+ * 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.event.kerberos;
+
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.event.AbstractAuditEvent;
+
+/**
+ * Base class for kerberos audit events
+ */
+@Immutable
+public class AbstractKerberosAuditEvent extends AbstractAuditEvent {
+  static abstract class AbstractKerberosAuditEventBuilder<T extends AbstractKerberosAuditEvent, TBuilder extends AbstractKerberosAuditEventBuilder<T, TBuilder>>
+    extends AbstractAuditEvent.AbstractAuditEventBuilder<T, TBuilder> {
+
+    /**
+     * Description of the operation
+     */
+    protected String operation;
+
+    /**
+     * Reason of failure, if it is not null, then the request is considered as failed
+     */
+    protected String reasonOfFailure;
+
+    /**
+     * Builds and audit log message based on the member variables
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      builder
+        .append("Operation(")
+        .append(operation);
+
+      builder.append("), Status(")
+        .append(reasonOfFailure == null ? "Success" : "Failed");
+
+      if (reasonOfFailure != null) {
+        builder.append("), Reason of failure(")
+          .append(reasonOfFailure);
+      }
+
+      builder.append(")");
+    }
+
+    public TBuilder withOperation(String operation) {
+      this.operation = operation;
+      return (TBuilder) this;
+    }
+
+    public TBuilder withReasonOfFailure(String reasonOfFailure) {
+      this.reasonOfFailure = reasonOfFailure;
+      return (TBuilder) this;
+    }
+  }
+
+  protected AbstractKerberosAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AbstractKerberosAuditEvent(AbstractKerberosAuditEventBuilder<?, ?> builder) {
+    super(builder);
+  }
+
+}

+ 118 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/ChangeSecurityStateKerberosAuditEvent.java

@@ -0,0 +1,118 @@
+/*
+ * 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.event.kerberos;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Audit event for kerberos security state change of components
+ */
+@Immutable
+public class ChangeSecurityStateKerberosAuditEvent extends AbstractKerberosAuditEvent {
+
+  public static class ChangeSecurityStateKerberosAuditEventBuilder extends AbstractKerberosAuditEventBuilder<ChangeSecurityStateKerberosAuditEvent, ChangeSecurityStateKerberosAuditEventBuilder> {
+
+    /**
+     * Service name
+     */
+    private String service;
+
+    /**
+     * Component name
+     */
+    private String component;
+
+    /**
+     * Host name
+     */
+    private String hostName;
+
+    /**
+     * Security state
+     */
+    private String state;
+
+    private ChangeSecurityStateKerberosAuditEventBuilder() {
+      this.withOperation("Security state change");
+    }
+
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Hostname(")
+        .append(hostName)
+        .append("), Service(")
+        .append(service)
+        .append("), Component(")
+        .append(component)
+        .append("), State(")
+        .append(state)
+        .append(")");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ChangeSecurityStateKerberosAuditEvent newAuditEvent() {
+      return new ChangeSecurityStateKerberosAuditEvent(this);
+    }
+
+    public ChangeSecurityStateKerberosAuditEventBuilder withService(String service) {
+      this.service = service;
+      return this;
+    }
+
+    public ChangeSecurityStateKerberosAuditEventBuilder withComponent(String component) {
+      this.component = component;
+      return this;
+    }
+
+    public ChangeSecurityStateKerberosAuditEventBuilder withHostName(String hostName) {
+      this.hostName = hostName;
+      return this;
+    }
+
+    public ChangeSecurityStateKerberosAuditEventBuilder withState(String state) {
+      this.state = state;
+      return this;
+    }
+  }
+
+  private ChangeSecurityStateKerberosAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private ChangeSecurityStateKerberosAuditEvent(ChangeSecurityStateKerberosAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ChangeSecurityStateKerberosAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ChangeSecurityStateKerberosAuditEventBuilder builder() {
+    return new ChangeSecurityStateKerberosAuditEventBuilder();
+  }
+}

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/CreateKeyTabKerberosAuditEvent.java

@@ -0,0 +1,110 @@
+/*
+ * 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.event.kerberos;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Audit event for kerberos keytab change
+ */
+@Immutable
+public class CreateKeyTabKerberosAuditEvent extends AbstractKerberosAuditEvent {
+
+  public static class CreateKeyTabKerberosAuditEventBuilder extends AbstractKerberosAuditEventBuilder<CreateKeyTabKerberosAuditEvent, CreateKeyTabKerberosAuditEventBuilder> {
+
+    /**
+     * Path to keytab file
+     */
+    private String keyTabFilePath;
+
+    /**
+     * Host name
+     */
+    private String hostName;
+
+    /**
+     * Principal that belons to the keytab file
+     */
+    private String principal;
+
+    private CreateKeyTabKerberosAuditEventBuilder() {
+      this.withOperation("Keytab file creation");
+    }
+
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Principal(")
+        .append(principal)
+        .append("), Hostname(")
+        .append(hostName)
+        .append("), Keytab file(")
+        .append(keyTabFilePath)
+        .append(")");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected CreateKeyTabKerberosAuditEvent newAuditEvent() {
+      return new CreateKeyTabKerberosAuditEvent(this);
+    }
+
+    public CreateKeyTabKerberosAuditEventBuilder withKeyTabFilePath(String keyTabFilePath) {
+      this.keyTabFilePath = keyTabFilePath;
+      return this;
+    }
+
+    public CreateKeyTabKerberosAuditEventBuilder withHostName(String hostName) {
+      this.hostName = hostName;
+      return this;
+    }
+
+    public CreateKeyTabKerberosAuditEventBuilder withPrincipal(String principal) {
+      this.principal = principal;
+      return this;
+    }
+
+    public boolean hasPrincipal() {
+      return principal != null;
+    }
+  }
+
+  private CreateKeyTabKerberosAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private CreateKeyTabKerberosAuditEvent(CreateKeyTabKerberosAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link CreateKeyTabKerberosAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static CreateKeyTabKerberosAuditEventBuilder builder() {
+    return new CreateKeyTabKerberosAuditEventBuilder();
+  }
+}

+ 73 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/CreatePrincipalKerberosAuditEvent.java

@@ -0,0 +1,73 @@
+/*
+ * 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.event.kerberos;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public class CreatePrincipalKerberosAuditEvent extends AbstractKerberosAuditEvent {
+
+  public static class CreatePrincipalKerberosAuditEventBuilder extends AbstractKerberosAuditEventBuilder<CreatePrincipalKerberosAuditEvent, CreatePrincipalKerberosAuditEventBuilder> {
+
+    private String principal;
+
+    private CreatePrincipalKerberosAuditEventBuilder() {
+      this.withOperation("Principal creation");
+    }
+
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+      builder.append(", Principal(")
+        .append(principal);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected CreatePrincipalKerberosAuditEvent newAuditEvent() {
+      return new CreatePrincipalKerberosAuditEvent(this);
+    }
+
+    public CreatePrincipalKerberosAuditEventBuilder withPrincipal(String principal) {
+      this.principal = principal;
+      return this;
+    }
+  }
+
+  private CreatePrincipalKerberosAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private CreatePrincipalKerberosAuditEvent(CreatePrincipalKerberosAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link CreatePrincipalKerberosAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static CreatePrincipalKerberosAuditEventBuilder builder() {
+    return new CreatePrincipalKerberosAuditEventBuilder();
+  }
+}

+ 80 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/kerberos/DestroyPrincipalKerberosAuditEvent.java

@@ -0,0 +1,80 @@
+/*
+ * 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.event.kerberos;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Audit event for destroying principal
+ */
+@Immutable
+public class DestroyPrincipalKerberosAuditEvent extends AbstractKerberosAuditEvent {
+
+  public static class DestroyPrincipalKerberosAuditEventBuilder extends AbstractKerberosAuditEventBuilder<DestroyPrincipalKerberosAuditEvent, DestroyPrincipalKerberosAuditEventBuilder> {
+
+    /**
+     * Destroyed principal
+     */
+    private String principal;
+
+    private DestroyPrincipalKerberosAuditEventBuilder() {
+      this.withOperation("Principal removal");
+    }
+
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Principal(")
+        .append(principal);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected DestroyPrincipalKerberosAuditEvent newAuditEvent() {
+      return new DestroyPrincipalKerberosAuditEvent(this);
+    }
+
+    public DestroyPrincipalKerberosAuditEventBuilder withPrincipal(String principal) {
+      this.principal = principal;
+      return this;
+    }
+  }
+
+  private DestroyPrincipalKerberosAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private DestroyPrincipalKerberosAuditEvent(DestroyPrincipalKerberosAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DestroyPrincipalKerberosAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DestroyPrincipalKerberosAuditEventBuilder builder() {
+    return new DestroyPrincipalKerberosAuditEventBuilder();
+  }
+}

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ActivateUserRequestAuditEvent.java

@@ -0,0 +1,101 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for setting a user active or inactive
+ */
+@Immutable
+public class ActivateUserRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ActivateUserRequestAuditEventBuilder extends RequestAuditEventBuilder<ActivateUserRequestAuditEvent, ActivateUserRequestAuditEventBuilder> {
+
+    /**
+     * Active or inactive
+     */
+    private boolean active;
+
+    /**
+     * Name of the user to set active or inactive
+     */
+    private String username;
+
+    public ActivateUserRequestAuditEventBuilder() {
+      super.withOperation("Set user activate");
+    }
+
+    @Override
+    protected ActivateUserRequestAuditEvent newAuditEvent() {
+      return new ActivateUserRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Affected username(")
+        .append(username)
+        .append("), ")
+        .append("Active(")
+        .append(active ? "yes" : "no")
+        .append(")");
+    }
+
+    public ActivateUserRequestAuditEventBuilder withActive(boolean active) {
+      this.active = active;
+      return this;
+    }
+
+    public ActivateUserRequestAuditEventBuilder withAffectedUsername(String username) {
+      this.username = username;
+      return this;
+    }
+
+  }
+
+  protected ActivateUserRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ActivateUserRequestAuditEvent(ActivateUserRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ActivateUserRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ActivateUserRequestAuditEventBuilder builder() {
+    return new ActivateUserRequestAuditEventBuilder();
+  }
+
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddAlertGroupRequestAuditEvent.java

@@ -0,0 +1,113 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for adding alert group
+ */
+@Immutable
+public class AddAlertGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddAlertGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<AddAlertGroupRequestAuditEvent, AddAlertGroupRequestAuditEventBuilder> {
+
+    /**
+     * Group name
+     */
+    private String name;
+
+    /**
+     * Definition ids for the group
+     */
+    private List<String> definitionIds;
+
+    /**
+     * Notification ids for the group
+     */
+    private List<String> notificationIds;
+
+    public AddAlertGroupRequestAuditEventBuilder() {
+      super.withOperation("Alert group addition");
+    }
+
+    @Override
+    protected AddAlertGroupRequestAuditEvent newAuditEvent() {
+      return new AddAlertGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Alert group name(")
+        .append(name)
+        .append("), Definition IDs(")
+        .append(StringUtils.join(definitionIds, ", "))
+        .append("), Notification IDs(")
+        .append(StringUtils.join(notificationIds, ", "))
+        .append(")");
+    }
+
+    public AddAlertGroupRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public AddAlertGroupRequestAuditEventBuilder withDefinitionIds(List<String> ids) {
+      this.definitionIds = ids;
+      return this;
+    }
+
+    public AddAlertGroupRequestAuditEventBuilder withNotificationIds(List<String> ids) {
+      this.notificationIds = ids;
+      return this;
+    }
+  }
+
+  protected AddAlertGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddAlertGroupRequestAuditEvent(AddAlertGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddAlertGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddAlertGroupRequestAuditEventBuilder builder() {
+    return new AddAlertGroupRequestAuditEventBuilder();
+  }
+
+}

+ 167 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddAlertTargetRequestAuditEvent.java

@@ -0,0 +1,167 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for adding alert target (= notification)
+ */
+@Immutable
+public class AddAlertTargetRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddAlertTargetRequestAuditEventBuilder extends RequestAuditEventBuilder<AddAlertTargetRequestAuditEvent, AddAlertTargetRequestAuditEventBuilder> {
+
+    /**
+     * Name of the alert target
+     */
+    private String name;
+
+    /**
+     * Description of the alert target
+     */
+    private String description;
+
+    /**
+     * Type of the alert target
+     */
+    private String notificationType;
+
+    /**
+     * Group list that belongs to the alert target
+     */
+    private List<String> groupIds;
+
+    /**
+     * Email address that should be in the from field
+     */
+    private String emailFrom;
+
+    /**
+     * Eamil recipients
+     */
+    private List<String> emailRecipients;
+
+    /**
+     * Alert states for the alert target
+     */
+    private List<String> alertStates;
+
+    public AddAlertTargetRequestAuditEventBuilder() {
+      super.withOperation("Notification addition");
+    }
+
+    @Override
+    protected AddAlertTargetRequestAuditEvent newAuditEvent() {
+      return new AddAlertTargetRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Notification name(")
+        .append(name)
+        .append("), Description(")
+        .append(description)
+        .append("), Notification type(")
+        .append(notificationType)
+        .append("), Group IDs(")
+        .append(StringUtils.join(groupIds, ", "));
+
+      if (emailFrom != null) {
+        builder.append("), Email from(")
+          .append(emailFrom);
+      }
+
+      if (emailRecipients != null && !emailRecipients.isEmpty()) {
+        builder.append("), Email to(")
+          .append(StringUtils.join(emailRecipients, ", "));
+      }
+      builder.append("), Alert states(")
+        .append(StringUtils.join(alertStates, ", "))
+        .append(")");
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withDescription(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withNotificationType(String notificationType) {
+      this.notificationType = notificationType;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withGroupIds(List<String> groupIds) {
+      this.groupIds = groupIds;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withEmailFrom(String emailFrom) {
+      this.emailFrom = emailFrom;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withEmailRecipients(List<String> emailRecipients) {
+      this.emailRecipients = emailRecipients;
+      return this;
+    }
+
+    public AddAlertTargetRequestAuditEventBuilder withAlertStates(List<String> alertStates) {
+      this.alertStates = alertStates;
+      return this;
+    }
+  }
+
+  protected AddAlertTargetRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddAlertTargetRequestAuditEvent(AddAlertTargetRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddAlertTargetRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddAlertTargetRequestAuditEventBuilder builder() {
+    return new AddAlertTargetRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddBlueprintRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding blueprint
+ */
+@Immutable
+public class AddBlueprintRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddBlueprintRequestAuditEventBuilder extends RequestAuditEventBuilder<AddBlueprintRequestAuditEvent, AddBlueprintRequestAuditEventBuilder> {
+
+    /**
+     * Blueprint name
+     */
+    private String blueprintName;
+
+    public AddBlueprintRequestAuditEventBuilder() {
+      super.withOperation("Upload blueprint");
+    }
+
+    @Override
+    protected AddBlueprintRequestAuditEvent newAuditEvent() {
+      return new AddBlueprintRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Blueprint name(")
+        .append(blueprintName)
+        .append(")");
+    }
+
+    public AddBlueprintRequestAuditEventBuilder withBlueprintName(String blueprintName) {
+      this.blueprintName = blueprintName;
+      return this;
+    }
+
+  }
+
+  protected AddBlueprintRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddBlueprintRequestAuditEvent(AddBlueprintRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddBlueprintRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddBlueprintRequestAuditEventBuilder builder() {
+    return new AddBlueprintRequestAuditEventBuilder();
+  }
+
+}

+ 98 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddComponentToHostRequestAuditEvent.java

@@ -0,0 +1,98 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding component to a host
+ */
+@Immutable
+public class AddComponentToHostRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddComponentToHostRequestAuditEventBuilder extends RequestAuditEventBuilder<AddComponentToHostRequestAuditEvent, AddComponentToHostRequestAuditEventBuilder> {
+
+    /**
+     * Host name
+     */
+    private String hostName;
+
+    /**
+     * Component name
+     */
+    private String component;
+
+    public AddComponentToHostRequestAuditEventBuilder() {
+      super.withOperation("Component addition to host");
+    }
+
+    @Override
+    protected AddComponentToHostRequestAuditEvent newAuditEvent() {
+      return new AddComponentToHostRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Hostname(")
+        .append(hostName)
+        .append(", Component(")
+        .append(component)
+        .append(")");
+    }
+
+    public AddComponentToHostRequestAuditEventBuilder withHostName(String hostName) {
+      this.hostName = hostName;
+      return this;
+    }
+
+    public AddComponentToHostRequestAuditEventBuilder withComponent(String component) {
+      this.component = component;
+      return this;
+    }
+  }
+
+  protected AddComponentToHostRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddComponentToHostRequestAuditEvent(AddComponentToHostRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddComponentToHostRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddComponentToHostRequestAuditEventBuilder builder() {
+    return new AddComponentToHostRequestAuditEventBuilder();
+  }
+
+}

+ 122 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddCredentialRequestAuditEvent.java

@@ -0,0 +1,122 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding credential
+ */
+@Immutable
+public class AddCredentialRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddCredentialAuditEventBuilder extends RequestAuditEventBuilder<AddCredentialRequestAuditEvent, AddCredentialAuditEventBuilder> {
+
+    /**
+     * Credential type (e.g. temporary)
+     */
+    private String type;
+
+    /**
+     * Cluster name
+     */
+    private String clusterName;
+
+    /**
+     * Principal
+     */
+    private String principal;
+
+    /**
+     * Alias for the credential
+     */
+    private String alias;
+
+    public AddCredentialAuditEventBuilder() {
+      super.withOperation("Credential addition");
+    }
+
+    @Override
+    protected AddCredentialRequestAuditEvent newAuditEvent() {
+      return new AddCredentialRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Type(")
+        .append(type)
+        .append("), Principal(")
+        .append(principal)
+        .append("), Alias(")
+        .append(alias)
+        .append("), Cluster name(")
+        .append(clusterName)
+        .append(")");
+    }
+
+    public AddCredentialAuditEventBuilder withType(String type) {
+      this.type = type;
+      return this;
+    }
+
+    public AddCredentialAuditEventBuilder withClusterName(String clusterName) {
+      this.clusterName = clusterName;
+      return this;
+    }
+
+    public AddCredentialAuditEventBuilder withPrincipal(String principal) {
+      this.principal = principal;
+      return this;
+    }
+
+    public AddCredentialAuditEventBuilder withAlias(String alias) {
+      this.alias = alias;
+      return this;
+    }
+  }
+
+  protected AddCredentialRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddCredentialRequestAuditEvent(AddCredentialAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddCredentialRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddCredentialAuditEventBuilder builder() {
+    return new AddCredentialAuditEventBuilder();
+  }
+
+}

+ 86 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddHostRequestAuditEvent.java

@@ -0,0 +1,86 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding host
+ */
+@Immutable
+public class AddHostRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddHostRequestAuditEventBuilder extends RequestAuditEventBuilder<AddHostRequestAuditEvent, AddHostRequestAuditEventBuilder> {
+
+    /**
+     * Hostname that is added
+     */
+    private String hostName;
+
+    public AddHostRequestAuditEventBuilder() {
+      super.withOperation("Host addition");
+    }
+
+    @Override
+    protected AddHostRequestAuditEvent newAuditEvent() {
+      return new AddHostRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Hostname(")
+        .append(hostName)
+        .append(")");
+    }
+
+    public AddHostRequestAuditEventBuilder withHostName(String hostName) {
+      this.hostName = hostName;
+      return this;
+    }
+  }
+
+  protected AddHostRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddHostRequestAuditEvent(AddHostRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddHostRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddHostRequestAuditEventBuilder builder() {
+    return new AddHostRequestAuditEventBuilder();
+  }
+
+}

+ 134 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRepositoryRequestAuditEvent.java

@@ -0,0 +1,134 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding repository
+ */
+@Immutable
+public class AddRepositoryRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddRepositoryRequestAuditEventBuilder extends RequestAuditEventBuilder<AddRepositoryRequestAuditEvent, AddRepositoryRequestAuditEventBuilder> {
+
+    /**
+     * Repository name
+     */
+    private String repo;
+
+    /**
+     * Stack name
+     */
+    private String stackName;
+
+    /**
+     * Operating system type
+     */
+    private String osType;
+
+    /**
+     * Base url for the repository
+     */
+    private String baseUrl;
+
+    /**
+     * Stack version
+     */
+    private String stackVersion;
+
+    public AddRepositoryRequestAuditEventBuilder() {
+      super.withOperation("Repository addition");
+    }
+
+    @Override
+    protected AddRepositoryRequestAuditEvent newAuditEvent() {
+      return new AddRepositoryRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stack(")
+        .append(stackName)
+        .append("), Stack version(")
+        .append(stackVersion)
+        .append("), OS(")
+        .append(osType)
+        .append("), Repo id(")
+        .append(repo)
+        .append("), Base URL(")
+        .append(baseUrl)
+        .append(")");
+    }
+
+    public AddRepositoryRequestAuditEventBuilder withRepo(String repo) {
+      this.repo = repo;
+      return this;
+    }
+
+    public AddRepositoryRequestAuditEventBuilder withStackName(String stackName) {
+      this.stackName = stackName;
+      return this;
+    }
+
+    public AddRepositoryRequestAuditEventBuilder withOsType(String osType) {
+      this.osType = osType;
+      return this;
+    }
+
+    public AddRepositoryRequestAuditEventBuilder withBaseUrl(String baseUrl) {
+      this.baseUrl = baseUrl;
+      return this;
+    }
+
+    public AddRepositoryRequestAuditEventBuilder withStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+      return this;
+    }
+  }
+
+  protected AddRepositoryRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddRepositoryRequestAuditEvent(AddRepositoryRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddRepositoryRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddRepositoryRequestAuditEventBuilder builder() {
+    return new AddRepositoryRequestAuditEventBuilder();
+  }
+
+}

+ 153 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRepositoryVersionRequestAuditEvent.java

@@ -0,0 +1,153 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding repository version
+ */
+@Immutable
+public class AddRepositoryVersionRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddRepositoryVersionAuditEventBuilder extends RequestAuditEventBuilder<AddRepositoryVersionRequestAuditEvent, AddRepositoryVersionAuditEventBuilder> {
+
+    /**
+     * Stack name
+     */
+    private String stackName;
+
+    /**
+     * Display name
+     */
+    private String displayName;
+
+    /**
+     * Stack version
+     */
+    private String stackVersion;
+
+    /**
+     * Repository version
+     */
+    private String repoVersion;
+
+    /**
+     * Details of the repositories
+     * os type -> list of repositories, where a repository is a key-value map of the properties (repo_id, repo_name, base_url)
+     */
+    private Map<String, List<Map<String, String>>> repos;
+
+    public AddRepositoryVersionAuditEventBuilder() {
+      super.withOperation("Repository version addition");
+    }
+
+    @Override
+    protected AddRepositoryVersionRequestAuditEvent newAuditEvent() {
+      return new AddRepositoryVersionRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stack(")
+        .append(stackName)
+        .append("), Stack version(")
+        .append(stackVersion)
+        .append("), Display name(")
+        .append(displayName)
+        .append("), Repo version(")
+        .append(repoVersion)
+        .append("), Repositories(");
+
+      if (!repos.isEmpty()) {
+        builder.append(System.lineSeparator());
+      }
+
+      for (Map.Entry<String, List<Map<String, String>>> repo : repos.entrySet()) {
+        builder.append("Operating system: ").append(repo.getKey());
+        builder.append(System.lineSeparator());
+        for (Map<String, String> properties : repo.getValue()) {
+          builder.append("    Repository ID(").append(properties.get("repo_id"));
+          builder.append("), Repository name(").append(properties.get("repo_name"));
+          builder.append("), Base url(").append(properties.get("base_url")).append(")");
+          builder.append(System.lineSeparator());
+        }
+      }
+
+      builder.append(")");
+    }
+
+    public AddRepositoryVersionAuditEventBuilder withStackName(String stackName) {
+      this.stackName = stackName;
+      return this;
+    }
+
+    public AddRepositoryVersionAuditEventBuilder withDisplayName(String displayName) {
+      this.displayName = displayName;
+      return this;
+    }
+
+    public AddRepositoryVersionAuditEventBuilder withStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+      return this;
+    }
+
+    public AddRepositoryVersionAuditEventBuilder withRepoVersion(String repoVersion) {
+      this.repoVersion = repoVersion;
+      return this;
+    }
+
+    public AddRepositoryVersionAuditEventBuilder withRepos(Map<String, List<Map<String, String>>> repos) {
+      this.repos = repos;
+      return this;
+    }
+  }
+
+  protected AddRepositoryVersionRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddRepositoryVersionRequestAuditEvent(AddRepositoryVersionAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddRepositoryVersionRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddRepositoryVersionAuditEventBuilder builder() {
+    return new AddRepositoryVersionAuditEventBuilder();
+  }
+
+}

+ 98 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddRequestRequestAuditEvent.java

@@ -0,0 +1,98 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for request
+ */
+@Immutable
+public class AddRequestRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddRequestAuditEventBuilder extends RequestAuditEventBuilder<AddRequestRequestAuditEvent, AddRequestAuditEventBuilder> {
+
+    /**
+     * Command in the request
+     */
+    private String command;
+
+    /**
+     * Cluster name
+     */
+    private String clusterName;
+
+    public AddRequestAuditEventBuilder() {
+      super.withOperation("Request from server");
+    }
+
+    @Override
+    protected AddRequestRequestAuditEvent newAuditEvent() {
+      return new AddRequestRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Command(")
+        .append(command)
+        .append("), Cluster name(")
+        .append(clusterName)
+        .append(")");
+    }
+
+    public AddRequestAuditEventBuilder withClusterName(String clusterName) {
+      this.clusterName = clusterName;
+      return this;
+    }
+
+    public AddRequestAuditEventBuilder withCommand(String command) {
+      this.command = command;
+      return this;
+    }
+  }
+
+  protected AddRequestRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddRequestRequestAuditEvent(AddRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddRequestRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddRequestAuditEventBuilder builder() {
+    return new AddRequestAuditEventBuilder();
+  }
+
+}

+ 111 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java

@@ -0,0 +1,111 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding upgrade
+ */
+@Immutable
+public class AddUpgradeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddUpgradeRequestAuditEventBuilder extends RequestAuditEventBuilder<AddUpgradeRequestAuditEvent, AddUpgradeRequestAuditEventBuilder> {
+
+    /**
+     * Repository version
+     */
+    private String repositoryVersion;
+
+    /**
+     * Upgrade type (rolling, non-rolling)
+     */
+    private String upgradeType;
+
+    /**
+     * Cluster name
+     */
+    private String clusterName;
+
+
+    public AddUpgradeRequestAuditEventBuilder() {
+      super.withOperation("Upgrade addition");
+    }
+
+    @Override
+    protected AddUpgradeRequestAuditEvent newAuditEvent() {
+      return new AddUpgradeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Repository version(")
+        .append(repositoryVersion)
+        .append("), Upgrade type(")
+        .append(upgradeType)
+        .append("), Cluster name(")
+        .append(clusterName)
+        .append(")");
+    }
+
+    public AddUpgradeRequestAuditEventBuilder withRepositoryVersion(String repositoryVersion) {
+      this.repositoryVersion = repositoryVersion;
+      return this;
+    }
+
+    public AddUpgradeRequestAuditEventBuilder withUpgradeType(String upgradeType) {
+      this.upgradeType = upgradeType;
+      return this;
+    }
+
+    public AddUpgradeRequestAuditEventBuilder withClusterName(String clusterName) {
+      this.clusterName = clusterName;
+      return this;
+    }
+  }
+
+  protected AddUpgradeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddUpgradeRequestAuditEvent(AddUpgradeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddUpgradeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddUpgradeRequestAuditEventBuilder builder() {
+    return new AddUpgradeRequestAuditEventBuilder();
+  }
+
+}

+ 98 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUserToGroupRequestAuditEvent.java

@@ -0,0 +1,98 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding a user to a group
+ */
+@Immutable
+public class AddUserToGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddUserToGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<AddUserToGroupRequestAuditEvent, AddUserToGroupRequestAuditEventBuilder> {
+
+    /**
+     * Group name
+     */
+    private String groupName;
+
+    /**
+     * Name of the user that is put to the group
+     */
+    private String affectedUserName;
+
+    public AddUserToGroupRequestAuditEventBuilder() {
+      super.withOperation("User addition to group");
+    }
+
+    @Override
+    protected AddUserToGroupRequestAuditEvent newAuditEvent() {
+      return new AddUserToGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Group(");
+      builder.append(groupName);
+      builder.append("), Affected username(");
+      builder.append(affectedUserName);
+      builder.append(")");
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withGroupName(String groupName) {
+      this.groupName = groupName;
+      return this;
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withAffectedUserName(String userName) {
+      this.affectedUserName = userName;
+      return this;
+    }
+  }
+
+  protected AddUserToGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddUserToGroupRequestAuditEvent(AddUserToGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddUserToGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddUserToGroupRequestAuditEventBuilder builder() {
+    return new AddUserToGroupRequestAuditEventBuilder();
+  }
+
+}

+ 134 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddViewInstanceRequestAuditEvent.java

@@ -0,0 +1,134 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for adding view instance
+ */
+@Immutable
+public class AddViewInstanceRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddViewInstanceRequestAuditEventBuilder extends RequestAuditEventBuilder<AddViewInstanceRequestAuditEvent, AddViewInstanceRequestAuditEventBuilder> {
+
+    /**
+     * View instance description
+     */
+    private String description;
+
+    /**
+     * View instance name
+     */
+    private String name;
+
+    /**
+     * View instance type (Files, Tez, etc)
+     */
+    private String type;
+
+    /**
+     * Display name for the view instance
+     */
+    private String displayName;
+
+    /**
+     * View instance version
+     */
+    private String version;
+
+    public AddViewInstanceRequestAuditEventBuilder() {
+      super.withOperation("View addition");
+    }
+
+    @Override
+    protected AddViewInstanceRequestAuditEvent newAuditEvent() {
+      return new AddViewInstanceRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Type(")
+        .append(type)
+        .append("), Version(")
+        .append(version)
+        .append("), Name(")
+        .append(name)
+        .append("), Display name(")
+        .append(displayName)
+        .append("), Description(")
+        .append(description)
+        .append(")");
+    }
+
+    public AddViewInstanceRequestAuditEventBuilder withDescription(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public AddViewInstanceRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public AddViewInstanceRequestAuditEventBuilder withType(String type) {
+      this.type = type;
+      return this;
+    }
+
+    public AddViewInstanceRequestAuditEventBuilder withDisplayName(String displayName) {
+      this.displayName = displayName;
+      return this;
+    }
+
+    public AddViewInstanceRequestAuditEventBuilder withVersion(String version) {
+      this.version = version;
+      return this;
+    }
+  }
+
+  protected AddViewInstanceRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AddViewInstanceRequestAuditEvent(AddViewInstanceRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AddViewInstanceRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddViewInstanceRequestAuditEventBuilder builder() {
+    return new AddViewInstanceRequestAuditEventBuilder();
+  }
+
+}

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AdminUserRequestAuditEvent.java

@@ -0,0 +1,101 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for setting or unsetting a user as admin
+ */
+@Immutable
+public class AdminUserRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AdminUserRequestAuditEventBuilder extends RequestAuditEventBuilder<AdminUserRequestAuditEvent, AdminUserRequestAuditEventBuilder> {
+
+    /**
+     * Admin is set or not
+     */
+    private boolean admin;
+
+    /**
+     * Name of the user that is set or unset as admin
+     */
+    private String username;
+
+    public AdminUserRequestAuditEventBuilder() {
+      super.withOperation("Set user admin");
+    }
+
+    @Override
+    protected AdminUserRequestAuditEvent newAuditEvent() {
+      return new AdminUserRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Affeted username(")
+        .append(username)
+        .append("), ")
+        .append("Administrator(")
+        .append(admin ? "yes" : "no")
+        .append(")");
+    }
+
+    public AdminUserRequestAuditEventBuilder withAdmin(boolean admin) {
+      this.admin = admin;
+      return this;
+    }
+
+    public AdminUserRequestAuditEventBuilder withAffectedUsername(String username) {
+      this.username = username;
+      return this;
+    }
+
+  }
+
+  protected AdminUserRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected AdminUserRequestAuditEvent(AdminUserRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link AdminUserRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AdminUserRequestAuditEventBuilder builder() {
+    return new AdminUserRequestAuditEventBuilder();
+  }
+
+}

+ 72 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/BlueprintExportRequestAuditEvent.java

@@ -0,0 +1,72 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for blueprint export
+ */
+@Immutable
+public class BlueprintExportRequestAuditEvent extends RequestAuditEvent {
+
+  public static class BlueprintExportRequestAuditEventBuilder extends RequestAuditEventBuilder<BlueprintExportRequestAuditEvent, BlueprintExportRequestAuditEventBuilder> {
+
+    public BlueprintExportRequestAuditEventBuilder() {
+      super.withOperation("Blueprint export");
+    }
+
+    @Override
+    protected BlueprintExportRequestAuditEvent newAuditEvent() {
+      return new BlueprintExportRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+    }
+  }
+
+  protected BlueprintExportRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected BlueprintExportRequestAuditEvent(BlueprintExportRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link BlueprintExportRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static BlueprintExportRequestAuditEventBuilder builder() {
+    return new BlueprintExportRequestAuditEventBuilder();
+  }
+
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeAlertGroupRequestAuditEvent.java

@@ -0,0 +1,113 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for changing alert group
+ */
+@Immutable
+public class ChangeAlertGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ChangeAlertGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<ChangeAlertGroupRequestAuditEvent, ChangeAlertGroupRequestAuditEventBuilder> {
+
+    /**
+     * Group name
+     */
+    private String name;
+
+    /**
+     * Definition ids
+     */
+    private List<String> definitionIds;
+
+    /**
+     * Notification ids
+     */
+    private List<String> notificationIds;
+
+    public ChangeAlertGroupRequestAuditEventBuilder() {
+      super.withOperation("Alert group change");
+    }
+
+    @Override
+    protected ChangeAlertGroupRequestAuditEvent newAuditEvent() {
+      return new ChangeAlertGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Alert group name(")
+        .append(name)
+        .append("), Definition IDs(")
+        .append(StringUtils.join(definitionIds, ", "))
+        .append("), Notification IDs(")
+        .append(StringUtils.join(notificationIds, ", "))
+        .append(")");
+    }
+
+    public ChangeAlertGroupRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public ChangeAlertGroupRequestAuditEventBuilder withDefinitionIds(List<String> ids) {
+      this.definitionIds = ids;
+      return this;
+    }
+
+    public ChangeAlertGroupRequestAuditEventBuilder withNotificationIds(List<String> ids) {
+      this.notificationIds = ids;
+      return this;
+    }
+  }
+
+  protected ChangeAlertGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ChangeAlertGroupRequestAuditEvent(ChangeAlertGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ChangeAlertGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ChangeAlertGroupRequestAuditEventBuilder builder() {
+    return new ChangeAlertGroupRequestAuditEventBuilder();
+  }
+
+}

+ 134 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeAlertTargetRequestAuditEvent.java

@@ -0,0 +1,134 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+public class ChangeAlertTargetRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ChangeAlertTargetRequestAuditEventBuilder extends RequestAuditEventBuilder<ChangeAlertTargetRequestAuditEvent, ChangeAlertTargetRequestAuditEventBuilder> {
+
+    private String name;
+    private String description;
+    private String notificationType;
+    private List<String> groupIds;
+    private String emailFrom;
+    private List<String> emailRecipients;
+    private List<String> alertStates;
+
+    public ChangeAlertTargetRequestAuditEventBuilder() {
+      super.withOperation("Notification change");
+    }
+
+    @Override
+    protected ChangeAlertTargetRequestAuditEvent newAuditEvent() {
+      return new ChangeAlertTargetRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Notification name(")
+        .append(name)
+        .append("), Description(")
+        .append(description)
+        .append("), Notification type(")
+        .append(notificationType)
+        .append("), Group IDs(")
+        .append(StringUtils.join(groupIds, ", "));
+
+      if (emailFrom != null) {
+        builder.append("), Email from(")
+          .append(emailFrom);
+      }
+
+      if (emailRecipients != null && !emailRecipients.isEmpty()) {
+        builder.append("), Email to(")
+          .append(StringUtils.join(emailRecipients, ", "));
+      }
+      builder.append("), Alert states(")
+        .append(StringUtils.join(alertStates, ", "))
+        .append(")");
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withDescription(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withNotificationType(String notificationType) {
+      this.notificationType = notificationType;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withGroupIds(List<String> groupIds) {
+      this.groupIds = groupIds;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withEmailFrom(String emailFrom) {
+      this.emailFrom = emailFrom;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withEmailRecipients(List<String> emailRecipients) {
+      this.emailRecipients = emailRecipients;
+      return this;
+    }
+
+    public ChangeAlertTargetRequestAuditEventBuilder withAlertStates(List<String> alertStates) {
+      this.alertStates = alertStates;
+      return this;
+    }
+  }
+
+  protected ChangeAlertTargetRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ChangeAlertTargetRequestAuditEvent(ChangeAlertTargetRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ChangeAlertTargetRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ChangeAlertTargetRequestAuditEventBuilder builder() {
+    return new ChangeAlertTargetRequestAuditEventBuilder();
+  }
+
+}

+ 153 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeRepositoryVersionRequestAuditEvent.java

@@ -0,0 +1,153 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for changing repository version
+ */
+@Immutable
+public class ChangeRepositoryVersionRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ChangeRepositoryVersionAuditEventBuilder extends RequestAuditEventBuilder<ChangeRepositoryVersionRequestAuditEvent, ChangeRepositoryVersionAuditEventBuilder> {
+
+    /**
+     * Stack name
+     */
+    private String stackName;
+
+    /**
+     * Display name
+     */
+    private String displayName;
+
+    /**
+     * Stack version
+     */
+    private String stackVersion;
+
+    /**
+     * Repository version
+     */
+    private String repoVersion;
+
+    /**
+     * Details of the repositories
+     * os type -> list of repositories, where a repository is a key-value map of the properties (repo_id, repo_name, base_url)
+     */
+    private Map<String, List<Map<String, String>>> repos;
+
+    public ChangeRepositoryVersionAuditEventBuilder() {
+      super.withOperation("Repository version change");
+    }
+
+    @Override
+    protected ChangeRepositoryVersionRequestAuditEvent newAuditEvent() {
+      return new ChangeRepositoryVersionRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stack(")
+        .append(stackName)
+        .append("), Stack version(")
+        .append(stackVersion)
+        .append("), Display name(")
+        .append(displayName)
+        .append("), Repo version(")
+        .append(repoVersion)
+        .append("), Repositories(");
+
+      if (!repos.isEmpty()) {
+        builder.append(System.lineSeparator());
+      }
+
+      for (Map.Entry<String, List<Map<String, String>>> repo : repos.entrySet()) {
+        builder.append("Operating system: ").append(repo.getKey());
+        builder.append(System.lineSeparator());
+        for (Map<String, String> properties : repo.getValue()) {
+          builder.append("    Repository ID(").append(properties.get("repo_id"));
+          builder.append("), Repository name(").append(properties.get("repo_name"));
+          builder.append("), Base url(").append(properties.get("base_url")).append(")");
+          builder.append(System.lineSeparator());
+        }
+      }
+
+      builder.append(")");
+    }
+
+    public ChangeRepositoryVersionAuditEventBuilder withStackName(String stackName) {
+      this.stackName = stackName;
+      return this;
+    }
+
+    public ChangeRepositoryVersionAuditEventBuilder withDisplayName(String displayName) {
+      this.displayName = displayName;
+      return this;
+    }
+
+    public ChangeRepositoryVersionAuditEventBuilder withStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+      return this;
+    }
+
+    public ChangeRepositoryVersionAuditEventBuilder withRepoVersion(String repoVersion) {
+      this.repoVersion = repoVersion;
+      return this;
+    }
+
+    public ChangeRepositoryVersionAuditEventBuilder withRepos(Map<String, List<Map<String, String>>> repos) {
+      this.repos = repos;
+      return this;
+    }
+  }
+
+  protected ChangeRepositoryVersionRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ChangeRepositoryVersionRequestAuditEvent(ChangeRepositoryVersionAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ChangeRepositoryVersionRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ChangeRepositoryVersionAuditEventBuilder builder() {
+    return new ChangeRepositoryVersionAuditEventBuilder();
+  }
+
+}

+ 134 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ChangeViewInstanceRequestAuditEvent.java

@@ -0,0 +1,134 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for change view instance
+ */
+@Immutable
+public class ChangeViewInstanceRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ChangeViewInstanceRequestAuditEventBuilder extends RequestAuditEventBuilder<ChangeViewInstanceRequestAuditEvent, ChangeViewInstanceRequestAuditEventBuilder> {
+
+    /**
+     * Description for the view instance
+     */
+    private String description;
+
+    /**
+     * Name for the view instance
+     */
+    private String name;
+
+    /**
+     * Type for view instance (Files, Tez)
+     */
+    private String type;
+
+    /**
+     * Display name for view instance
+     */
+    private String displayName;
+
+    /**
+     * Version for view instance
+     */
+    private String version;
+
+    public ChangeViewInstanceRequestAuditEventBuilder() {
+      super.withOperation("View change");
+    }
+
+    @Override
+    protected ChangeViewInstanceRequestAuditEvent newAuditEvent() {
+      return new ChangeViewInstanceRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Type(")
+        .append(type)
+        .append("), Version(")
+        .append(version)
+        .append("), Name(")
+        .append(name)
+        .append("), Display name(")
+        .append(displayName)
+        .append("), Description(")
+        .append(description)
+        .append(")");
+    }
+
+    public ChangeViewInstanceRequestAuditEventBuilder withDescription(String description) {
+      this.description = description;
+      return this;
+    }
+
+    public ChangeViewInstanceRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public ChangeViewInstanceRequestAuditEventBuilder withType(String type) {
+      this.type = type;
+      return this;
+    }
+
+    public ChangeViewInstanceRequestAuditEventBuilder withDisplayName(String displayName) {
+      this.displayName = displayName;
+      return this;
+    }
+
+    public ChangeViewInstanceRequestAuditEventBuilder withVersion(String version) {
+      this.version = version;
+      return this;
+    }
+  }
+
+  protected ChangeViewInstanceRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ChangeViewInstanceRequestAuditEvent(ChangeViewInstanceRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ChangeViewInstanceRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ChangeViewInstanceRequestAuditEventBuilder builder() {
+    return new ChangeViewInstanceRequestAuditEventBuilder();
+  }
+
+}

+ 100 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClientConfigDownloadRequestAuditEvent.java

@@ -0,0 +1,100 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for downloading client config for a component
+ */
+@Immutable
+public class ClientConfigDownloadRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ClientConfigDownloadRequestAuditEventBuilder extends RequestAuditEventBuilder<ClientConfigDownloadRequestAuditEvent, ClientConfigDownloadRequestAuditEventBuilder> {
+
+    /**
+     * Service name
+     */
+    private String service;
+
+    /**
+     * Component name
+     */
+    private String component;
+
+    public ClientConfigDownloadRequestAuditEventBuilder() {
+      super.withOperation("Client config download");
+    }
+
+    @Override
+    protected ClientConfigDownloadRequestAuditEvent newAuditEvent() {
+      return new ClientConfigDownloadRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Service(")
+        .append(service)
+        .append("), Component(")
+        .append(component)
+        .append(")");
+
+    }
+
+    public ClientConfigDownloadRequestAuditEventBuilder withService(String service) {
+      this.service = service;
+      return this;
+    }
+
+    public ClientConfigDownloadRequestAuditEventBuilder withComponent(String component) {
+      this.component = component;
+      return this;
+    }
+
+  }
+
+  protected ClientConfigDownloadRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ClientConfigDownloadRequestAuditEvent(ClientConfigDownloadRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ClientConfigDownloadRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ClientConfigDownloadRequestAuditEventBuilder builder() {
+    return new ClientConfigDownloadRequestAuditEventBuilder();
+  }
+
+}

+ 91 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClusterNameChangeRequestAuditEvent.java

@@ -0,0 +1,91 @@
+/*
+ * 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.event.request;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Base class for start operation audit events.
+ */
+public class ClusterNameChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ClusterNameChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<ClusterNameChangeRequestAuditEvent, ClusterNameChangeRequestAuditEventBuilder> {
+
+    private String oldName;
+
+    private String newName;
+
+    public ClusterNameChangeRequestAuditEventBuilder() {
+      super.withOperation("Cluster name change");
+    }
+
+    @Override
+    protected ClusterNameChangeRequestAuditEvent newAuditEvent() {
+      return new ClusterNameChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Old name(")
+        .append(oldName)
+        .append("), New name(")
+        .append(newName)
+        .append(")");
+    }
+
+    public ClusterNameChangeRequestAuditEventBuilder withOldName(String oldName) {
+      this.oldName = oldName;
+      return this;
+    }
+
+    public ClusterNameChangeRequestAuditEventBuilder withNewName(String newName) {
+      this.newName = newName;
+      return this;
+    }
+
+  }
+
+  protected ClusterNameChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ClusterNameChangeRequestAuditEvent(ClusterNameChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ClusterNameChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ClusterNameChangeRequestAuditEventBuilder builder() {
+    return new ClusterNameChangeRequestAuditEventBuilder();
+  }
+
+}

+ 126 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ClusterPrivilegeChangeRequestAuditEvent.java

@@ -0,0 +1,126 @@
+/*
+ * 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.event.request;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for changing cluster privilege
+ */
+@Immutable
+public class ClusterPrivilegeChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ClusterPrivilegeChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<ClusterPrivilegeChangeRequestAuditEvent, ClusterPrivilegeChangeRequestAuditEventBuilder> {
+
+    /**
+     * Roles for users
+     * username -> list of roles
+     */
+    private Map<String, List<String>> users;
+
+    /**
+     * Roles for groups
+     * groupname -> list fo roles
+     */
+    private Map<String, List<String>> groups;
+
+    public ClusterPrivilegeChangeRequestAuditEventBuilder() {
+      super.withOperation("Role change");
+    }
+
+    @Override
+    protected ClusterPrivilegeChangeRequestAuditEvent newAuditEvent() {
+      return new ClusterPrivilegeChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      Set<String> roleSet = new HashSet<String>();
+      roleSet.addAll(users.keySet());
+      roleSet.addAll(groups.keySet());
+
+      builder.append(", Roles(");
+      if (!users.isEmpty() || !groups.isEmpty()) {
+        builder.append(System.lineSeparator());
+      }
+
+      List<String> lines = new LinkedList<String>();
+
+      for (String role : roleSet) {
+        lines.add(role + ": ");
+        if (users.get(role) != null && !users.get(role).isEmpty()) {
+          lines.add("  Users: " + StringUtils.join(users.get(role), ", "));
+        }
+        if (groups.get(role) != null && !groups.get(role).isEmpty()) {
+          lines.add("  Groups: " + StringUtils.join(groups.get(role), ", "));
+        }
+      }
+
+      builder.append(StringUtils.join(lines, System.lineSeparator()));
+
+      builder.append(")");
+    }
+
+    public ClusterPrivilegeChangeRequestAuditEventBuilder withUsers(Map<String, List<String>> users) {
+      this.users = users;
+      return this;
+    }
+
+    public ClusterPrivilegeChangeRequestAuditEventBuilder withGroups(Map<String, List<String>> groups) {
+      this.groups = groups;
+      return this;
+    }
+  }
+
+  protected ClusterPrivilegeChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ClusterPrivilegeChangeRequestAuditEvent(ClusterPrivilegeChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ClusterPrivilegeChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ClusterPrivilegeChangeRequestAuditEventBuilder builder() {
+    return new ClusterPrivilegeChangeRequestAuditEventBuilder();
+  }
+
+}

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ConfigurationChangeRequestAuditEvent.java

@@ -0,0 +1,101 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for configuration change
+ */
+@Immutable
+public class ConfigurationChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ConfigurationChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<ConfigurationChangeRequestAuditEvent, ConfigurationChangeRequestAuditEventBuilder> {
+
+    /**
+     * Version number of the new version
+     */
+    private String versionNumber;
+
+    /**
+     * Version note for the new version
+     */
+    private String versionNote;
+
+    public ConfigurationChangeRequestAuditEventBuilder() {
+      super.withOperation("Configuration change");
+    }
+
+    @Override
+    protected ConfigurationChangeRequestAuditEvent newAuditEvent() {
+      return new ConfigurationChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", VersionNumber(V")
+        .append(versionNumber)
+        .append("), ")
+        .append("VersionNote(")
+        .append(versionNote)
+        .append(")");
+    }
+
+    public ConfigurationChangeRequestAuditEventBuilder withVersionNumber(String versionNumber) {
+      this.versionNumber = versionNumber;
+      return this;
+    }
+
+    public ConfigurationChangeRequestAuditEventBuilder withVersionNote(String versionNote) {
+      this.versionNote = versionNote;
+      return this;
+    }
+
+  }
+
+  protected ConfigurationChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ConfigurationChangeRequestAuditEvent(ConfigurationChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ConfigurationChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ConfigurationChangeRequestAuditEventBuilder builder() {
+    return new ConfigurationChangeRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/CreateGroupRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for creating a group
+ */
+@Immutable
+public class CreateGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class CreateGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<CreateGroupRequestAuditEvent, CreateGroupRequestAuditEventBuilder> {
+
+    /**
+     * NAme of the created group
+     */
+    private String groupName;
+
+    public CreateGroupRequestAuditEventBuilder() {
+      super.withOperation("Group creation");
+    }
+
+    @Override
+    protected CreateGroupRequestAuditEvent newAuditEvent() {
+      return new CreateGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Group(")
+        .append(groupName)
+        .append(")");
+    }
+
+    public CreateGroupRequestAuditEventBuilder withGroupName(String groupName) {
+      this.groupName = groupName;
+      return this;
+    }
+
+  }
+
+  protected CreateGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected CreateGroupRequestAuditEvent(CreateGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link CreateGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static CreateGroupRequestAuditEventBuilder builder() {
+    return new CreateGroupRequestAuditEventBuilder();
+  }
+
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/CreateUserRequestAuditEvent.java

@@ -0,0 +1,113 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for creating a user
+ */
+@Immutable
+public class CreateUserRequestAuditEvent extends RequestAuditEvent {
+
+  public static class CreateUserRequestAuditEventBuilder extends RequestAuditEventBuilder<CreateUserRequestAuditEvent, CreateUserRequestAuditEventBuilder> {
+
+    /**
+     * Is the user admin
+     */
+    private boolean admin;
+
+    /**
+     * Is the user active
+     */
+    private boolean active;
+
+    /**
+     * Username
+     */
+    private String username;
+
+    public CreateUserRequestAuditEventBuilder() {
+      super.withOperation("User creation");
+    }
+
+    @Override
+    protected CreateUserRequestAuditEvent newAuditEvent() {
+      return new CreateUserRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Created Username(")
+        .append(username)
+        .append("), Active(")
+        .append(active ? "yes" : "no")
+        .append("), ")
+        .append("Administrator(")
+        .append(admin ? "yes" : "no")
+        .append(")");
+    }
+
+    public CreateUserRequestAuditEventBuilder withAdmin(boolean admin) {
+      this.admin = admin;
+      return this;
+    }
+
+    public CreateUserRequestAuditEventBuilder withActive(boolean active) {
+      this.active = active;
+      return this;
+    }
+
+    public CreateUserRequestAuditEventBuilder withCreatedUsername(String username) {
+      this.username = username;
+      return this;
+    }
+
+  }
+
+  protected CreateUserRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected CreateUserRequestAuditEvent(CreateUserRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link CreateUserRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static CreateUserRequestAuditEventBuilder builder() {
+    return new CreateUserRequestAuditEventBuilder();
+  }
+
+}

+ 86 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteAlertGroupRequestAuditEvent.java

@@ -0,0 +1,86 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/***
+ * Audit event for alert group deletion
+ */
+@Immutable
+public class DeleteAlertGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteAlertGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteAlertGroupRequestAuditEvent, DeleteAlertGroupRequestAuditEventBuilder> {
+
+    /**
+     * Alert group id
+     */
+    private String id;
+
+    public DeleteAlertGroupRequestAuditEventBuilder() {
+      super.withOperation("Alert group removal");
+    }
+
+    @Override
+    protected DeleteAlertGroupRequestAuditEvent newAuditEvent() {
+      return new DeleteAlertGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Alert group ID(")
+        .append(id)
+        .append(")");
+    }
+
+    public DeleteAlertGroupRequestAuditEventBuilder withId(String id) {
+      this.id = id;
+      return this;
+    }
+  }
+
+  protected DeleteAlertGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteAlertGroupRequestAuditEvent(DeleteAlertGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteAlertGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteAlertGroupRequestAuditEventBuilder builder() {
+    return new DeleteAlertGroupRequestAuditEventBuilder();
+  }
+
+}

+ 86 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteAlertTargetRequestAuditEvent.java

@@ -0,0 +1,86 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for deleting alert target (=notification)
+ */
+@Immutable
+public class DeleteAlertTargetRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteAlertTargetRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteAlertTargetRequestAuditEvent, DeleteAlertTargetRequestAuditEventBuilder> {
+
+    /**
+     * Alert target id
+     */
+    private String id;
+
+    public DeleteAlertTargetRequestAuditEventBuilder() {
+      super.withOperation("Notification removal");
+    }
+
+    @Override
+    protected DeleteAlertTargetRequestAuditEvent newAuditEvent() {
+      return new DeleteAlertTargetRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Notification ID(")
+        .append(id)
+        .append(")");
+    }
+
+    public DeleteAlertTargetRequestAuditEventBuilder withId(String id) {
+      this.id = id;
+      return this;
+    }
+  }
+
+  protected DeleteAlertTargetRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteAlertTargetRequestAuditEvent(DeleteAlertTargetRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteAlertTargetRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteAlertTargetRequestAuditEventBuilder builder() {
+    return new DeleteAlertTargetRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteBlueprintRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for blueprint deletion
+ */
+@Immutable
+public class DeleteBlueprintRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteBlueprintRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteBlueprintRequestAuditEvent, DeleteBlueprintRequestAuditEventBuilder> {
+
+    /**
+     * Name of the deleted blueprint
+     */
+    private String blueprintName;
+
+    public DeleteBlueprintRequestAuditEventBuilder() {
+      super.withOperation("Delete blueprint");
+    }
+
+    @Override
+    protected DeleteBlueprintRequestAuditEvent newAuditEvent() {
+      return new DeleteBlueprintRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Blueprint name(")
+        .append(blueprintName)
+        .append(")");
+    }
+
+    public DeleteBlueprintRequestAuditEventBuilder withBlueprintName(String blueprintName) {
+      this.blueprintName = blueprintName;
+      return this;
+    }
+
+  }
+
+  protected DeleteBlueprintRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteBlueprintRequestAuditEvent(DeleteBlueprintRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteBlueprintRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteBlueprintRequestAuditEventBuilder builder() {
+    return new DeleteBlueprintRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteGroupRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for group deletion
+ */
+@Immutable
+public class DeleteGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteGroupRequestAuditEvent, DeleteGroupRequestAuditEventBuilder> {
+
+    /**
+     * Name of the deleted group
+     */
+    private String groupName;
+
+    public DeleteGroupRequestAuditEventBuilder() {
+      super.withOperation("Group delete");
+    }
+
+    @Override
+    protected DeleteGroupRequestAuditEvent newAuditEvent() {
+      return new DeleteGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Group(")
+        .append(groupName)
+        .append(")");
+    }
+
+    public DeleteGroupRequestAuditEventBuilder withGroupName(String groupName) {
+      this.groupName = groupName;
+      return this;
+    }
+
+  }
+
+  protected DeleteGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteGroupRequestAuditEvent(DeleteGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteGroupRequestAuditEventBuilder builder() {
+    return new DeleteGroupRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteHostRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for deleting a host
+ */
+@Immutable
+public class DeleteHostRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteHostRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteHostRequestAuditEvent, DeleteHostRequestAuditEventBuilder> {
+
+    /**
+     * Name of the deleted host
+     */
+    private String hostName;
+
+    public DeleteHostRequestAuditEventBuilder() {
+      super.withOperation("Host deletion");
+    }
+
+    @Override
+    protected DeleteHostRequestAuditEvent newAuditEvent() {
+      return new DeleteHostRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Hostname(")
+        .append(hostName)
+        .append(")");
+    }
+
+    public DeleteHostRequestAuditEventBuilder withHostName(String groupName) {
+      this.hostName = groupName;
+      return this;
+    }
+
+  }
+
+  protected DeleteHostRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteHostRequestAuditEvent(DeleteHostRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteHostRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteHostRequestAuditEventBuilder builder() {
+    return new DeleteHostRequestAuditEventBuilder();
+  }
+
+}

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteRepositoryVersionRequestAuditEvent.java

@@ -0,0 +1,110 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for deleting a repository version
+ */
+@Immutable
+public class DeleteRepositoryVersionRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteRepositoryVersionAuditEventBuilder extends RequestAuditEventBuilder<DeleteRepositoryVersionRequestAuditEvent, DeleteRepositoryVersionAuditEventBuilder> {
+
+    /**
+     * Stack name
+     */
+    private String stackName;
+
+    /**
+     * Stack version
+     */
+    private String stackVersion;
+
+    /**
+     * Repository version
+     */
+    private String repoVersion;
+
+    public DeleteRepositoryVersionAuditEventBuilder() {
+      super.withOperation("Repository version removal");
+    }
+
+    @Override
+    protected DeleteRepositoryVersionRequestAuditEvent newAuditEvent() {
+      return new DeleteRepositoryVersionRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stack(")
+        .append(stackName)
+        .append("), Stack version(")
+        .append(stackVersion)
+        .append("), Repo version ID(")
+        .append(repoVersion)
+        .append(")");
+    }
+
+    public DeleteRepositoryVersionAuditEventBuilder withStackName(String stackName) {
+      this.stackName = stackName;
+      return this;
+    }
+
+    public DeleteRepositoryVersionAuditEventBuilder withStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+      return this;
+    }
+
+    public DeleteRepositoryVersionAuditEventBuilder withRepoVersion(String repoVersion) {
+      this.repoVersion = repoVersion;
+      return this;
+    }
+  }
+
+  protected DeleteRepositoryVersionRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteRepositoryVersionRequestAuditEvent(DeleteRepositoryVersionAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteRepositoryVersionRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteRepositoryVersionAuditEventBuilder builder() {
+    return new DeleteRepositoryVersionAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteServiceRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for service deletion
+ */
+@Immutable
+public class DeleteServiceRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteServiceRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteServiceRequestAuditEvent, DeleteServiceRequestAuditEventBuilder> {
+
+    /**
+     * Name of the deleted service
+     */
+    private String serviceName;
+
+    public DeleteServiceRequestAuditEventBuilder() {
+      super.withOperation("Service deletion");
+    }
+
+    @Override
+    protected DeleteServiceRequestAuditEvent newAuditEvent() {
+      return new DeleteServiceRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Service(")
+        .append(serviceName)
+        .append(")");
+    }
+
+    public DeleteServiceRequestAuditEventBuilder withService(String service) {
+      this.serviceName = service;
+      return this;
+    }
+
+  }
+
+  protected DeleteServiceRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteServiceRequestAuditEvent(DeleteServiceRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteServiceRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteServiceRequestAuditEventBuilder builder() {
+    return new DeleteServiceRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteUserRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for deleting a user
+ */
+@Immutable
+public class DeleteUserRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteUserRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteUserRequestAuditEvent, DeleteUserRequestAuditEventBuilder> {
+
+    /**
+     * Name of the deleted user
+     */
+    private String username;
+
+    public DeleteUserRequestAuditEventBuilder() {
+      super.withOperation("User delete");
+    }
+
+    @Override
+    protected DeleteUserRequestAuditEvent newAuditEvent() {
+      return new DeleteUserRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Deleted Username(")
+        .append(username)
+        .append(")");
+    }
+
+    public DeleteUserRequestAuditEventBuilder withDeletedUsername(String username) {
+      this.username = username;
+      return this;
+    }
+
+  }
+
+  protected DeleteUserRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteUserRequestAuditEvent(DeleteUserRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteUserRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteUserRequestAuditEventBuilder builder() {
+    return new DeleteUserRequestAuditEventBuilder();
+  }
+
+}

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/DeleteViewInstanceRequestAuditEvent.java

@@ -0,0 +1,110 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for deleting a view instance
+ */
+@Immutable
+public class DeleteViewInstanceRequestAuditEvent extends RequestAuditEvent {
+
+  public static class DeleteViewInstanceRequestAuditEventBuilder extends RequestAuditEventBuilder<DeleteViewInstanceRequestAuditEvent, DeleteViewInstanceRequestAuditEventBuilder> {
+
+    /**
+     * View instance name
+     */
+    private String name;
+
+    /**
+     * View instance type (Files, Tez, etc...)
+     */
+    private String type;
+
+    /**
+     * View instance version
+     */
+    private String version;
+
+    public DeleteViewInstanceRequestAuditEventBuilder() {
+      super.withOperation("View deletion");
+    }
+
+    @Override
+    protected DeleteViewInstanceRequestAuditEvent newAuditEvent() {
+      return new DeleteViewInstanceRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Type(")
+        .append(type)
+        .append("), Version(")
+        .append(version)
+        .append("), Name(")
+        .append(name)
+        .append(")");
+    }
+
+    public DeleteViewInstanceRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public DeleteViewInstanceRequestAuditEventBuilder withType(String type) {
+      this.type = type;
+      return this;
+    }
+
+    public DeleteViewInstanceRequestAuditEventBuilder withVersion(String version) {
+      this.version = version;
+      return this;
+    }
+  }
+
+  protected DeleteViewInstanceRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected DeleteViewInstanceRequestAuditEvent(DeleteViewInstanceRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link DeleteViewInstanceRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static DeleteViewInstanceRequestAuditEventBuilder builder() {
+    return new DeleteViewInstanceRequestAuditEventBuilder();
+  }
+
+}

+ 108 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/MembershipChangeRequestAuditEvent.java

@@ -0,0 +1,108 @@
+/*
+ * 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.event.request;
+
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for group membership change
+ */
+@Immutable
+public class MembershipChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddUserToGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<MembershipChangeRequestAuditEvent, AddUserToGroupRequestAuditEventBuilder> {
+
+    /**
+     * New list of users
+     */
+    private List<String> userNameList;
+
+    /**
+     * Group name
+     */
+    private String groupName;
+
+    public AddUserToGroupRequestAuditEventBuilder() {
+      super.withOperation("Membership change");
+    }
+
+    @Override
+    protected MembershipChangeRequestAuditEvent newAuditEvent() {
+      return new MembershipChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Group(")
+        .append(groupName)
+        .append("), Members(");
+
+      if (userNameList.isEmpty()) {
+        builder.append("<empty>");
+      }
+
+      StringUtils.join(userNameList, ", ");
+
+      builder.append(")");
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withUserNameList(List<String> users) {
+      this.userNameList = users;
+      return this;
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withGroupName(String groupName) {
+      this.groupName = groupName;
+      return this;
+    }
+
+  }
+
+  protected MembershipChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected MembershipChangeRequestAuditEvent(AddUserToGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link MembershipChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddUserToGroupRequestAuditEventBuilder builder() {
+    return new AddUserToGroupRequestAuditEventBuilder();
+  }
+
+}

+ 113 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/PrivilegeChangeRequestAuditEvent.java

@@ -0,0 +1,113 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for privilege change
+ */
+@Immutable
+public class PrivilegeChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class PrivilegeChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<PrivilegeChangeRequestAuditEvent, PrivilegeChangeRequestAuditEventBuilder> {
+
+    /**
+     * User name (this or group is set)
+     */
+    private String user;
+
+    /**
+     * Group name (this or user is set)
+     */
+    private String group;
+
+    /**
+     * Role for the user or group
+     */
+    private String role;
+
+    public PrivilegeChangeRequestAuditEventBuilder() {
+      super.withOperation("Role change");
+    }
+
+    @Override
+    protected PrivilegeChangeRequestAuditEvent newAuditEvent() {
+      return new PrivilegeChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Role(")
+        .append(role)
+        .append(")");
+
+      if (user != null) {
+        builder.append(", User(").append(user).append(")");
+      }
+      if (group != null) {
+        builder.append(", Group(").append(group).append(")");
+      }
+    }
+
+    public PrivilegeChangeRequestAuditEventBuilder withUser(String user) {
+      this.user = user;
+      return this;
+    }
+
+    public PrivilegeChangeRequestAuditEventBuilder withGroup(String group) {
+      this.group = group;
+      return this;
+    }
+
+    public PrivilegeChangeRequestAuditEventBuilder withRole(String role) {
+      this.role = role;
+      return this;
+    }
+  }
+
+  protected PrivilegeChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected PrivilegeChangeRequestAuditEvent(PrivilegeChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link PrivilegeChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static PrivilegeChangeRequestAuditEventBuilder builder() {
+    return new PrivilegeChangeRequestAuditEventBuilder();
+  }
+
+}

+ 98 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/RemoveUserFromGroupRequestAuditEvent.java

@@ -0,0 +1,98 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for removing a user from a group
+ */
+@Immutable
+public class RemoveUserFromGroupRequestAuditEvent extends RequestAuditEvent {
+
+  public static class AddUserToGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<RemoveUserFromGroupRequestAuditEvent, AddUserToGroupRequestAuditEventBuilder> {
+
+    /**
+     * Group name to remove from
+     */
+    private String groupName;
+
+    /**
+     * Name of the user that is removed
+     */
+    private String affectedUserName;
+
+    public AddUserToGroupRequestAuditEventBuilder() {
+      super.withOperation("User removal from group");
+    }
+
+    @Override
+    protected RemoveUserFromGroupRequestAuditEvent newAuditEvent() {
+      return new RemoveUserFromGroupRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Group(");
+      builder.append(groupName);
+      builder.append("), Affected username(");
+      builder.append(affectedUserName);
+      builder.append(")");
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withGroupName(String groupName) {
+      this.groupName = groupName;
+      return this;
+    }
+
+    public AddUserToGroupRequestAuditEventBuilder withAffectedUserName(String userName) {
+      this.affectedUserName = userName;
+      return this;
+    }
+  }
+
+  protected RemoveUserFromGroupRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected RemoveUserFromGroupRequestAuditEvent(AddUserToGroupRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link RemoveUserFromGroupRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static AddUserToGroupRequestAuditEventBuilder builder() {
+    return new AddUserToGroupRequestAuditEventBuilder();
+  }
+
+}

+ 126 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/StartOperationRequestAuditEvent.java

@@ -0,0 +1,126 @@
+/*
+ * 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.event.request;
+
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.event.AbstractUserAuditEvent;
+
+/**
+ * Start operation request was accepted.
+ */
+@Immutable
+public class StartOperationRequestAuditEvent extends AbstractUserAuditEvent {
+
+  public static class StartOperationAuditEventBuilder
+    extends AbstractUserAuditEventBuilder<StartOperationRequestAuditEvent, StartOperationAuditEventBuilder> {
+
+    /**
+     * Request id
+     */
+    private String requestId;
+
+    /**
+     * Reason of failure, if it is set, then the request is considered as failed
+     */
+    private String reasonOfFailure;
+
+    /**
+     * Description of the request
+     */
+    private String operation;
+
+    private StartOperationAuditEventBuilder() {
+    }
+
+    /**
+     * Appends to the audit event the identifier of the
+     * operation through whcih the operation progress can be tracked.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Operation(")
+        .append(operation)
+        .append("), RequestId(")
+        .append(requestId)
+        .append("), Status(")
+        .append(reasonOfFailure == null ? "Successfully queued" : "Failed to queue");
+
+      if (reasonOfFailure != null) {
+        builder.append("), Reason(")
+          .append(reasonOfFailure);
+      }
+      builder.append(")");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected StartOperationRequestAuditEvent newAuditEvent() {
+      return new StartOperationRequestAuditEvent(this);
+    }
+
+    /**
+     * Sets the identifier of the operation through which the operation progress can be tracked.
+     *
+     * @param requestId the identifier of the operation through which the operation progress can be tracked.
+     * @return this builder
+     */
+    public StartOperationAuditEventBuilder withRequestId(String requestId) {
+      this.requestId = requestId;
+      return this;
+    }
+
+    public StartOperationAuditEventBuilder withReasonOfFailure(String reasonOfFailure) {
+      this.reasonOfFailure = reasonOfFailure;
+      return this;
+    }
+
+    public StartOperationAuditEventBuilder withOperation(String operation) {
+      this.operation = operation;
+      return this;
+    }
+  }
+
+  private StartOperationRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  private StartOperationRequestAuditEvent(StartOperationAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link StartOperationRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static StartOperationAuditEventBuilder builder() {
+    return new StartOperationAuditEventBuilder();
+  }
+}

+ 134 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UpdateRepositoryRequestAuditEvent.java

@@ -0,0 +1,134 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for updating repository
+ */
+@Immutable
+public class UpdateRepositoryRequestAuditEvent extends RequestAuditEvent {
+
+  public static class UpdateRepositoryRequestAuditEventBuilder extends RequestAuditEventBuilder<UpdateRepositoryRequestAuditEvent, UpdateRepositoryRequestAuditEventBuilder> {
+
+    /**
+     * Repository name
+     */
+    private String repo;
+
+    /**
+     * Stack name
+     */
+    private String stackName;
+
+    /**
+     * Operating system type
+     */
+    private String osType;
+
+    /**
+     * Base url for the repository
+     */
+    private String baseUrl;
+
+    /**
+     * Stack version
+     */
+    private String stackVersion;
+
+    public UpdateRepositoryRequestAuditEventBuilder() {
+      super.withOperation("Repository update");
+    }
+
+    @Override
+    protected UpdateRepositoryRequestAuditEvent newAuditEvent() {
+      return new UpdateRepositoryRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stack(")
+        .append(stackName)
+        .append("), Stack version(")
+        .append(stackVersion)
+        .append("), OS(")
+        .append(osType)
+        .append("), Repo id(")
+        .append(repo)
+        .append("), Base URL(")
+        .append(baseUrl)
+        .append(")");
+    }
+
+    public UpdateRepositoryRequestAuditEventBuilder withRepo(String repo) {
+      this.repo = repo;
+      return this;
+    }
+
+    public UpdateRepositoryRequestAuditEventBuilder withStackName(String stackName) {
+      this.stackName = stackName;
+      return this;
+    }
+
+    public UpdateRepositoryRequestAuditEventBuilder withOsType(String osType) {
+      this.osType = osType;
+      return this;
+    }
+
+    public UpdateRepositoryRequestAuditEventBuilder withBaseUrl(String baseUrl) {
+      this.baseUrl = baseUrl;
+      return this;
+    }
+
+    public UpdateRepositoryRequestAuditEventBuilder withStackVersion(String stackVersion) {
+      this.stackVersion = stackVersion;
+      return this;
+    }
+  }
+
+  protected UpdateRepositoryRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected UpdateRepositoryRequestAuditEvent(UpdateRepositoryRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link UpdateRepositoryRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static UpdateRepositoryRequestAuditEventBuilder builder() {
+    return new UpdateRepositoryRequestAuditEventBuilder();
+  }
+
+}

+ 111 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UpdateUpgradeItemRequestAuditEvent.java

@@ -0,0 +1,111 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for updating an upgrade item
+ */
+@Immutable
+public class UpdateUpgradeItemRequestAuditEvent extends RequestAuditEvent {
+
+  public static class UpdateUpgradeItemRequestAuditEventBuilder extends RequestAuditEventBuilder<UpdateUpgradeItemRequestAuditEvent, UpdateUpgradeItemRequestAuditEventBuilder> {
+
+    /**
+     * Stage id
+     */
+    private String stageId;
+
+    /**
+     * Status
+     */
+    private String status;
+
+    /**
+     * Request id
+     */
+    private String requestId;
+
+
+    public UpdateUpgradeItemRequestAuditEventBuilder() {
+      super.withOperation("Action confirmation by the user");
+    }
+
+    @Override
+    protected UpdateUpgradeItemRequestAuditEvent newAuditEvent() {
+      return new UpdateUpgradeItemRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Stage id(")
+        .append(stageId)
+        .append("), Status(")
+        .append(status)
+        .append("), Request id(")
+        .append(requestId)
+        .append(")");
+    }
+
+    public UpdateUpgradeItemRequestAuditEventBuilder withStageId(String stageId) {
+      this.stageId = stageId;
+      return this;
+    }
+
+    public UpdateUpgradeItemRequestAuditEventBuilder withStatus(String status) {
+      this.status = status;
+      return this;
+    }
+
+    public UpdateUpgradeItemRequestAuditEventBuilder withRequestId(String requestId) {
+      this.requestId = requestId;
+      return this;
+    }
+  }
+
+  protected UpdateUpgradeItemRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected UpdateUpgradeItemRequestAuditEvent(UpdateUpgradeItemRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link UpdateUpgradeItemRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static UpdateUpgradeItemRequestAuditEventBuilder builder() {
+    return new UpdateUpgradeItemRequestAuditEventBuilder();
+  }
+
+}

+ 88 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/UserPasswordChangeRequestAuditEvent.java

@@ -0,0 +1,88 @@
+/*
+ * 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.event.request;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+
+/**
+ * Audit event for changing user password
+ */
+@Immutable
+public class UserPasswordChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class UserPasswordChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<UserPasswordChangeRequestAuditEvent, UserPasswordChangeRequestAuditEventBuilder> {
+
+    /**
+     * Name of the user whose password is changed
+     */
+    private String username;
+
+    public UserPasswordChangeRequestAuditEventBuilder() {
+      super.withOperation("Password change");
+    }
+
+    @Override
+    protected UserPasswordChangeRequestAuditEvent newAuditEvent() {
+      return new UserPasswordChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder
+        .append(", Affected username(")
+        .append(username)
+        .append(")");
+    }
+
+
+    public UserPasswordChangeRequestAuditEventBuilder withAffectedUsername(String username) {
+      this.username = username;
+      return this;
+    }
+  }
+
+  protected UserPasswordChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected UserPasswordChangeRequestAuditEvent(UserPasswordChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link UserPasswordChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static UserPasswordChangeRequestAuditEventBuilder builder() {
+    return new UserPasswordChangeRequestAuditEventBuilder();
+  }
+
+}

+ 163 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/ViewPrivilegeChangeRequestAuditEvent.java

@@ -0,0 +1,163 @@
+/*
+ * 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.event.request;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Audit event for changing view privilege
+ */
+@Immutable
+public class ViewPrivilegeChangeRequestAuditEvent extends RequestAuditEvent {
+
+  public static class ViewPrivilegeChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<ViewPrivilegeChangeRequestAuditEvent, ViewPrivilegeChangeRequestAuditEventBuilder> {
+
+    /**
+     * Users with their roles
+     */
+    private Map<String, List<String>> users;
+
+    /**
+     * Groups with their roles
+     */
+    private Map<String, List<String>> groups;
+
+    /**
+     * View name
+     */
+    private String name;
+
+    /**
+     * View type (Files, Tez, etc...)
+     */
+    private String type;
+
+    /**
+     * View version
+     */
+    private String version;
+
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder() {
+      super.withOperation("View permission change");
+    }
+
+    @Override
+    protected ViewPrivilegeChangeRequestAuditEvent newAuditEvent() {
+      return new ViewPrivilegeChangeRequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+
+      builder.append(", Type(")
+        .append(type)
+        .append("), Version(")
+        .append(version)
+        .append("), Name(")
+        .append(name)
+        .append(")");
+
+      Set<String> roleSet = new HashSet<String>();
+      roleSet.addAll(users.keySet());
+      roleSet.addAll(groups.keySet());
+
+      builder.append(", Permissions(");
+      if (!users.isEmpty() || !groups.isEmpty()) {
+        builder.append(System.lineSeparator());
+      }
+
+      List<String> lines = new LinkedList<String>();
+
+      for (String role : roleSet) {
+        lines.add(role + ": ");
+        if (users.get(role) != null && !users.get(role).isEmpty()) {
+          lines.add("  Users: " + StringUtils.join(users.get(role), ", "));
+        }
+        if (groups.get(role) != null && !groups.get(role).isEmpty()) {
+          lines.add("  Groups: " + StringUtils.join(groups.get(role), ", "));
+        }
+      }
+
+      builder.append(StringUtils.join(lines, System.lineSeparator()));
+
+      builder.append(")");
+    }
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder withName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder withType(String type) {
+      this.type = type;
+      return this;
+    }
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder withVersion(String version) {
+      this.version = version;
+      return this;
+    }
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder withUsers(Map<String, List<String>> users) {
+      this.users = users;
+      return this;
+    }
+
+    public ViewPrivilegeChangeRequestAuditEventBuilder withGroups(Map<String, List<String>> groups) {
+      this.groups = groups;
+      return this;
+    }
+  }
+
+  protected ViewPrivilegeChangeRequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected ViewPrivilegeChangeRequestAuditEvent(ViewPrivilegeChangeRequestAuditEventBuilder builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link ViewPrivilegeChangeRequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static ViewPrivilegeChangeRequestAuditEventBuilder builder() {
+    return new ViewPrivilegeChangeRequestAuditEventBuilder();
+  }
+
+}

+ 161 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditEvent.java

@@ -0,0 +1,161 @@
+/*
+ * 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 org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.ResultStatus;
+import org.apache.ambari.server.audit.event.AbstractUserAuditEvent;
+
+/**
+ * Base class for start operation audit events.
+ */
+public class RequestAuditEvent extends AbstractUserAuditEvent {
+
+  public static class RequestAuditEventBuilder<T extends RequestAuditEvent, TBuilder extends RequestAuditEventBuilder<T, TBuilder>> extends AbstractUserAuditEventBuilder<T, TBuilder> {
+
+    /**
+     * Request type (PUT, POST, DELETE, etc...)
+     */
+    private Request.Type requestType;
+
+    /**
+     * Result status, that contains http statuses (OK, ACCEPTED, FORBIDDEN, etc...)
+     */
+    private ResultStatus resultStatus;
+
+    /**
+     * The url that is called
+     */
+    private String url;
+
+    /**
+     * Description of the operation
+     */
+    private String operation;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected T newAuditEvent() {
+      return (T) new RequestAuditEvent(this);
+    }
+
+    /**
+     * Appends to the event the details of the incoming request.
+     *
+     * @param builder builder for the audit event details.
+     */
+    @Override
+    protected void buildAuditMessage(StringBuilder builder) {
+      super.buildAuditMessage(builder);
+      if (operation != null) {
+        builder
+          .append(", Operation(")
+          .append(operation)
+          .append(")");
+      }
+      builder
+        .append(", RequestType(")
+        .append(requestType)
+        .append("), ")
+        .append("url(")
+        .append(url)
+        .append("), ResultStatus(")
+        .append(resultStatus.getStatusCode())
+        .append(" ")
+        .append(resultStatus.getStatus())
+        .append(")");
+
+      if (resultStatus.isErrorState()) {
+        builder.append(", Reason(")
+          .append(resultStatus.getMessage())
+          .append(")");
+      }
+    }
+
+    /**
+     * Sets the request type to be added to the audit event.
+     *
+     * @param requestType request type to be added to the audit event.
+     * @return this builder
+     */
+    public TBuilder withRequestType(Request.Type requestType) {
+      this.requestType = requestType;
+
+      return (TBuilder) this;
+    }
+
+    /**
+     * Sets the url to be added to the audit event.
+     *
+     * @param url url to be added to the audit event.
+     * @return this builder
+     */
+    public TBuilder withUrl(String url) {
+      this.url = url;
+
+      return (TBuilder) this;
+    }
+
+    /**
+     * Sets the result status to be added to the audit event.
+     *
+     * @param resultStatus result status to be added to the audit event.
+     * @return this builder
+     */
+    public TBuilder withResultStatus(ResultStatus resultStatus) {
+      this.resultStatus = resultStatus;
+
+      return (TBuilder) this;
+    }
+
+    /**
+     * Sets the operation to be added to the audit event.
+     *
+     * @param operation operation to be added to the audit event.
+     * @return this builder
+     */
+    public TBuilder withOperation(String operation) {
+      this.operation = operation;
+
+      return (TBuilder) this;
+    }
+  }
+
+  protected RequestAuditEvent() {
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected RequestAuditEvent(RequestAuditEventBuilder<?, ?> builder) {
+    super(builder);
+  }
+
+  /**
+   * Returns an builder for {@link RequestAuditEvent}
+   *
+   * @return a builder instance
+   */
+  public static RequestAuditEventBuilder<?, ?> builder() {
+    return new RequestAuditEventBuilder();
+  }
+
+}

+ 59 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditEventCreator.java

@@ -0,0 +1,59 @@
+/*
+ * 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.event.AuditEvent;
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * This interface must be implemented by the plugins for the request audit logger
+ * in order to make custom {@link AuditEvent}s based on {@link org.apache.ambari.server.api.services.Request.Type}s
+ * and {@link org.apache.ambari.server.controller.spi.Resource.Type}
+ */
+public interface RequestAuditEventCreator {
+
+  /**
+   * @return the set of {@link org.apache.ambari.server.api.services.Request.Type}s that are handled by this creator
+   */
+  Set<Request.Type> getRequestTypes();
+
+  /**
+   * @return the {@link org.apache.ambari.server.controller.spi.Resource.Type}s that is handled by this creator
+   */
+  Set<Resource.Type> getResourceTypes();
+
+  /**
+   * @return the {@link ResultStatus}es that is handled by this creator
+   */
+  Set<ResultStatus.STATUS> getResultStatuses();
+
+  /**
+   * Creates and {@link AuditEvent}
+   * @param request HTTP request object
+   * @param result HTTP result object
+   * @return an {@link AuditEvent}
+   */
+  AuditEvent createAuditEvent(Request request, Result result);
+
+}

+ 36 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditLogger.java

@@ -0,0 +1,36 @@
+/*
+ * 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 org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.Result;
+
+/**
+ * Audit logger interface for logging requests
+ */
+public interface RequestAuditLogger {
+
+  /**
+   * Logs an audit event based on the http request and result
+   * @param request
+   * @param result
+   */
+  void log(Request request, Result result);
+
+}

+ 150 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/RequestAuditLoggerImpl.java

@@ -0,0 +1,150 @@
+/*
+ * 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.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);
+  }
+}

+ 170 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/AlertGroupEventCreator.java

@@ -0,0 +1,170 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddAlertGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.ChangeAlertGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteAlertGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles alert group requests
+ * For resource type {@link Resource.Type#AlertGroup}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class AlertGroupEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.AlertGroup).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddAlertGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withName(getName(request))
+          .withDefinitionIds(getDefinitionIds(request))
+          .withNotificationIds(getNotificationIds(request))
+          .build();
+      case PUT:
+        return ChangeAlertGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withName(getName(request))
+          .withDefinitionIds(getDefinitionIds(request))
+          .withNotificationIds(getNotificationIds(request))
+          .build();
+      case DELETE:
+        return DeleteAlertGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withId(request.getResource().getKeyValueMap().get(Resource.Type.AlertGroup))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns the alert group name from the request
+   * @param request
+   * @return
+   */
+  private String getName(Request request) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getNamedPropertySets().iterator().next().getProperties().get(PropertyHelper.getPropertyId("AlertGroup", "name")));
+    }
+    return null;
+  }
+
+  /**
+   * Returns definition ids from the request
+   * @param request
+   * @return
+   */
+  private List<String> getDefinitionIds(Request request) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      List<String> list = (List<String>) request.getBody().getNamedPropertySets().iterator().next().getProperties().get(PropertyHelper.getPropertyId("AlertGroup", "definitions"));
+      if (list != null) {
+        return list;
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  /**
+   * Returns notification ids from the request
+   * @param request
+   * @return
+   */
+  private List<String> getNotificationIds(Request request) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      List<String> list = (List<String>) request.getBody().getNamedPropertySets().iterator().next().getProperties().get(PropertyHelper.getPropertyId("AlertGroup", "targets"));
+      if (list != null) {
+        return list;
+      }
+    }
+    return Collections.emptyList();
+  }
+}

+ 164 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/AlertTargetEventCreator.java

@@ -0,0 +1,164 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Collections;
+import java.util.List;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddAlertTargetRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.ChangeAlertTargetRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteAlertTargetRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles alert target requests
+ * For resource type {@link Resource.Type#AlertTarget}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class AlertTargetEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.AlertTarget).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddAlertTargetRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withName(getProperty(request, "name"))
+          .withDescription(getProperty(request, "description"))
+          .withAlertStates(getPropertyList(request, "alert_states"))
+          .withGroupIds(getPropertyList(request, "groups"))
+          .withNotificationType(getProperty(request, "notification_type"))
+          .withEmailFrom(getProperty(request, "properties/mail.smtp.from"))
+          .withEmailRecipients(getPropertyList(request, "properties/ambari.dispatch.recipients"))
+          .build();
+      case PUT:
+        return ChangeAlertTargetRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withName(getProperty(request, "name"))
+          .withDescription(getProperty(request, "description"))
+          .withAlertStates(getPropertyList(request, "alert_states"))
+          .withGroupIds(getPropertyList(request, "groups"))
+          .withNotificationType(getProperty(request, "notification_type"))
+          .withEmailFrom(getProperty(request, "properties/mail.smtp.from"))
+          .withEmailRecipients(getPropertyList(request, "properties/ambari.dispatch.recipients"))
+          .build();
+      case DELETE:
+        return DeleteAlertTargetRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withId(request.getResource().getKeyValueMap().get(Resource.Type.AlertTarget))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns a property list from the request, named by the parameter propertyName
+   * @param request
+   * @param propertyName
+   * @return
+   */
+  private List<String> getPropertyList(Request request, String propertyName) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      List<String> list = (List<String>) request.getBody().getNamedPropertySets().iterator().next().getProperties().get(PropertyHelper.getPropertyId("AlertTarget", propertyName));
+      if (list != null) {
+        return list;
+      }
+    }
+    return Collections.emptyList();
+  }
+
+  /**
+   * Returns a property from the request, named by the parameter propertyName
+   * @param request
+   * @param propertyName
+   * @return
+   */
+  private String getProperty(Request request, String propertyName) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("AlertTarget", propertyName)));
+    }
+    return null;
+  }
+}

+ 109 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/BlueprintEventCreator.java

@@ -0,0 +1,109 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddBlueprintRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteBlueprintRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles blueprint add and remove requests
+ * For resource type {@link Resource.Type#Blueprint}
+ * and request types {@link Request.Type#POST} and {@link Request.Type#POST}
+ */
+public class BlueprintEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Blueprint).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddBlueprintRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withBlueprintName(request.getResource().getKeyValueMap().get(Resource.Type.Blueprint))
+          .build();
+      case DELETE:
+        return DeleteBlueprintRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withBlueprintName(request.getResource().getKeyValueMap().get(Resource.Type.Blueprint))
+          .build();
+      default:
+        return null;
+    }
+  }
+}

+ 94 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/BlueprintExportEventCreator.java

@@ -0,0 +1,94 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.BlueprintExportRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles blueprint export requests
+ * For resource type {@link Resource.Type#Cluster}
+ * and request types {@link Request.Type#GET}
+ */
+public class BlueprintExportEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.GET).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Cluster).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+    if (!request.getURI().contains("format=blueprint")) {
+      return null;
+    }
+    return BlueprintExportRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .build();
+  }
+}

+ 188 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ComponentEventCreator.java

@@ -0,0 +1,188 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.StartOperationRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.internal.RequestOperationLevel;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles operation requests (start, stop, install, etc)
+ * For resource type {@link org.apache.ambari.server.controller.spi.Resource.Type#HostComponent}
+ * and request types {@link org.apache.ambari.server.api.services.Request.Type#POST}, {@link org.apache.ambari.server.api.services.Request.Type#PUT} and {@link org.apache.ambari.server.api.services.Request.Type#DELETE}
+ */
+public class ComponentEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.HostComponent).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    // null makes this default
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    String operation = getOperation(request);
+
+    Long requestId = null;
+    if (containsRequestId(result)) {
+      requestId = getRequestId(result);
+    }
+
+    StartOperationRequestAuditEvent.StartOperationAuditEventBuilder auditEventBuilder = StartOperationRequestAuditEvent.builder()
+      .withOperation(operation)
+      .withUserName(username)
+      .withRemoteIp(request.getRemoteAddress())
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestId(String.valueOf(requestId));
+
+    if (result.getStatus().isErrorState()) {
+      auditEventBuilder.withReasonOfFailure(result.getStatus().getMessage());
+    }
+
+    return auditEventBuilder.build();
+  }
+
+  /**
+   * Generates operation name based on the request. It checks the operation level, the host name, the service name, the status
+   * and whether this is a maintenance mode switch change.
+   * @param request
+   * @return
+   */
+  private String getOperation(Request request) {
+    if (request.getRequestType() == Request.Type.DELETE) {
+      return "Delete component " + request.getResource().getKeyValueMap().get(Resource.Type.HostComponent);
+    }
+
+    if (request.getBody().getRequestInfoProperties().containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      String operation = "";
+      switch (request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+        case "CLUSTER":
+          for (Map<String, Object> map : request.getBody().getPropertySets()) {
+            if (map.containsKey(PropertyHelper.getPropertyId("HostRoles", "cluster_name"))) {
+              operation = String.valueOf(map.get(PropertyHelper.getPropertyId("HostRoles", "state"))) + ": all services"
+                + " on all hosts"
+                + (request.getBody().getQueryString().length() > 0 ? " that matches " + request.getBody().getQueryString() : "")
+                + " (" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID) + ")";
+              break;
+            }
+          }
+          break;
+        case "HOST":
+          for (Map<String, Object> map : request.getBody().getPropertySets()) {
+            if (map.containsKey(PropertyHelper.getPropertyId("HostRoles", "cluster_name"))) {
+              String query = request.getBody().getRequestInfoProperties().get("query");
+              operation = String.valueOf(map.get(PropertyHelper.getPropertyId("HostRoles", "state"))) + ": " + query.substring(query.indexOf("(") + 1, query.length() - 1)
+                + " on " + request.getBody().getRequestInfoProperties().get("operation_level/host_names")
+                + " (" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID) + ")";
+              break;
+            }
+          }
+          break;
+        case "HOST_COMPONENT":
+          for (Map<String, Object> map : request.getBody().getPropertySets()) {
+            if (map.containsKey(PropertyHelper.getPropertyId("HostRoles", "component_name"))) {
+              operation = String.valueOf(map.get(PropertyHelper.getPropertyId("HostRoles", "state"))) + ": " + String.valueOf(map.get(PropertyHelper.getPropertyId("HostRoles", "component_name")))
+                + "/" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_SERVICE_ID)
+                + " on " + request.getBody().getRequestInfoProperties().get("operation_level/host_name")
+                + " (" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID) + ")";
+              break;
+            }
+          }
+          break;
+      }
+      return operation;
+    }
+
+    for (Map<String, Object> map : request.getBody().getPropertySets()) {
+      if (map.containsKey(PropertyHelper.getPropertyId("HostRoles", "maintenance_state"))) {
+        return "Turn " + map.get(PropertyHelper.getPropertyId("HostRoles", "maintenance_state")) + " Maintenance Mode for " + map.get(PropertyHelper.getPropertyId("HostRoles", "component_name"));
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Returns request id from the result
+   * @param result
+   * @return
+   */
+  private Long getRequestId(Result result) {
+    return (Long) result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests").get("id");
+  }
+
+  /**
+   * Checks if request id can be found in the result
+   * @param result
+   * @return
+   */
+  private boolean containsRequestId(Result result) {
+    return result.getResultTree().getChild("request") != null
+      && result.getResultTree().getChild("request").getObject() != null
+      && result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests") != null
+      && result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests").get("id") != null;
+  }
+}

+ 150 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ConfigurationChangeEventCreator.java

@@ -0,0 +1,150 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.ClusterNameChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.ConfigurationChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles operation requests (start, stop, install, etc)
+ * For resource type {@link Resource.Type#HostComponent}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class ConfigurationChangeEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Cluster).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      Map<String, Object> map = request.getBody().getPropertySets().iterator().next();
+      if (map.size() == 1 && map.containsKey(PropertyHelper.getPropertyId("Clusters", "cluster_name"))) {
+        String newName = String.valueOf(map.get(PropertyHelper.getPropertyId("Clusters", "cluster_name")));
+        String oldName = request.getResource().getKeyValueMap().get(Resource.Type.Cluster);
+        return ClusterNameChangeRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withOldName(oldName)
+          .withNewName(newName)
+          .build();
+      }
+    }
+
+    return ConfigurationChangeRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withVersionNote(getServiceConfigVersionNote(result))
+      .withVersionNumber(getServiceConfigVersion(result))
+      .build();
+  }
+
+  /**
+   * Returns service configuration version from the result
+   * @param result
+   * @return
+   */
+  private String getServiceConfigVersion(Result result) {
+    Map<String, Object> map = getServiceConfigMap(result);
+    return map == null ? null : String.valueOf(map.get("service_config_version"));
+  }
+
+  /**
+   * Returns service configurationv ersion note from the result
+   * @param result
+   * @return
+   */
+  private String getServiceConfigVersionNote(Result result) {
+    Map<String, Object> map = getServiceConfigMap(result);
+    return map == null ? null : String.valueOf(map.get("service_config_version_note"));
+  }
+
+  /**
+   * Returns service configuration map from the result. This map contains version number and version info
+   * @param result
+   * @return
+   */
+  private Map<String, Object> getServiceConfigMap(Result result) {
+    if (result.getResultTree().getChild("resources") != null &&
+      !result.getResultTree().getChild("resources").getChildren().isEmpty() &&
+      result.getResultTree().getChild("resources").getChildren().iterator().next().getObject() != null) {
+      return result.getResultTree().getChild("resources").getChildren().iterator().next().getObject().getPropertiesMap().get("");
+    }
+    return null;
+  }
+
+}

+ 111 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/CredentialEventCreator.java

@@ -0,0 +1,111 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddCredentialRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles crednetial requests
+ * For resource type {@link Resource.Type#Upgrade}
+ * and request types {@link Request.Type#POST}
+ */
+public class CredentialEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Credential).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    return AddCredentialRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withClusterName(getProperty(request, "cluster_name"))
+      .withType(getProperty(request, "type"))
+      .withAlias(getProperty(request, "alias"))
+      .withPrincipal(getProperty(request, "principal"))
+      .build();
+
+  }
+
+  /**
+   * Returns a property from the resquest
+   * @param request
+   * @param propertyName
+   * @return
+   */
+  private String getProperty(Request request, String propertyName) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Credential", propertyName)));
+    }
+    return null;
+  }
+}

+ 89 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/DefaultEventCreator.java

@@ -0,0 +1,89 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.eventcreator;
+
+import java.util.EnumSet;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.audit.request.RequestAuditLogger;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Default creator for {@link RequestAuditLogger}
+ */
+public class DefaultEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link org.apache.ambari.server.api.services.Request.Type}s that are handled by this plugin
+   * In this case all {@link Request.Type}s are listed, except {@link Request.Type#GET}
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().addAll(EnumSet.complementOf(EnumSet.of(Request.Type.GET))).build();
+
+
+  /** {@inheritDoc} */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    // null makes this default
+    return null;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    // null makes this default
+    return null;
+  }
+
+  /**
+   * Creates a simple {@link AuditEvent} with the details of request and response
+   * @param request HTTP request object
+   * @param result HTTP result object
+   * @return
+   */
+  @Override
+  public AuditEvent createAuditEvent(final Request request, final Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    return RequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withUserName(username)
+      .withRemoteIp(request.getRemoteAddress())
+      .withRequestType(request.getRequestType())
+      .withUrl(request.getURI())
+      .withResultStatus(result.getStatus())
+      .build();
+  }
+
+}

+ 124 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/GroupEventCreator.java

@@ -0,0 +1,124 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.CreateGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles group requests
+ * For resource type {@link Resource.Type#Group}
+ * and request types {@link Request.Type#POST} and {@link Request.Type#DELETE}
+ */
+public class GroupEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Group).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return CreateGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withGroupName(getGroupName(request))
+          .build();
+      case DELETE:
+        return DeleteGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withGroupName(request.getResource().getKeyValueMap().get(Resource.Type.Group))
+          .build();
+      default:
+        break;
+    }
+    return null;
+  }
+
+  /**
+   * Returns group name from request
+   * @param request
+   * @return
+   */
+  private String getGroupName(Request request) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Groups", "group_name")));
+    }
+    return null;
+  }
+
+}

+ 167 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/HostEventCreator.java

@@ -0,0 +1,167 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddComponentToHostRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.AddHostRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteHostRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles host requests (add, delete, add component)
+ * For resource type {@link Resource.Type#HostComponent}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#DELETE} and {@link Request.Type#QUERY_POST}
+ */
+public class HostEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.QUERY_POST, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Host).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    // null makes this default
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case DELETE:
+        return DeleteHostRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withHostName(request.getResource().getKeyValueMap().get(Resource.Type.Host))
+          .build();
+      case POST:
+        return AddHostRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withHostName(getHostName(request))
+          .build();
+      case QUERY_POST:
+        return AddComponentToHostRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withHostName(getHostNameFromQuery(request))
+          .withComponent(getHostComponent(request))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns hostname from the request
+   * @param request
+   * @return
+   */
+  private String getHostName(Request request) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getNamedPropertySets().iterator().next().getProperties().get(PropertyHelper.getPropertyId("Hosts", "host_name")));
+    }
+    return null;
+  }
+
+  /**
+   * Returns component name from the request
+   * @param request
+   * @return
+   */
+  private String getHostComponent(Request request) {
+    if (!request.getBody().getNamedPropertySets().isEmpty()) {
+      Set<Map<String, String>> set = (Set<Map<String, String>>) request.getBody().getNamedPropertySets().iterator().next().getProperties().get("host_components");
+      if (set != null && !set.isEmpty()) {
+        return set.iterator().next().get(PropertyHelper.getPropertyId("HostRoles", "component_name"));
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns hostname from the query string of the request
+   * @param request
+   * @return
+   */
+  private String getHostNameFromQuery(Request request) {
+    final String key = PropertyHelper.getPropertyId("Hosts", "host_name");
+    if (request.getBody().getQueryString().contains(key)) {
+      String q = request.getBody().getQueryString();
+      int startIndex = q.indexOf(key) + key.length() + 1;
+      int endIndex = q.indexOf("&", startIndex) == -1 ? q.length() : q.indexOf("&", startIndex);
+      return q.substring(startIndex, endIndex);
+    }
+    return null;
+  }
+}

+ 175 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/MemberEventCreator.java

@@ -0,0 +1,175 @@
+/*
+ * 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.eventcreator;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddUserToGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.MembershipChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.RemoveUserFromGroupRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles member requests
+ * For resource type {@link Resource.Type#Member}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class MemberEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Member).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddUserToGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withAffectedUserName(getUserName(request))
+          .withGroupName(getGroupName(request))
+          .build();
+      case DELETE:
+        return RemoveUserFromGroupRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withAffectedUserName(getUserName(request))
+          .withGroupName(getGroupName(request))
+          .build();
+      case PUT:
+        return MembershipChangeRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withGroupName(getGroupNameForPut(request))
+          .withUserNameList(getUsers(request))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns users from the request
+   * @param request
+   * @return
+   */
+  private List<String> getUsers(Request request) {
+    List<String> users = new LinkedList<String>();
+
+    for (Map<String, Object> propertyMap : request.getBody().getPropertySets()) {
+      String userName = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("MemberInfo", "user_name")));
+      users.add(userName);
+    }
+    return users;
+  }
+
+  /**
+   * Returns target group name from the request. This is called when PUT request type is used.
+   * @param request
+   * @return
+   */
+  private String getGroupNameForPut(Request request) {
+
+    for (Map<String, Object> propertyMap : request.getBody().getPropertySets()) {
+      return String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("MemberInfo", "group_name")));
+    }
+    return null;
+  }
+
+  /**
+   * Returns username from the request
+   * @param request
+   * @return
+   */
+  private String getUserName(Request request) {
+    return request.getResource().getKeyValueMap().get(Resource.Type.Member);
+  }
+
+  /**
+   * Returns groupname from the request
+   * @param request
+   * @return
+   */
+  private String getGroupName(Request request) {
+    return request.getResource().getKeyValueMap().get(Resource.Type.Group);
+  }
+
+
+}

+ 147 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/PrivilegeEventCreator.java

@@ -0,0 +1,147 @@
+/*
+ * 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.eventcreator;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.ClusterPrivilegeChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.PrivilegeChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles privilege requests
+ * For resource type {@link Resource.Type#ClusterPrivilege}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT}
+ */
+public class PrivilegeEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.ClusterPrivilege).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    Map<String, List<String>> users = getEntities(request, "USER");
+    Map<String, List<String>> groups = getEntities(request, "GROUP");
+
+    switch (request.getRequestType()) {
+      case PUT:
+        return ClusterPrivilegeChangeRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withUsers(users)
+          .withGroups(groups)
+          .build();
+      case POST:
+        String role = users.isEmpty() ? (groups.isEmpty() ? null : groups.keySet().iterator().next()) : users.keySet().iterator().next();
+        return PrivilegeChangeRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withRole(role)
+          .withGroup(groups.get(role) == null ? null : groups.get(role).get(0))
+          .withUser(users.get(role) == null ? null : users.get(role).get(0))
+          .withOperation((users.isEmpty() ? (groups.isEmpty() ? "" : "Group ") : "User ") + "role change")
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Assembles entities from the request. The result can contain users or groups based on the value of type parameter
+   * @param request
+   * @param type
+   * @return a map of role -> [user|group] names
+   */
+  private Map<String, List<String>> getEntities(final Request request, final String type) {
+    Map<String, List<String>> entities = new HashMap<String, List<String>>();
+
+    for (Map<String, Object> propertyMap : request.getBody().getPropertySets()) {
+      String ptype = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "principal_type")));
+      if (type.equals(ptype)) {
+        String role = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "permission_name")));
+        String name = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "principal_name")));
+        if (!entities.containsKey(role)) {
+          entities.put(role, new LinkedList<String>());
+        }
+
+        entities.get(role).add(name);
+      }
+    }
+    return entities;
+  }
+
+}

+ 81 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RecommendationIgnoreEventCreator.java

@@ -0,0 +1,81 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator ignores recommendation post requests
+ * For resource type {@link Resource.Type#Recommendation}
+ * and request types {@link Request.Type#POST}
+ */
+public class RecommendationIgnoreEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Recommendation).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    // intentionally skipping this event
+    return null;
+  }
+}

+ 132 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryEventCreator.java

@@ -0,0 +1,132 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddRepositoryRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.UpdateRepositoryRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles privilege requests
+ * For resource type {@link Resource.Type#Repository}
+ * and request types {@link Request.Type#POST} and {@link Request.Type#PUT}
+ */
+public class RepositoryEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Repository).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddRepositoryRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withRepo(getProperty(request, PropertyHelper.getPropertyId("Repositories", "repo_id")))
+          .withStackName(getProperty(request, PropertyHelper.getPropertyId("Repositories", "stack_name")))
+          .withStackVersion(getProperty(request, PropertyHelper.getPropertyId("Repositories", "stack_version")))
+          .withOsType(getProperty(request, PropertyHelper.getPropertyId("Repositories", "os_type")))
+          .withBaseUrl(getProperty(request, PropertyHelper.getPropertyId("Repositories", "base_url")))
+          .build();
+      case PUT:
+        return UpdateRepositoryRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withRepo(getProperty(request, PropertyHelper.getPropertyId("Repositories", "repo_id")))
+          .withStackName(getProperty(request, PropertyHelper.getPropertyId("Repositories", "stack_name")))
+          .withStackVersion(getProperty(request, PropertyHelper.getPropertyId("Repositories", "stack_version")))
+          .withOsType(getProperty(request, PropertyHelper.getPropertyId("Repositories", "os_type")))
+          .withBaseUrl(getProperty(request, PropertyHelper.getPropertyId("Repositories", "base_url")))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns a property from the request based on the propertyId parameter
+   * @param request
+   * @param properyId
+   * @return
+   */
+  private String getProperty(Request request, String properyId) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(properyId));
+    }
+    return null;
+  }
+
+}

+ 215 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryVersionEventCreator.java

@@ -0,0 +1,215 @@
+/*
+ * 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.eventcreator;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddRepositoryVersionRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.ChangeRepositoryVersionRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteRepositoryVersionRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles privilege requests
+ * For resource type {@link Resource.Type#Repository}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class RepositoryVersionEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.RepositoryVersion).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddRepositoryVersionRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withStackName(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "stack_name")))
+          .withStackVersion(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "stack_version")))
+          .withDisplayName(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "display_name")))
+          .withRepoVersion(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "repository_version")))
+          .withRepos(getRepos(request))
+          .build();
+      case PUT:
+        return ChangeRepositoryVersionRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withStackName(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "stack_name")))
+          .withStackVersion(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "stack_version")))
+          .withDisplayName(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "display_name")))
+          .withRepoVersion(getProperty(request, PropertyHelper.getPropertyId("RepositoryVersions", "repository_version")))
+          .withRepos(getRepos(request))
+          .build();
+      case DELETE:
+        return DeleteRepositoryVersionRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withStackName(request.getResource().getKeyValueMap().get(Resource.Type.Stack))
+          .withStackVersion(request.getResource().getKeyValueMap().get(Resource.Type.StackVersion))
+          .withRepoVersion(request.getResource().getKeyValueMap().get(Resource.Type.RepositoryVersion))
+          .build();
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Assembles repositories from the request
+   * operating system -> list of repositories where the repository is a map of properties (repo_id, repo_name, base_url)
+   * @param request
+   * @return a map of repositories
+   */
+  private Map<String, List<Map<String, String>>> getRepos(Request request) {
+
+    Map<String, List<Map<String, String>>> result = new HashMap<String, List<Map<String, String>>>();
+
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      if (request.getBody().getPropertySets().iterator().next().get("operating_systems") instanceof Set) {
+        Set<Object> set = (Set<Object>) request.getBody().getPropertySets().iterator().next().get("operating_systems");
+
+        result = createResultForOperationSystems(set);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns repos for the set of operating systems
+   * @param set
+   * @return
+   */
+  private Map<String, List<Map<String, String>>> createResultForOperationSystems(Set<Object> set) {
+    Map<String, List<Map<String, String>>> result = new HashMap<String, List<Map<String, String>>>();
+    for (Object entry : set) {
+      if (entry instanceof Map) {
+        Map<String, Object> map = (Map<String, Object>) entry;
+        String osType = (String) map.get(PropertyHelper.getPropertyId("OperatingSystems", "os_type"));
+        if (!result.containsKey(osType)) {
+          result.put(osType, new LinkedList<Map<String, String>>());
+        }
+        if (map.get("repositories") instanceof Set) {
+          Set<Object> repos = (Set<Object>) map.get("repositories");
+          for (Object repo : repos) {
+            if (repo instanceof Map) {
+              Map<String, String> resultMap = buildResultRepo((Map<String, String>) repo);
+              result.get(osType).add(resultMap);
+            }
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns a map with the repository properties (repo_id, repo_name, base_url)
+   * @param repo
+   * @return
+   */
+  private Map<String, String> buildResultRepo(Map<String, String> repo) {
+    Map<String, String> m = repo;
+    String repoId = m.get(PropertyHelper.getPropertyId("Repositories", "repo_id"));
+    String repo_name = m.get(PropertyHelper.getPropertyId("Repositories", "repo_name"));
+    String baseUrl = m.get(PropertyHelper.getPropertyId("Repositories", "base_url"));
+    Map<String, String> resultMap = new HashMap<>();
+    resultMap.put("repo_id", repoId);
+    resultMap.put("repo_name", repo_name);
+    resultMap.put("base_url", baseUrl);
+    return resultMap;
+  }
+
+  /**
+   * Returns property from the request based on the propertyId parameter
+   * @param request
+   * @param properyId
+   * @return
+   */
+  private String getProperty(Request request, String properyId) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(properyId));
+    }
+    return null;
+  }
+
+
+}

+ 101 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RequestEventCreator.java

@@ -0,0 +1,101 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddRequestRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.internal.RequestOperationLevel;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles request type requests
+ * For resource type {@link Resource.Type#Request}
+ * and request types {@link Request.Type#POST}
+ */
+public class RequestEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Request).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    // null makes this default
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return AddRequestRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withCommand(request.getBody().getRequestInfoProperties().get("command"))
+          .withClusterName(request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID))
+          .build();
+      default:
+        return null;
+    }
+  }
+}

+ 92 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceConfigDownloadEventCreator.java

@@ -0,0 +1,92 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.ClientConfigDownloadRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles service config download requests
+ * For resource type {@link Resource.Type#Service}
+ * and request types {@link Request.Type#GET}
+ */
+public class ServiceConfigDownloadEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.GET).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.ClientConfig).build();
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+    return ClientConfigDownloadRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withService(request.getResource().getKeyValueMap().get(Resource.Type.Service))
+      .withComponent(request.getResource().getKeyValueMap().get(Resource.Type.Component))
+      .build();
+  }
+}

+ 179 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceEventCreator.java

@@ -0,0 +1,179 @@
+/*
+ * 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.eventcreator;
+
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteServiceRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.StartOperationRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.internal.RequestOperationLevel;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles operation requests (start, stop, install, etc)
+ * For resource type {@link Resource.Type#Service}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class ServiceEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Service).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    // null makes this default
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    if (request.getRequestType() == Request.Type.DELETE) {
+      return DeleteServiceRequestAuditEvent.builder()
+        .withTimestamp(System.currentTimeMillis())
+        .withRequestType(request.getRequestType())
+        .withResultStatus(result.getStatus())
+        .withUrl(request.getURI())
+        .withRemoteIp(request.getRemoteAddress())
+        .withUserName(username)
+        .withService(request.getResource().getKeyValueMap().get(Resource.Type.Service))
+        .build();
+    }
+
+    String operation = getOperation(request);
+
+    Long requestId = null;
+    if (containsRequestId(result)) {
+      requestId = getRequestId(result);
+    }
+
+    StartOperationRequestAuditEvent.StartOperationAuditEventBuilder auditEventBuilder = StartOperationRequestAuditEvent.builder()
+      .withOperation(operation)
+      .withUserName(username)
+      .withRemoteIp(request.getRemoteAddress())
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestId(String.valueOf(requestId));
+
+    if (result.getStatus().isErrorState()) {
+      auditEventBuilder.withReasonOfFailure(result.getStatus().getMessage());
+    }
+
+    return auditEventBuilder.build();
+  }
+
+  /**
+   * Generates operation name based on the request. It checks the operation level, the host name, the service name, the status
+   * and whether this is a maintenance mode switch change.
+   * @param request
+   * @return
+   */
+  private String getOperation(Request request) {
+    if (request.getBody().getRequestInfoProperties().containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      String operation = "";
+      if ("CLUSTER".equals(request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_LEVEL_ID))) {
+        for (Map<String, Object> map : request.getBody().getPropertySets()) {
+          if (map.containsKey(PropertyHelper.getPropertyId("ServiceInfo", "state"))) {
+            operation = String.valueOf(map.get(PropertyHelper.getPropertyId("ServiceInfo", "state"))) + ": all services"
+              + " (" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID) + ")";
+            break;
+          }
+        }
+      }
+      if ("SERVICE".equals(request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_LEVEL_ID))) {
+        for (Map<String, Object> map : request.getBody().getPropertySets()) {
+          if (map.containsKey(PropertyHelper.getPropertyId("ServiceInfo", "state"))) {
+            operation = String.valueOf(map.get(PropertyHelper.getPropertyId("ServiceInfo", "state"))) + ": " + map.get(PropertyHelper.getPropertyId("ServiceInfo", "service_name"))
+              + " (" + request.getBody().getRequestInfoProperties().get(RequestOperationLevel.OPERATION_CLUSTER_ID) + ")";
+            break;
+          }
+        }
+      }
+      return operation;
+    }
+
+    for (Map<String, Object> map : request.getBody().getPropertySets()) {
+      if (map.containsKey(PropertyHelper.getPropertyId("ServiceInfo", "maintenance_state"))) {
+        return "Turn " + map.get(PropertyHelper.getPropertyId("ServiceInfo", "maintenance_state")) + " Maintenance Mode for " + map.get(PropertyHelper.getPropertyId("ServiceInfo", "service_name"));
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns request id from the result
+   * @param result
+   * @return
+   */
+  private Long getRequestId(Result result) {
+    return (Long) result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests").get("id");
+  }
+
+  /**
+   * Checks if request id can be found in the result
+   * @param result
+   * @return
+   */
+  private boolean containsRequestId(Result result) {
+    return result.getResultTree().getChild("request") != null
+      && result.getResultTree().getChild("request").getObject() != null
+      && result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests") != null
+      && result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests").get("id") != null;
+  }
+}

+ 86 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UnauthorizedEventCreator.java

@@ -0,0 +1,86 @@
+/*
+ * 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.eventcreator;
+
+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.event.AccessUnauthorizedAuditEvent;
+import org.apache.ambari.server.audit.event.AuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles unauthorized actions
+ * For result status {@link ResultStatus.STATUS#UNAUTHORIZED} and {@link ResultStatus.STATUS#FORBIDDEN}
+ */
+public class UnauthorizedEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<ResultStatus.STATUS> statuses = ImmutableSet.<ResultStatus.STATUS>builder().add(ResultStatus.STATUS.UNAUTHORIZED, ResultStatus.STATUS.FORBIDDEN).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return statuses;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+    AccessUnauthorizedAuditEvent ae = AccessUnauthorizedAuditEvent.builder()
+      .withRemoteIp(request.getRemoteAddress())
+      .withResourcePath(request.getURI())
+      .withTimestamp(System.currentTimeMillis())
+      .withUserName(username)
+      .build();
+
+    return ae;
+  }
+}

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java

@@ -0,0 +1,110 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddUpgradeRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles upgrade requests
+ * For resource type {@link Resource.Type#Upgrade}
+ * and request types {@link Request.Type#POST}
+ */
+public class UpgradeEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Upgrade).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    return AddUpgradeRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withRepositoryVersion(getProperty(request, "repository_version"))
+      .withUpgradeType(getProperty(request, "upgrade_type"))
+      .withClusterName(getProperty(request, "cluster_name"))
+      .build();
+
+  }
+
+  /**
+   * Returns property from the request based on the propertyName parameter
+   * @param request
+   * @param propertyName
+   * @return
+   */
+  private String getProperty(Request request, String propertyName) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Upgrade", propertyName)));
+    }
+    return null;
+  }
+}

+ 110 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeItemEventCreator.java

@@ -0,0 +1,110 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.UpdateUpgradeItemRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles upgrade requests
+ * For resource type {@link Resource.Type#Upgrade}
+ * and request types {@link Request.Type#PUT}
+ */
+public class UpgradeItemEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.UpgradeItem).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    return UpdateUpgradeItemRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withStatus(getProperty(request, "status"))
+      .withStageId(getProperty(request, "stage_id"))
+      .withRequestId(getProperty(request, "request_id"))
+      .build();
+
+  }
+
+  /**
+   * Returns property from the request based on the propertyName parameter
+   * @param request
+   * @param propertyName
+   * @return
+   */
+  private String getProperty(Request request, String propertyName) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("UpgradeItem", propertyName)));
+    }
+    return null;
+  }
+}

+ 211 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UserEventCreator.java

@@ -0,0 +1,211 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.ActivateUserRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.AdminUserRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.CreateUserRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteUserRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.UserPasswordChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles user requests
+ * For resource type {@link Resource.Type#User}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class UserEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.User).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+      case POST:
+        return CreateUserRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withCreatedUsername(getUsername(request))
+          .withActive(isActive(request))
+          .withAdmin(isAdmin(request))
+          .build();
+      case DELETE:
+        return DeleteUserRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withDeletedUsername(request.getResource().getKeyValueMap().get(Resource.Type.User))
+          .build();
+      case PUT:
+        if (hasActive(request)) {
+          return ActivateUserRequestAuditEvent.builder()
+            .withTimestamp(System.currentTimeMillis())
+            .withRequestType(request.getRequestType())
+            .withResultStatus(result.getStatus())
+            .withUrl(request.getURI())
+            .withRemoteIp(request.getRemoteAddress())
+            .withUserName(username)
+            .withAffectedUsername(getUsername(request))
+            .withActive(isActive(request))
+            .build();
+        }
+        if (hasAdmin(request)) {
+          return AdminUserRequestAuditEvent.builder()
+            .withTimestamp(System.currentTimeMillis())
+            .withRequestType(request.getRequestType())
+            .withResultStatus(result.getStatus())
+            .withUrl(request.getURI())
+            .withRemoteIp(request.getRemoteAddress())
+            .withUserName(username)
+            .withAffectedUsername(getUsername(request))
+            .withAdmin(isAdmin(request))
+            .build();
+        }
+        if (hasOldPassword(request)) {
+          return UserPasswordChangeRequestAuditEvent.builder()
+            .withTimestamp(System.currentTimeMillis())
+            .withRequestType(request.getRequestType())
+            .withResultStatus(result.getStatus())
+            .withUrl(request.getURI())
+            .withRemoteIp(request.getRemoteAddress())
+            .withUserName(username)
+            .withAffectedUsername(getUsername(request))
+            .build();
+        }
+      default:
+        break;
+    }
+    return null;
+  }
+
+
+  /**
+   * Returns fromt he request if the user has admin rights
+   * @param request
+   * @return
+   */
+  private boolean isAdmin(Request request) {
+    return hasAdmin(request) && "true".equals(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Users", "admin")));
+  }
+
+  /**
+   * Returns from the request if the user is active
+   * @param request
+   * @return
+   */
+  private boolean isActive(Request request) {
+    return hasActive(request) && "true".equals(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Users", "active")));
+  }
+
+  /**
+   * Returns if the request contains admin property
+   * @param request
+   * @return
+   */
+  private boolean hasAdmin(Request request) {
+    return !request.getBody().getPropertySets().isEmpty() && request.getBody().getPropertySets().iterator().next().containsKey(PropertyHelper.getPropertyId("Users", "admin"));
+  }
+
+  /**
+   * Returns if the request contains active property
+   * @param request
+   * @return
+   */
+  private boolean hasActive(Request request) {
+    return !request.getBody().getPropertySets().isEmpty() && request.getBody().getPropertySets().iterator().next().containsKey(PropertyHelper.getPropertyId("Users", "active"));
+  }
+
+  /**
+   * Returns if the request contains old password field
+   * @param request
+   * @return
+   */
+  private boolean hasOldPassword(Request request) {
+    return !request.getBody().getPropertySets().isEmpty() && request.getBody().getPropertySets().iterator().next().containsKey(PropertyHelper.getPropertyId("Users", "old_password"));
+  }
+
+  /**
+   * Returns the username from the request
+   * @param request
+   * @return
+   */
+  private String getUsername(Request request) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(PropertyHelper.getPropertyId("Users", "user_name")));
+    }
+    return null;
+  }
+
+}

+ 81 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ValidationIgnoreEventCreator.java

@@ -0,0 +1,81 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator ignores validation post requests
+ * For resource type {@link Resource.Type#Validation}
+ * and request types {@link Request.Type#POST}
+ */
+public class ValidationIgnoreEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.POST).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.Validation).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    // intentionally skipping this event
+    return null;
+  }
+}

+ 149 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewInstanceEventCreator.java

@@ -0,0 +1,149 @@
+/*
+ * 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.eventcreator;
+
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.AddViewInstanceRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.ChangeViewInstanceRequestAuditEvent;
+import org.apache.ambari.server.audit.event.request.DeleteViewInstanceRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles view instance requests
+ * For resource type {@link Resource.Type#ViewInstance}
+ * and request types {@link Request.Type#POST}, {@link Request.Type#PUT} and {@link Request.Type#DELETE}
+ */
+public class ViewInstanceEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT, Request.Type.POST, Request.Type.DELETE).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.ViewInstance).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+    switch (request.getRequestType()) {
+
+      case POST:
+        return AddViewInstanceRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withType(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "view_name")))
+          .withVersion(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "version")))
+          .withName(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "instance_name")))
+          .withDisplayName(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "label")))
+          .withDescription(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "description")))
+          .build();
+
+      case PUT:
+        return ChangeViewInstanceRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withType(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "view_name")))
+          .withVersion(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "version")))
+          .withName(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "instance_name")))
+          .withDisplayName(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "label")))
+          .withDescription(getProperty(request, PropertyHelper.getPropertyId("ViewInstanceInfo", "description")))
+          .build();
+
+      case DELETE:
+        return DeleteViewInstanceRequestAuditEvent.builder()
+          .withTimestamp(System.currentTimeMillis())
+          .withRequestType(request.getRequestType())
+          .withResultStatus(result.getStatus())
+          .withUrl(request.getURI())
+          .withRemoteIp(request.getRemoteAddress())
+          .withUserName(username)
+          .withType(request.getResource().getKeyValueMap().get(Resource.Type.View))
+          .withVersion(request.getResource().getKeyValueMap().get(Resource.Type.ViewVersion))
+          .withName(request.getResource().getKeyValueMap().get(Resource.Type.ViewInstance))
+          .build();
+
+      default:
+        return null;
+    }
+  }
+
+  /**
+   * Returns property from the requet based on the propertyId parameter
+   * @param request
+   * @param properyId
+   * @return
+   */
+  private String getProperty(Request request, String properyId) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(properyId));
+    }
+    return null;
+  }
+
+}

+ 145 - 0
ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewPrivilegeEventCreator.java

@@ -0,0 +1,145 @@
+/*
+ * 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.eventcreator;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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.event.AuditEvent;
+import org.apache.ambari.server.audit.event.request.ViewPrivilegeChangeRequestAuditEvent;
+import org.apache.ambari.server.audit.request.RequestAuditEventCreator;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This creator handles view privilege requests
+ * For resource type {@link Resource.Type#ViewInstance}
+ * and request types {@link Request.Type#PUT}
+ */
+public class ViewPrivilegeEventCreator implements RequestAuditEventCreator {
+
+  /**
+   * Set of {@link Request.Type}s that are handled by this plugin
+   */
+  private Set<Request.Type> requestTypes = ImmutableSet.<Request.Type>builder().add(Request.Type.PUT).build();
+
+  /**
+   * Set of {@link Resource.Type}s that are handled by this plugin
+   */
+  private Set<Resource.Type> resourceTypes = ImmutableSet.<Resource.Type>builder().add(Resource.Type.ViewPrivilege).build();
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Request.Type> getRequestTypes() {
+    return requestTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<Resource.Type> getResourceTypes() {
+    return resourceTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Set<ResultStatus.STATUS> getResultStatuses() {
+    return null;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AuditEvent createAuditEvent(Request request, Result result) {
+    String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
+
+
+    Map<String, List<String>> users = getEntities(request, "USER");
+    Map<String, List<String>> groups = getEntities(request, "GROUP");
+
+    return ViewPrivilegeChangeRequestAuditEvent.builder()
+      .withTimestamp(System.currentTimeMillis())
+      .withRequestType(request.getRequestType())
+      .withResultStatus(result.getStatus())
+      .withUrl(request.getURI())
+      .withRemoteIp(request.getRemoteAddress())
+      .withUserName(username)
+      .withType(getProperty(request, PropertyHelper.getPropertyId("PrivilegeInfo", "view_name")))
+      .withVersion(getProperty(request, PropertyHelper.getPropertyId("PrivilegeInfo", "version")))
+      .withName(getProperty(request, PropertyHelper.getPropertyId("PrivilegeInfo", "instance_name")))
+      .withUsers(users)
+      .withGroups(groups)
+      .build();
+
+  }
+
+  /**
+   * Returns property from the request based on the propertyId parameter
+   * @param request
+   * @param properyId
+   * @return
+   */
+  private String getProperty(Request request, String properyId) {
+    if (!request.getBody().getPropertySets().isEmpty()) {
+      return String.valueOf(request.getBody().getPropertySets().iterator().next().get(properyId));
+    }
+    return null;
+  }
+
+  /**
+   * Assembles entities from the request. The result can contain users or groups based on the value of type parameter
+   * @param request
+   * @param type
+   * @return a map of role -> [user|group] names
+   */
+  private Map<String, List<String>> getEntities(final Request request, final String type) {
+    Map<String, List<String>> entities = new HashMap<String, List<String>>();
+
+    for (Map<String, Object> propertyMap : request.getBody().getPropertySets()) {
+      String ptype = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "principal_type")));
+      if (type.equals(ptype)) {
+        String role = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "permission_name")));
+        String name = String.valueOf(propertyMap.get(PropertyHelper.getPropertyId("PrivilegeInfo", "principal_name")));
+        if (!entities.containsKey(role)) {
+          entities.put(role, new LinkedList<String>());
+        }
+
+        entities.get(role).add(name);
+      }
+    }
+    return entities;
+  }
+
+}

+ 24 - 0
ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java

@@ -676,6 +676,17 @@ public class Configuration {
           "custom.oracle.jdbc.name", "custom.postgres.jdbc.name", "custom.mssql.jdbc.name", "custom.hsqldb.jdbc.name",
           "custom.sqlanywhere.jdbc.name"));
 
+  /**
+   * Main switch for audit log feature
+   */
+  private static final String AUDIT_LOG_ENABLED = "auditlog.enabled";
+
+  /**
+   * Audit logger capacity
+   */
+  private static final String AUDIT_LOGGER_CAPACITY = "auditlog.logger.capacity";
+  private static final int AUDIT_LOGGER_CAPACITY_DEFAULT = 10000;
+
   private static final Logger LOG = LoggerFactory.getLogger(
     Configuration.class);
 
@@ -2840,4 +2851,17 @@ public class Configuration {
   public String isAgentStackRetryOnInstallEnabled(){
     return properties.getProperty(AGENT_STACK_RETRY_ON_REPO_UNAVAILABILITY_KEY, AGENT_STACK_RETRY_ON_REPO_UNAVAILABILITY_DEFAULT);
   }
+
+  public boolean isAuditLogEnabled() {
+    return Boolean.parseBoolean(properties.getProperty(AUDIT_LOG_ENABLED,Boolean.TRUE.toString()));
+  }
+
+  /**
+   * @return the capacity of async audit logger
+   */
+  public int getAuditLoggerCapacity() {
+    return NumberUtils.toInt(
+      properties.getProperty(AUDIT_LOGGER_CAPACITY),
+      AUDIT_LOGGER_CAPACITY_DEFAULT);
+  }
 }

+ 29 - 12
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java

@@ -44,11 +44,17 @@ import org.apache.ambari.server.api.MethodOverrideFilter;
 import org.apache.ambari.server.api.UserNameOverrideFilter;
 import org.apache.ambari.server.api.rest.BootStrapResource;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.api.services.BaseService;
 import org.apache.ambari.server.api.services.KeyService;
+import org.apache.ambari.server.api.services.LogoutService;
 import org.apache.ambari.server.api.services.PersistKeyValueImpl;
 import org.apache.ambari.server.api.services.PersistKeyValueService;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorBlueprintProcessor;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
+import org.apache.ambari.server.audit.AuditLogger;
+import org.apache.ambari.server.audit.request.RequestAuditLogger;
+import org.apache.ambari.server.audit.AuditLoggerModule;
+import org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter;
 import org.apache.ambari.server.bootstrap.BootStrapImpl;
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
 import org.apache.ambari.server.configuration.Configuration;
@@ -92,6 +98,8 @@ import org.apache.ambari.server.security.SecurityFilter;
 import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
 import org.apache.ambari.server.security.authorization.AmbariLocalUserDetailsService;
+import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.authorization.internal.AmbariInternalAuthenticationProvider;
 import org.apache.ambari.server.security.authorization.jwt.JwtAuthenticationFilter;
@@ -99,6 +107,7 @@ import org.apache.ambari.server.security.ldap.AmbariLdapDataPopulator;
 import org.apache.ambari.server.security.unsecured.rest.CertificateDownload;
 import org.apache.ambari.server.security.unsecured.rest.CertificateSign;
 import org.apache.ambari.server.security.unsecured.rest.ConnectionInfo;
+import org.apache.ambari.server.serveraction.AbstractServerAction;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.topology.AmbariContext;
 import org.apache.ambari.server.topology.BlueprintFactory;
@@ -294,19 +303,25 @@ public class AmbariServer {
 
       factory.registerSingleton("guiceInjector", injector);
       factory.registerSingleton("passwordEncoder",
-          injector.getInstance(PasswordEncoder.class));
+        injector.getInstance(PasswordEncoder.class));
+      factory.registerSingleton("auditLogger",
+        injector.getInstance(AuditLogger.class));
+      factory.registerSingleton("permissionHelper",
+        injector.getInstance(PermissionHelper.class));
       factory.registerSingleton("ambariLocalUserService",
-          injector.getInstance(AmbariLocalUserDetailsService.class));
+        injector.getInstance(AmbariLocalUserDetailsService.class));
       factory.registerSingleton("ambariLdapAuthenticationProvider",
-          injector.getInstance(AmbariLdapAuthenticationProvider.class));
+        injector.getInstance(AmbariLdapAuthenticationProvider.class));
       factory.registerSingleton("ambariLdapDataPopulator",
-          injector.getInstance(AmbariLdapDataPopulator.class));
+        injector.getInstance(AmbariLdapDataPopulator.class));
       factory.registerSingleton("ambariAuthorizationFilter",
-          injector.getInstance(AmbariAuthorizationFilter.class));
+        injector.getInstance(AmbariAuthorizationFilter.class));
       factory.registerSingleton("ambariInternalAuthenticationProvider",
-          injector.getInstance(AmbariInternalAuthenticationProvider.class));
+        injector.getInstance(AmbariInternalAuthenticationProvider.class));
       factory.registerSingleton("ambariJwtAuthenticationFilter",
-          injector.getInstance(JwtAuthenticationFilter.class));
+        injector.getInstance(JwtAuthenticationFilter.class));
+      factory.registerSingleton("ambariAuthenticationFilter",
+        injector.getInstance(AmbariAuthenticationFilter.class));
 
       // Spring Security xml config depends on this Bean
       String[] contextLocations = {SPRING_CONTEXT_LOCATION};
@@ -698,9 +713,9 @@ public class AmbariServer {
     }
 
     LOG.info(
-        "Jetty is configuring {} with {} reserved acceptors/selectors and a total pool size of {} for {} processors.",
-        threadPoolName, acceptorThreads * 2, configuredThreadPoolSize,
-        Runtime.getRuntime().availableProcessors());
+      "Jetty is configuring {} with {} reserved acceptors/selectors and a total pool size of {} for {} processors.",
+      threadPoolName, acceptorThreads * 2, configuredThreadPoolSize,
+      Runtime.getRuntime().availableProcessors());
 
     final QueuedThreadPool qtp = server.getBean(QueuedThreadPool.class);
     qtp.setName(threadPoolName);
@@ -843,7 +858,7 @@ public class AmbariServer {
     StageUtils.setGson(injector.getInstance(Gson.class));
     StageUtils.setTopologyManager(injector.getInstance(TopologyManager.class));
     WorkflowJsonService.setDBProperties(
-        injector.getInstance(Configuration.class));
+      injector.getInstance(Configuration.class));
     SecurityFilter.init(injector.getInstance(Configuration.class));
     StackDefinedPropertyProvider.init(injector);
     AbstractControllerResourceProvider.init(injector.getInstance(ResourceProviderFactory.class));
@@ -872,6 +887,8 @@ public class AmbariServer {
     StackAdvisorBlueprintProcessor.init(injector.getInstance(StackAdvisorHelper.class));
     ThreadPoolEnabledPropertyProvider.init(injector.getInstance(Configuration.class));
 
+    BaseService.init(injector.getInstance(RequestAuditLogger.class));
+
     RetryHelper.init(configs.getOperationsRetryAttempts());
   }
 
@@ -909,7 +926,7 @@ public class AmbariServer {
   }
 
   public static void main(String[] args) throws Exception {
-    Injector injector = Guice.createInjector(new ControllerModule());
+    Injector injector = Guice.createInjector(new ControllerModule(), new AuditLoggerModule());
 
     AmbariServer server = null;
     try {

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است