http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/RemoveUserFromGroupRequestAuditEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/RemoveUserFromGroupRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/RemoveUserFromGroupRequestAuditEvent.java new file mode 100644 index 0000000..0176dad --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/RemoveUserFromGroupRequestAuditEvent.java @@ -0,0 +1,85 @@ +/* + * 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.event; + +import org.apache.ambari.server.audit.event.request.RequestAuditEvent; + +public class RemoveUserFromGroupRequestAuditEvent extends RequestAuditEvent { + + public static class AddUserToGroupRequestAuditEventBuilder extends RequestAuditEventBuilder<RemoveUserFromGroupRequestAuditEvent, AddUserToGroupRequestAuditEventBuilder> { + + private String groupName; + 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(); + } + +}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateRepositoryRequestAuditEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateRepositoryRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateRepositoryRequestAuditEvent.java new file mode 100644 index 0000000..0959cd5 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateRepositoryRequestAuditEvent.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.event; + +import org.apache.ambari.server.audit.event.request.RequestAuditEvent; + +public class UpdateRepositoryRequestAuditEvent extends RequestAuditEvent { + + public static class UpdateRepositoryRequestAuditEventBuilder extends RequestAuditEventBuilder<UpdateRepositoryRequestAuditEvent, UpdateRepositoryRequestAuditEventBuilder> { + + private String repo; + + private String stackName; + + private String osType; + + private String baseUrl; + + 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(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateUpgradeItemRequestAuditEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateUpgradeItemRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateUpgradeItemRequestAuditEvent.java new file mode 100644 index 0000000..62e7333 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UpdateUpgradeItemRequestAuditEvent.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.event.request.event; + +import org.apache.ambari.server.audit.event.request.RequestAuditEvent; + +public class UpdateUpgradeItemRequestAuditEvent extends RequestAuditEvent { + + public static class UpdateUpgradeItemRequestAuditEventBuilder extends RequestAuditEventBuilder<UpdateUpgradeItemRequestAuditEvent, UpdateUpgradeItemRequestAuditEventBuilder> { + + private String stageId; + private String status; + 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(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UserPasswordChangeRequestAuditEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UserPasswordChangeRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UserPasswordChangeRequestAuditEvent.java new file mode 100644 index 0000000..4923e74 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/UserPasswordChangeRequestAuditEvent.java @@ -0,0 +1,79 @@ +/* + * 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.event; + +import org.apache.ambari.server.audit.event.request.RequestAuditEvent; + +public class UserPasswordChangeRequestAuditEvent extends RequestAuditEvent { + + public static class UserPasswordChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<UserPasswordChangeRequestAuditEvent, UserPasswordChangeRequestAuditEventBuilder> { + + 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(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/ViewPrivilegeChangeRequestAuditEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/ViewPrivilegeChangeRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/ViewPrivilegeChangeRequestAuditEvent.java new file mode 100644 index 0000000..ae129b1 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/event/ViewPrivilegeChangeRequestAuditEvent.java @@ -0,0 +1,141 @@ +/* + * 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.event; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.audit.event.request.RequestAuditEvent; +import org.apache.commons.lang.StringUtils; + +public class ViewPrivilegeChangeRequestAuditEvent extends RequestAuditEvent { + + public static class ViewPrivilegeChangeRequestAuditEventBuilder extends RequestAuditEventBuilder<ViewPrivilegeChangeRequestAuditEvent, ViewPrivilegeChangeRequestAuditEventBuilder> { + + private Map<String, List<String>> users; + private Map<String, List<String>> groups; + + private String name; + + private String type; + + 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(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertGroupEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertGroupEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertGroupEventCreator.java new file mode 100644 index 0000000..61079fc --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertGroupEventCreator.java @@ -0,0 +1,152 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddAlertGroupRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.ChangeAlertGroupRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.DeleteAlertGroupRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.AlertGroup); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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(DateTime.now()) + .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; + } + } + + 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; + } + + 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(); + } + + 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(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertTargetEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertTargetEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertTargetEventCreator.java new file mode 100644 index 0000000..973aa0d --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/AlertTargetEventCreator.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.event.request.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddAlertTargetRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.ChangeAlertTargetRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.DeleteAlertTargetRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.AlertTarget); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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(DateTime.now()) + .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; + } + } + + 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(); + } + + 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; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintEventCreator.java new file mode 100644 index 0000000..ba469d9 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintEventCreator.java @@ -0,0 +1,107 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddBlueprintRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.DeleteBlueprintRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Blueprint); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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; + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintExportEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintExportEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintExportEventCreator.java new file mode 100644 index 0000000..077a072 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/BlueprintExportEventCreator.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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.BlueprintExportRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.GET); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Cluster); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .build(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ComponentEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ComponentEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ComponentEventCreator.java new file mode 100644 index 0000000..86464dd --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ComponentEventCreator.java @@ -0,0 +1,176 @@ +/* + * 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.eventcreator; + +import java.util.HashSet; +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.StartOperationAuditEvent; +import org.apache.ambari.server.audit.event.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.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 org.apache.ambari.server.api.services.Request.Type}s that are handled by this plugin + */ + private Set<Request.Type> requestTypes = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.DELETE); + } + + private Set<Resource.Type> resourceTypes = new HashSet<Resource.Type>(); + + { + resourceTypes.add(Resource.Type.HostComponent); + } + + /** + * {@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; + } + + @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); + } + + StartOperationAuditEvent.StartOperationAuditEventBuilder auditEventBuilder = StartOperationAuditEvent.builder() + .withOperation(operation) + .withUserName(username) + .withRemoteIp(request.getRemoteAddress()) + .withTimestamp(DateTime.now()) + .withRequestId(String.valueOf(requestId)); + + if (result.getStatus().isErrorState()) { + auditEventBuilder.withReasonOfFailure(result.getStatus().getMessage()); + } + + return auditEventBuilder.build(); + } + + 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_names") + + " (" + 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; + } + + private Long getRequestId(Result result) { + return (Long) result.getResultTree().getChild("request").getObject().getPropertiesMap().get("Requests").get("id"); + } + + 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/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ConfigurationChangeEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ConfigurationChangeEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ConfigurationChangeEventCreator.java new file mode 100644 index 0000000..0f37510 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/ConfigurationChangeEventCreator.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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.ClusterNameChangeRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.ConfigurationChangeRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Cluster); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .withOldName(oldName) + .withNewName(newName) + .build(); + } + } + + return ConfigurationChangeRequestAuditEvent.builder() + .withTimestamp(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .withVersionNote(getServiceConfigVersionNote(result)) + .withVersionNumber(getServiceConfigVersion(result)) + .build(); + } + + private String getServiceConfigVersion(Result result) { + Map<String, Object> map = getServiceConfigMap(result); + return map == null ? null : String.valueOf(map.get("service_config_version")); + } + + private String getServiceConfigVersionNote(Result result) { + Map<String, Object> map = getServiceConfigMap(result); + return map == null ? null : String.valueOf(map.get("service_config_version_note")); + } + + 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; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/CredentialEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/CredentialEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/CredentialEventCreator.java new file mode 100644 index 0000000..1f38371 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/CredentialEventCreator.java @@ -0,0 +1,102 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddCredentialRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Credential); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @Override + public AuditEvent createAuditEvent(Request request, Result result) { + String username = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername(); + + return AddCredentialRequestAuditEvent.builder() + .withTimestamp(DateTime.now()) + .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(); + + } + + 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; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/DefaultEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/DefaultEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/DefaultEventCreator.java new file mode 100644 index 0000000..49a17c1 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/DefaultEventCreator.java @@ -0,0 +1,95 @@ +/** + * 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.event.request.eventcreator; + +import java.util.Arrays; +import java.util.HashSet; +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.RequestAuditEvent; +import org.apache.ambari.server.audit.event.request.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.RequestAuditLogger; +import org.apache.ambari.server.controller.spi.Resource; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +import com.google.inject.Singleton; + +/** + * Default creator for {@link RequestAuditLogger} + */ +@Singleton +public class DefaultEventCreator implements RequestAuditEventCreator { + + /** + * Set of {@link org.apache.ambari.server.api.services.Request.Type}s that are handled by this plugin + */ + private Set<Request.Type> requestTypes = new HashSet<Request.Type>(); + + { + requestTypes.addAll(Arrays.asList(Request.Type.values())); + requestTypes.remove(Request.Type.GET); // get is not handled by default + } + + /** {@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(DateTime.now()) + .withUserName(username) + .withRemoteIp(request.getRemoteAddress()) + .withRequestType(request.getRequestType()) + .withUrl(request.getURI()) + .withResultStatus(result.getStatus()) + .build(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/GroupEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/GroupEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/GroupEventCreator.java new file mode 100644 index 0000000..edeb251 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/GroupEventCreator.java @@ -0,0 +1,117 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.CreateGroupRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.DeleteGroupRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Group); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .withGroupName(getGroupName(request)) + .build(); + case DELETE: + return DeleteGroupRequestAuditEvent.builder() + .withTimestamp(DateTime.now()) + .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; + } + + 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; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/HostEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/HostEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/HostEventCreator.java new file mode 100644 index 0000000..9eaa5d4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/HostEventCreator.java @@ -0,0 +1,156 @@ +/* + * 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.eventcreator; + +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddComponentToHostRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.AddHostRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.DeleteHostRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + requestTypes.add(Request.Type.QUERY_POST); + } + + private Set<Resource.Type> resourceTypes = new HashSet<Resource.Type>(); + + { + resourceTypes.add(Resource.Type.Host); + } + + /** + * {@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; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .withHostName(getHostNameFromQuery(request)) + .withComponent(getHostComponent(request)) + .build(); + default: + return null; + } + } + + 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; + } + + 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; + } + + 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; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/MemberEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/MemberEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/MemberEventCreator.java new file mode 100644 index 0000000..75c72a4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/MemberEventCreator.java @@ -0,0 +1,154 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.AddUserToGroupRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.MembershipChangeRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.RemoveUserFromGroupRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.POST); + requestTypes.add(Request.Type.DELETE); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.Member); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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(DateTime.now()) + .withRequestType(request.getRequestType()) + .withResultStatus(result.getStatus()) + .withUrl(request.getURI()) + .withRemoteIp(request.getRemoteAddress()) + .withUserName(username) + .withGroupName(getGroupNameForPut(request)) + .withUserNameList(getUsers(request)) + .build(); + default: + return null; + } + } + + 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; + } + + 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; + } + + private String getUserName(Request request) { + return request.getResource().getKeyValueMap().get(Resource.Type.Member); + } + + private String getGroupName(Request request) { + return request.getResource().getKeyValueMap().get(Resource.Type.Group); + } + + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/1b1b3bc6/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/PrivilegeEventCreator.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/PrivilegeEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/PrivilegeEventCreator.java new file mode 100644 index 0000000..6c7cd69 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/eventcreator/PrivilegeEventCreator.java @@ -0,0 +1,139 @@ +/* + * 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.eventcreator; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +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.RequestAuditEventCreator; +import org.apache.ambari.server.audit.event.request.event.ClusterPrivilegeChangeRequestAuditEvent; +import org.apache.ambari.server.audit.event.request.event.PrivilegeChangeRequestAuditEvent; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.joda.time.DateTime; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; + +/** + * 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 = new HashSet<Request.Type>(); + + { + requestTypes.add(Request.Type.PUT); + requestTypes.add(Request.Type.POST); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Request.Type> getRequestTypes() { + return requestTypes; + } + + /** + * {@inheritDoc} + */ + @Override + public Set<Resource.Type> getResourceTypes() { + return Collections.singleton(Resource.Type.ClusterPrivilege); + } + + /** + * {@inheritDoc} + */ + @Override + public Set<ResultStatus.STATUS> getResultStatuses() { + return null; + } + + @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(DateTime.now()) + .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(DateTime.now()) + .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; + } + } + + 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; + } + +}
