You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by st...@apache.org on 2016/03/30 21:51:17 UTC

[3/7] ambari git commit: AMBARI-15241. Basic Operational Audit Logging. (Daniel Gergely via stoader)

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RecommendationIgnoreEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RecommendationIgnoreEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RecommendationIgnoreEventCreator.java
new file mode 100644
index 0000000..6b7bb2b
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryEventCreator.java
new file mode 100644
index 0000000..fe6f8cc
--- /dev/null
+++ b/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;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryVersionEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryVersionEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RepositoryVersionEventCreator.java
new file mode 100644
index 0000000..7c9c731
--- /dev/null
+++ b/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;
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RequestEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RequestEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/RequestEventCreator.java
new file mode 100644
index 0000000..fd13973
--- /dev/null
+++ b/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;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceConfigDownloadEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceConfigDownloadEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceConfigDownloadEventCreator.java
new file mode 100644
index 0000000..681cfb8
--- /dev/null
+++ b/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();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ServiceEventCreator.java
new file mode 100644
index 0000000..2e2b91d
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UnauthorizedEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UnauthorizedEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UnauthorizedEventCreator.java
new file mode 100644
index 0000000..d53aa68
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
new file mode 100644
index 0000000..b8a6873
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeItemEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeItemEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeItemEventCreator.java
new file mode 100644
index 0000000..9f83172
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UserEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UserEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UserEventCreator.java
new file mode 100644
index 0000000..2b4e5c1
--- /dev/null
+++ b/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;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ValidationIgnoreEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ValidationIgnoreEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ValidationIgnoreEventCreator.java
new file mode 100644
index 0000000..081f3d3
--- /dev/null
+++ b/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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewInstanceEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewInstanceEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewInstanceEventCreator.java
new file mode 100644
index 0000000..611b1ea
--- /dev/null
+++ b/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;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewPrivilegeEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewPrivilegeEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/ViewPrivilegeEventCreator.java
new file mode 100644
index 0000000..18b860a
--- /dev/null
+++ b/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;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 0302b6e..7767fb2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/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);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 4b769e3..5802f08 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/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 {

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index daca64d..91d6b4d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -377,7 +377,6 @@ public class ControllerModule extends AbstractModule {
     registerUpgradeChecks();
   }
 
-
   // ----- helper methods ----------------------------------------------------
 
   private PersistModule buildJpaPersistModule() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/46a34ccd/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CalculatedStatus.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CalculatedStatus.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CalculatedStatus.java
index 985e9ad..3a86aef 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CalculatedStatus.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/CalculatedStatus.java
@@ -376,7 +376,7 @@ public class CalculatedStatus {
    *
    * @return summary request status based on statuses of tasks in different states.
    */
-  private static HostRoleStatus calculateSummaryStatusOfStage(Map<HostRoleStatus, Integer> counters,
+  public static HostRoleStatus calculateSummaryStatusOfStage(Map<HostRoleStatus, Integer> counters,
       int total, boolean skippable) {
     if (counters.get(HostRoleStatus.PENDING) == total) {
       return HostRoleStatus.PENDING;