/*-
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
* Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed 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.
*
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
package org.onap.policy.xacml.pdp.application.monitoring;
import com.att.research.xacml.api.AttributeAssignment;
import com.att.research.xacml.api.DataTypeException;
import com.att.research.xacml.api.Decision;
import com.att.research.xacml.api.Obligation;
import com.att.research.xacml.api.Request;
import com.att.research.xacml.api.Response;
import com.att.research.xacml.api.Result;
import com.att.research.xacml.api.XACML3;
import com.att.research.xacml.api.pdp.PDPEngine;
import com.att.research.xacml.api.pdp.PDPException;
import com.att.research.xacml.std.annotations.RequestParser;
import com.att.research.xacml.util.XACMLPolicyScanner;
import com.att.research.xacml.util.XACMLPolicyWriter;
import com.att.research.xacml.util.XACMLProperties;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOfType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.MatchType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionsType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.RuleType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.TargetType;
import org.json.JSONObject;
import org.onap.policy.models.decisions.concepts.DecisionRequest;
import org.onap.policy.models.decisions.concepts.DecisionResponse;
import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConversionException;
import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConverter;
import org.onap.policy.pdp.xacml.application.common.ToscaPolicyConverterUtils;
import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
/**
* This is the engine class that manages the instance of the XACML PDP engine.
*
*
It is responsible for initializing it and shutting it down properly in a thread-safe manner.
*
*
* @author pameladragosh
*
*/
public class MonitoringPdpApplication implements ToscaPolicyConverter, XacmlApplicationServiceProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringPdpApplication.class);
private static final String ONAP_MONITORING_BASE_POLICY_TYPE = "onap.Monitoring";
private static final String ONAP_MONITORING_DERIVED_POLICY_TYPE = "onap.policies.monitoring";
private Path pathForData = null;
private Properties pdpProperties = null;
private PDPEngine pdpEngine = null;
private Map supportedPolicyTypes = new HashMap<>();
/**
* Constructor.
*/
public MonitoringPdpApplication() {
//
// By default this supports just Monitoring policy types
//
supportedPolicyTypes.put(ONAP_MONITORING_BASE_POLICY_TYPE, "1.0.0");
}
@Override
public String applicationName() {
return "Monitoring Application";
}
@Override
public List actionDecisionsSupported() {
return Arrays.asList("configure");
}
@Override
public synchronized void initialize(Path pathForData) {
//
// Save our path
//
this.pathForData = pathForData;
LOGGER.debug("New Path is {}", this.pathForData.toAbsolutePath());
//
// Look for and load the properties object
//
try {
pdpProperties = XacmlPolicyUtils.loadXacmlProperties(XacmlPolicyUtils.getPropertiesPath(pathForData));
LOGGER.debug("{}", pdpProperties);
} catch (IOException e) {
LOGGER.error("{}", e);
}
//
// Create an engine
//
PDPEngine newEngine = XacmlPolicyUtils.createEngine(pdpProperties);
if (newEngine != null) {
pdpEngine = newEngine;
}
}
@Override
public synchronized List supportedPolicyTypes() {
return Lists.newArrayList(supportedPolicyTypes.keySet());
}
@Override
public boolean canSupportPolicyType(String policyType, String policyTypeVersion) {
//
// For Monitoring, we will attempt to support all versions
// of the policy type. Since we are only packaging a decision
// back with a JSON payload of the property contents.
//
return (policyType.equals(ONAP_MONITORING_BASE_POLICY_TYPE)
|| policyType.startsWith(ONAP_MONITORING_DERIVED_POLICY_TYPE));
}
@Override
public synchronized void loadPolicies(Map toscaPolicies) {
try {
//
// Convert the policies first
//
List listPolicies = this.convertPolicies(toscaPolicies);
if (listPolicies.isEmpty()) {
throw new ToscaPolicyConversionException("Converted 0 policies");
}
//
// Read in our Root Policy
//
Set roots = XACMLProperties.getRootPolicyIDs(pdpProperties);
if (roots.isEmpty()) {
throw new ToscaPolicyConversionException("There are NO root policies defined");
}
//
// Really only should be one
//
String rootFile = pdpProperties.getProperty(roots.iterator().next() + ".file");
try (InputStream is = new FileInputStream(rootFile)) {
//
// Read the Root Policy into memory
//
Object policyData = XACMLPolicyScanner.readPolicy(is);
//
// Should be a PolicySet
//
if (policyData instanceof PolicySetType) {
//
// Add the referenced policies into a new Root Policy
//
PolicyType[] newPolicies = listPolicies.toArray(new PolicyType[listPolicies.size()]);
PolicySetType newRootPolicy = XacmlPolicyUtils.addPoliciesToXacmlRootPolicy(
(PolicySetType) policyData, newPolicies);
LOGGER.debug("New ROOT Policy");
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
XACMLPolicyWriter.writePolicyFile(os, newRootPolicy);
LOGGER.debug("{}", os);
} catch (IOException e) {
LOGGER.error("Failed to convert {}", e);
}
//
// Save the new Policies to disk
//
for (PolicyType policy : newPolicies) {
//
// Construct the filename
//
Path refPath = XacmlPolicyUtils.constructUniquePolicyFilename(policy, pathForData);
//
// Write the policy to disk
// Maybe check for an error
//
XACMLPolicyWriter.writePolicyFile(refPath, policy);
//
// Save it off
//
XacmlPolicyUtils.addReferencedPolicy(pdpProperties, refPath);
}
//
// Save the root policy to disk
//
XACMLPolicyWriter.writePolicyFile(Paths.get(rootFile), newRootPolicy);
//
// Write the policies to disk
//
XacmlPolicyUtils.storeXacmlProperties(pdpProperties,
XacmlPolicyUtils.getPropertiesPath(pathForData));
//
// Reload the engine
//
PDPEngine newEngine = XacmlPolicyUtils.createEngine(pdpProperties);
if (newEngine != null) {
pdpEngine = newEngine;
}
} else {
throw new ToscaPolicyConversionException("Root policy isn't a PolicySet");
}
}
} catch (IOException | ToscaPolicyConversionException e) {
LOGGER.error("Failed to loadPolicies {}", e);
}
}
@Override
public synchronized DecisionResponse makeDecision(DecisionRequest request) {
//
// Convert to a XacmlRequest
//
Request xacmlRequest = this.convertRequest(request);
//
// Now get a decision
//
Response xacmlResponse = this.xacmlDecision(xacmlRequest);
//
// Convert to a DecisionResponse
//
return this.convertResponse(xacmlResponse);
}
@Override
public List convertPolicies(Map toscaObject) throws ToscaPolicyConversionException {
//
// Return the policies
//
return scanAndConvertPolicies(toscaObject);
}
@Override
public List convertPolicies(InputStream isToscaPolicy) throws ToscaPolicyConversionException {
//
// Have snakeyaml parse the object
//
Yaml yaml = new Yaml();
Map toscaObject = yaml.load(isToscaPolicy);
//
// Return the policies
//
return scanAndConvertPolicies(toscaObject);
}
@SuppressWarnings("unchecked")
private List scanAndConvertPolicies(Map toscaObject)
throws ToscaPolicyConversionException {
//
// Our return object
//
List scannedPolicies = new ArrayList<>();
//
// Iterate each of the Policies
//
List