From 85744c81b27a833db4a8089c90a4faeb98d8f349 Mon Sep 17 00:00:00 2001 From: Pamela Dragosh Date: Wed, 11 Dec 2019 10:00:21 -0500 Subject: Add optimization subscriber request Adding support for a preliminary request to pull subscriber details. The returned decision adds scope attributes for the original request. Fixed some checkstyle issues due to new checkstyle requirements. Issue-ID: POLICY-2066 Change-Id: Ief02d896ce33e4864bb20e9185b0d0f5eb254bfd Signed-off-by: Pamela Dragosh --- .../optimization/OptimizationPdpApplication.java | 132 ++++++++++++++- .../OptimizationPdpApplicationTranslator.java | 185 +++++++++++++++++++++ .../OptimizationSubscriberRequest.java | 113 +++++++++++++ 3 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTranslator.java create mode 100644 applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationSubscriberRequest.java (limited to 'applications/optimization/src/main') diff --git a/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java index c5a9e7cf..e921dce8 100644 --- a/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java +++ b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplication.java @@ -22,16 +22,27 @@ package org.onap.policy.xacml.pdp.application.optimization; +import com.att.research.xacml.api.Advice; +import com.att.research.xacml.api.AttributeAssignment; +import com.att.research.xacml.api.Decision; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.api.Result; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; import org.onap.policy.common.endpoints.parameters.RestServerParameters; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.models.decisions.concepts.DecisionResponse; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; import org.onap.policy.pdp.xacml.application.common.ToscaPolicyTranslator; import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; -import org.onap.policy.pdp.xacml.application.common.std.StdMatchableTranslator; import org.onap.policy.pdp.xacml.application.common.std.StdXacmlApplicationServiceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,8 +51,9 @@ public class OptimizationPdpApplication extends StdXacmlApplicationServiceProvid private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplication.class); private static final String STRING_VERSION100 = "1.0.0"; + private static final String RESOURCE_SUBSCRIBERNAME = "subscriberName"; - private StdMatchableTranslator translator = new StdMatchableTranslator(); + private OptimizationPdpApplicationTranslator translator = new OptimizationPdpApplicationTranslator(); private List supportedPolicyTypes = new ArrayList<>(); /** @@ -117,6 +129,63 @@ public class OptimizationPdpApplication extends StdXacmlApplicationServiceProvid return false; } + @Override + public Pair makeDecision(DecisionRequest request, + Map requestQueryParams) { + // + // Check if there are subject attributes for subscriber + // + if (hasSubscriberAttributes(request)) { + // + // We must do an initial request to pull subscriber attributes + // + LOGGER.info("Request Subscriber attributes"); + // + // Convert the request + // + DecisionRequest subscriberRequest = new DecisionRequest(request); + // + // Override the PolicyType to ensure we are only looking at Subscriber Policies + // + if (subscriberRequest.getResource().containsKey("policy-type")) { + subscriberRequest.getResource().remove("policy-type"); + } + subscriberRequest.getResource().put("policy-type", "onap.policies.optimization.service.SubscriberPolicy"); + // + // Convert to a XacmlRequest and get a decision + // + Response xacmlResponse = null; + try { + xacmlResponse = this.xacmlDecision(OptimizationSubscriberRequest.createInstance(subscriberRequest)); + } catch (XacmlApplicationException e) { + LOGGER.error("Could not create subscriberName request {}", e); + } + // + // Check the response for subscriber attributes and add them + // to the initial request. + // + if (! addSubscriberAttributes(xacmlResponse, request)) { + LOGGER.error("Failed to get subscriber attributes"); + // + // Convert to a DecisionResponse + // + return Pair.of(this.getTranslator().convertResponse(xacmlResponse), xacmlResponse); + } + } + // + // Convert to a XacmlRequest + // + Request xacmlRequest = this.getTranslator().convertRequest(request); + // + // Now get a decision + // + Response xacmlResponse = this.xacmlDecision(xacmlRequest); + // + // Convert to a DecisionResponse + // + return Pair.of(this.getTranslator().convertResponse(xacmlResponse), xacmlResponse); + } + @Override protected ToscaPolicyTranslator getTranslator(String type) { // @@ -125,4 +194,63 @@ public class OptimizationPdpApplication extends StdXacmlApplicationServiceProvid return translator; } + @SuppressWarnings("unchecked") + private boolean hasSubscriberAttributes(DecisionRequest request) { + return request.getContext() != null + && request.getContext().containsKey(RESOURCE_SUBSCRIBERNAME) + && request.getContext().get(RESOURCE_SUBSCRIBERNAME) instanceof List + && ! ((List) request.getContext().get(RESOURCE_SUBSCRIBERNAME)).isEmpty(); + } + + private boolean addSubscriberAttributes(Response xacmlResponse, DecisionRequest initialRequest) { + // + // Should only be one result + // + for (Result result : xacmlResponse.getResults()) { + // + // Check the result + // + if (result.getStatus().isOk() && result.getDecision().equals(Decision.PERMIT)) { + // + // Pull out the advice which has attributes + // + scanAdvice(result.getAssociatedAdvice(), initialRequest); + // + // PLD this is an assumption + // + return true; + } else { + LOGGER.error("XACML result not ok {} or Permit {}", result.getStatus(), result.getDecision()); + } + } + return false; + } + + @SuppressWarnings("unchecked") + private void scanAdvice(Collection adviceCollection, DecisionRequest initialRequest) { + // + // There really should only be one advice object + // + for (Advice advice : adviceCollection) { + // + // Look for the optimization specific advice + // + if (ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER.equals(advice.getId())) { + // + // Get the attributes and add them + for (AttributeAssignment attribute : advice.getAttributeAssignments()) { + // + // If this is subscriber role + // + if (ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_ROLE.equals(attribute.getAttributeId())) { + ((List) initialRequest.getResource().get("scope")).add(attribute.getAttributeValue() + .getValue().toString()); + } + } + } else { + LOGGER.error("Unsupported advice id {}", advice.getId()); + } + } + } + } diff --git a/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTranslator.java b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTranslator.java new file mode 100644 index 00000000..7ec8f676 --- /dev/null +++ b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationPdpApplicationTranslator.java @@ -0,0 +1,185 @@ +/*- + * ============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.optimization; + +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.util.XACMLPolicyWriter; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType; +import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionsType; +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.PolicyType; +import org.apache.commons.lang3.StringUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +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.ToscaPolicyTranslatorUtils; +import org.onap.policy.pdp.xacml.application.common.std.StdMatchableTranslator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OptimizationPdpApplicationTranslator extends StdMatchableTranslator { + private static final Logger LOGGER = LoggerFactory.getLogger(OptimizationPdpApplicationTranslator.class); + + private static final String OPTIMIZATION_POLICYTYPE_SUBSCRIBER = + "onap.policies.optimization.service.SubscriberPolicy"; + + @SuppressWarnings("unchecked") + @Override + public PolicyType convertPolicy(ToscaPolicy toscaPolicy) throws ToscaPolicyConversionException { + // + // Have our superclass do the work + // + PolicyType policy = super.convertPolicy(toscaPolicy); + // + // Check if this is the subscriber policy + // + if (OPTIMIZATION_POLICYTYPE_SUBSCRIBER.equals(toscaPolicy.getType())) { + // + // Ensure the policy has the subscriber properties + // + Map subscriberProperties = (Map) toscaPolicy.getProperties() + .get("subscriberProperties"); + if (subscriberProperties == null) { + throw new ToscaPolicyConversionException("Missing subscriberProperties from subscriber policy"); + } + // + // Add subscriber name to the target so the policy + // only matches for the given subscriberName. + // + addSubscriberNameIntoTarget(policy, subscriberProperties); + // + // Add subscriber advice + // + policy.setAdviceExpressions(generateSubscriberAdvice(toscaPolicy, subscriberProperties)); + // + // Dump our revised policy out + // + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + XACMLPolicyWriter.writePolicyFile(os, policy); + LOGGER.info("{}", os); + } catch (IOException e) { + LOGGER.error("Failed to create byte array stream", e); + } + } + return policy; + } + + @SuppressWarnings("unchecked") + private static PolicyType addSubscriberNameIntoTarget(PolicyType policy, + Map subscriberProperties) throws ToscaPolicyConversionException { + // + // Find the subscriber names + // + Object subscriberNames = subscriberProperties.get("subscriberName"); + if (subscriberNames == null) { + throw new ToscaPolicyConversionException("Missing subscriberName property"); + } + // + // Iterate through all the subscriber names + // + AnyOfType anyOf = new AnyOfType(); + for (Object subscriberName : subscriberNames instanceof Collection ? (List) subscriberNames : + Arrays.asList(subscriberNames)) { + + MatchType match = ToscaPolicyTranslatorUtils.buildMatchTypeDesignator( + XACML3.ID_FUNCTION_STRING_EQUAL, + subscriberName, + XACML3.ID_DATATYPE_STRING, + ToscaDictionary.ID_SUBJECT_OPTIMIZATION_SUBSCRIBER_NAME, + XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT); + + anyOf.getAllOf().add(ToscaPolicyTranslatorUtils.buildAllOf(match)); + } + // + // Add to the target + // + policy.getTarget().getAnyOf().add(anyOf); + // + // Return for convenience + // + return policy; + } + + @SuppressWarnings("unchecked") + private static AdviceExpressionsType generateSubscriberAdvice(ToscaPolicy toscaPolicy, + Map subscriberProperties) throws ToscaPolicyConversionException { + // + // Get the subscriber role + // + Object role = subscriberProperties.get("subscriberRole"); + if (role == null || StringUtils.isBlank(role.toString())) { + throw new ToscaPolicyConversionException("Missing subscriberRole"); + } + // + // Get the provision status + // TODO + // + // Our subscriber Advice expression holds all the attribute assignments + // + AdviceExpressionType adviceExpression = new AdviceExpressionType(); + adviceExpression.setAppliesTo(EffectType.PERMIT); + adviceExpression.setAdviceId(ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER.stringValue()); + // + // Add in subscriber role + // + generateSubscriberRoleAdvice(adviceExpression, role instanceof Collection ? (List) role : + Arrays.asList(role)); + + AdviceExpressionsType adviceExpressions = new AdviceExpressionsType(); + adviceExpressions.getAdviceExpression().add(adviceExpression); + + return adviceExpressions; + } + + private static AdviceExpressionType generateSubscriberRoleAdvice(AdviceExpressionType adviceExpression, + Collection subscriberRoles) { + for (Object subscriberRole : subscriberRoles) { + AttributeValueType value = new AttributeValueType(); + value.setDataType(XACML3.ID_DATATYPE_STRING.stringValue()); + value.getContent().add(subscriberRole.toString()); + + AttributeAssignmentExpressionType assignment = new AttributeAssignmentExpressionType(); + assignment.setAttributeId(ToscaDictionary.ID_ADVICE_OPTIMIZATION_SUBSCRIBER_ROLE.stringValue()); + assignment.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT.stringValue()); + assignment.setExpression(new ObjectFactory().createAttributeValue(value)); + + adviceExpression.getAttributeAssignmentExpression().add(assignment); + + } + // + // Return for convenience + // + return adviceExpression; + } +} diff --git a/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationSubscriberRequest.java b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationSubscriberRequest.java new file mode 100644 index 00000000..b1028e89 --- /dev/null +++ b/applications/optimization/src/main/java/org/onap/policy/xacml/pdp/application/optimization/OptimizationSubscriberRequest.java @@ -0,0 +1,113 @@ +/*- + * ============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.optimization; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.DataTypeFactory; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.XACML3; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.StdMutableRequest; +import com.att.research.xacml.std.StdMutableRequestAttributes; +import com.att.research.xacml.std.annotations.XACMLSubject; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.onap.policy.models.decisions.concepts.DecisionRequest; +import org.onap.policy.pdp.xacml.application.common.ToscaDictionary; +import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException; +import org.onap.policy.pdp.xacml.application.common.std.StdMatchablePolicyRequest; + +public class OptimizationSubscriberRequest extends StdMatchablePolicyRequest { + + @XACMLSubject(attributeId = "urn:org:onap:optimization:subscriber:name", includeInResults = true) + List subscriberRoles; + + /** + * Create an instance of xacml request. + * + * @param decisionRequest Incoming DecisionRequest object + * @return XACML request + * @throws XacmlApplicationException XacmlApplicationException + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Request createInstance(DecisionRequest decisionRequest) throws XacmlApplicationException { + Request request = StdMatchablePolicyRequest.createInstance(decisionRequest); + + // + // Add in the context attributes + // + StdMutableRequest mutableRequest = new StdMutableRequest(request); + StdMutableRequestAttributes contextAttributes = new StdMutableRequestAttributes(); + contextAttributes.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT); + // + // Add the context attributes + // + Map contexts = decisionRequest.getContext(); + for (Entry entrySet : contexts.entrySet()) { + try { + if (entrySet.getValue() instanceof Collection) { + addSubject(contextAttributes, (Collection) entrySet.getValue(), + ToscaDictionary.ID_SUBJECT_OPTIMIZATION_SUBSCRIBER_NAME); + } else { + addSubject(contextAttributes, Arrays.asList(entrySet.getValue().toString()), + ToscaDictionary.ID_SUBJECT_OPTIMIZATION_SUBSCRIBER_NAME); + } + } catch (DataTypeException e) { + throw new XacmlApplicationException("Failed to add resource ", e); + } + } + mutableRequest.add(contextAttributes); + return mutableRequest; + } + + protected static StdMutableRequestAttributes addSubject(StdMutableRequestAttributes attributes, + Collection values, Identifier id) throws DataTypeException { + + DataTypeFactory factory = getDataTypeFactory(); + if (factory == null) { + return null; + } + for (Object value : values) { + StdMutableAttribute mutableAttribute = new StdMutableAttribute(); + mutableAttribute.setCategory(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT); + mutableAttribute.setAttributeId(id); + mutableAttribute.setIncludeInResults(true); + + DataType dataTypeExtended = factory.getDataType(XACML3.ID_DATATYPE_STRING); + AttributeValue attributeValue = dataTypeExtended.createAttributeValue(value); + Collection> attributeValues = new ArrayList<>(); + attributeValues.add(attributeValue); + mutableAttribute.setValues(attributeValues); + + attributes.add(mutableAttribute); + } + return attributes; + } +} -- cgit 1.2.3-korg