/*
* 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 java.util.SortedMap;
import java.util.TreeMap;
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.controller.internal.OperatingSystemResourceProvider;
import org.apache.ambari.server.controller.internal.RepositoryResourceProvider;
import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider;
import org.apache.ambari.server.controller.spi.Resource;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* 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) {
switch (request.getRequestType()) {
case POST:
return AddRepositoryVersionRequestAuditEvent.builder()
.withTimestamp(System.currentTimeMillis())
.withRequestType(request.getRequestType())
.withResultStatus(result.getStatus())
.withUrl(request.getURI())
.withRemoteIp(request.getRemoteAddress())
.withStackName(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID))
.withStackVersion(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID))
.withDisplayName(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID))
.withRepoVersion(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORY_VERSION_PROPERTY_ID))
.withRepos(getRepos(request))
.build();
case PUT:
return ChangeRepositoryVersionRequestAuditEvent.builder()
.withTimestamp(System.currentTimeMillis())
.withRequestType(request.getRequestType())
.withResultStatus(result.getStatus())
.withUrl(request.getURI())
.withRemoteIp(request.getRemoteAddress())
.withStackName(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_NAME_PROPERTY_ID))
.withStackVersion(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_STACK_VERSION_PROPERTY_ID))
.withDisplayName(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_DISPLAY_NAME_PROPERTY_ID))
.withRepoVersion(RequestAuditEventCreatorHelper.getProperty(request, RepositoryVersionResourceProvider.REPOSITORY_VERSION_REPOSITORY_VERSION_PROPERTY_ID))
.withRepos(getRepos(request))
.build();
case DELETE:
return DeleteRepositoryVersionRequestAuditEvent.builder()
.withTimestamp(System.currentTimeMillis())
.withRequestType(request.getRequestType())
.withResultStatus(result.getStatus())
.withUrl(request.getURI())
.withRemoteIp(request.getRemoteAddress())
.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 SortedMap<String, List<Map<String, String>>> getRepos(Request request) {
SortedMap<String, List<Map<String, String>>> result = new TreeMap<>();
Map<String, Object> first = Iterables.getFirst(request.getBody().getPropertySets(), null);
if (first != null && first.get("operating_systems") instanceof Set) {
Set<?> set = (Set<?>) first.get("operating_systems");
result = createResultForOperationSystems(set);
}
return result;
}
/**
* Returns repos for the set of operating systems
* @param set
* @return
*/
private SortedMap<String, List<Map<String, String>>> createResultForOperationSystems(Set<?> set) {
SortedMap<String, List<Map<String, String>>> result = new TreeMap<>();
for (Object entry : set) {
if (entry instanceof Map) {
Map<?, ?> map = (Map<?, ?>) entry;
String osType = (String) map.get(OperatingSystemResourceProvider.OPERATING_SYSTEM_OS_TYPE_PROPERTY_ID);
if (!result.containsKey(osType)) {
result.put(osType, new LinkedList<Map<String, String>>());
}
if (map.get("repositories") instanceof Set) {
Set<?> repos = (Set<?>) 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(RepositoryResourceProvider.REPOSITORY_REPO_ID_PROPERTY_ID);
String repo_name = m.get(RepositoryResourceProvider.REPOSITORY_REPO_NAME_PROPERTY_ID);
String baseUrl = m.get(RepositoryResourceProvider.REPOSITORY_BASE_URL_PROPERTY_ID);
Map<String, String> resultMap = new HashMap<>();
resultMap.put("repo_id", repoId);
resultMap.put("repo_name", repo_name);
resultMap.put("base_url", baseUrl);
return resultMap;
}
}