From ae2b058a7756cbc4eadd7700159e9d8e76050c35 Mon Sep 17 00:00:00 2001 From: Chenfei Gao Date: Tue, 10 Mar 2020 16:13:17 -0400 Subject: Added support for application/xacml+json in native app Issue-ID: POLICY-2182 Change-Id: I13246e08afdc2f5a380b5737c72851f271211d46 Signed-off-by: Chenfei Gao --- .../serialization/XacmlJsonMessageBodyHandler.java | 8 ++-- .../pdpx/main/startstop/XacmlPdpRestServer.java | 4 +- .../onap/policy/pdpx/main/rest/TestDecision.java | 37 ++++++++-------- .../TestXacmlJsonMessageBodyHandler.java | 50 ++++++++++++++++++++-- .../decisions/decision.native.request.json | 41 ++++++++++++++++++ 5 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 main/src/test/resources/decisions/decision.native.request.json diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonMessageBodyHandler.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonMessageBodyHandler.java index 6bf2efd3..9b59a003 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonMessageBodyHandler.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/serialization/XacmlJsonMessageBodyHandler.java @@ -22,6 +22,8 @@ package org.onap.policy.pdpx.main.rest.serialization; import com.att.research.xacml.api.Request; import com.att.research.xacml.api.Response; +import com.att.research.xacml.std.json.JsonRequestTranslator; +import com.att.research.xacml.std.json.JsonResponseTranslator; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -60,8 +62,7 @@ public class XacmlJsonMessageBodyHandler implements MessageBodyReader, throws IOException { try (OutputStreamWriter writer = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) { - //TODO - //writer.write(JsonResponseTranslator.toString(response, true)); + writer.write(JsonResponseTranslator.toString(response, true)); } catch (Exception exc) { throw new IOException("failed to convert a json response to a string"); } @@ -78,8 +79,7 @@ public class XacmlJsonMessageBodyHandler implements MessageBodyReader, Request jsonRequest = null; try { - //TODO - //jsonRequest = JsonResponseTranslator.load(entityStream); + jsonRequest = JsonRequestTranslator.load(entityStream); } catch (Exception exc) { throw new IOException("failed to decode incoming request string to a json request"); } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpRestServer.java b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpRestServer.java index a92d750e..b0f3b8c0 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpRestServer.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpRestServer.java @@ -29,6 +29,8 @@ import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter; import org.onap.policy.common.endpoints.parameters.RestServerParameters; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.pdpx.main.rest.serialization.XacmlJsonExceptionMapper; +import org.onap.policy.pdpx.main.rest.serialization.XacmlJsonMessageBodyHandler; import org.onap.policy.pdpx.main.rest.serialization.XacmlXmlExceptionMapper; import org.onap.policy.pdpx.main.rest.serialization.XacmlXmlMessageBodyHandler; @@ -62,7 +64,7 @@ public class XacmlPdpRestServer extends RestServer { props.setProperty(svcpfx + PolicyEndPointProperties.PROPERTY_HTTP_SERIALIZATION_PROVIDER, String.join(",", GsonMessageBodyHandler.class.getName(), YamlMessageBodyHandler.class.getName(), JsonExceptionMapper.class.getName(), YamlExceptionMapper.class.getName(), - //XacmlJsonMessageBodyHandler.class.getName(), XacmlJsonExceptionMapper.class.getName(), + XacmlJsonMessageBodyHandler.class.getName(), XacmlJsonExceptionMapper.class.getName(), XacmlXmlMessageBodyHandler.class.getName(), XacmlXmlExceptionMapper.class.getName())); return props; } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java index 178e4b14..6f7dec6d 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ package org.onap.policy.pdpx.main.rest; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; -import com.att.research.xacml.std.dom.DOMStructureException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.io.File; @@ -76,6 +75,7 @@ public class TestDecision { private static HttpClient client; private static CommonTestData testData = new CommonTestData(); private static final String APPLICATION_XACML_XML = "application/xacml+xml"; + private static final String APPLICATION_XACML_JSON = "application/xacml+json"; @ClassRule public static final TemporaryFolder appsFolder = new TemporaryFolder(); @@ -142,7 +142,6 @@ public class TestDecision { @Test public void testDecision_UnsupportedAction() throws Exception { - LOGGER.info("Running test testDecision_UnsupportedAction"); DecisionRequest request = new DecisionRequest(); @@ -164,7 +163,6 @@ public class TestDecision { @Test public void testDecision_Guard() throws KeyManagementException, NoSuchAlgorithmException, ClassNotFoundException { - LOGGER.info("Running test testDecision_Guard"); DecisionRequest request = new DecisionRequest(); @@ -183,19 +181,28 @@ public class TestDecision { } @Test - public void testDecision_Native() throws IOException, DOMStructureException { - + public void testDecision_Native() throws IOException { LOGGER.info("Running test testDecision_Native"); - String requestAsString = ResourceUtils.getResourceAsString( + String xmlRequestAsString = ResourceUtils.getResourceAsString( "src/test/resources/decisions/decision.native.request.xml"); - if (requestAsString == null) { + if (xmlRequestAsString == null) { throw new IOException("failed to read the xml request"); } - String response = getNativeDecision(requestAsString); - LOGGER.info("Response {}", response); - assertThat(response).contains("NOTAPPLICABLE"); + String jsonRequestAsString = ResourceUtils.getResourceAsString( + "src/test/resources/decisions/decision.native.request.json"); + if (jsonRequestAsString == null) { + throw new IOException("failed to read the json request"); + } + + String responseFromXmlRequest = getNativeDecision(xmlRequestAsString, APPLICATION_XACML_XML); + LOGGER.info("Response from xml request {}", responseFromXmlRequest); + assertThat(responseFromXmlRequest).contains("NOTAPPLICABLE"); + + String responseFromJsonRequest = getNativeDecision(jsonRequestAsString, APPLICATION_XACML_JSON); + LOGGER.info("Response from json request {}", responseFromJsonRequest); + assertThat(responseFromJsonRequest).contains("NOTAPPLICABLE"); } private static Main startXacmlPdpService(File params) throws PolicyXacmlPdpException { @@ -208,7 +215,6 @@ public class TestDecision { } private DecisionResponse getDecision(DecisionRequest request) { - Entity entityRequest = Entity.entity(request, MediaType.APPLICATION_JSON); Response response = client.post("/decision", entityRequest, Collections.emptyMap()); @@ -217,9 +223,8 @@ public class TestDecision { return HttpClient.getBody(response, DecisionResponse.class); } - private String getNativeDecision(String request) { - - Entity entityRequest = Entity.entity(request, APPLICATION_XACML_XML); + private String getNativeDecision(String request, String mediaType) { + Entity entityRequest = Entity.entity(request, mediaType); Response response = client.post("/xacml", entityRequest, Collections.emptyMap()); assertEquals(200, response.getStatus()); @@ -228,7 +233,6 @@ public class TestDecision { } private ErrorResponse getErrorDecision(DecisionRequest request) { - Entity entityRequest = Entity.entity(request, MediaType.APPLICATION_JSON); Response response = client.post("/decision", entityRequest, Collections.emptyMap()); @@ -254,5 +258,4 @@ public class TestDecision { LOGGER.error("Failed to copy {} to {}", source, dest); } } - } \ No newline at end of file diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/serialization/TestXacmlJsonMessageBodyHandler.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/serialization/TestXacmlJsonMessageBodyHandler.java index 5d5a4b88..988c91a0 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/rest/serialization/TestXacmlJsonMessageBodyHandler.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/rest/serialization/TestXacmlJsonMessageBodyHandler.java @@ -20,16 +20,35 @@ package org.onap.policy.pdpx.main.rest.serialization; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.att.research.xacml.api.Request; +import com.att.research.xacml.api.RequestAttributes; +import com.att.research.xacml.api.Response; +import com.att.research.xacml.std.dom.DOMResponse; import com.att.research.xacml.std.dom.DOMStructureException; +import com.att.research.xacml.std.json.JSONStructureException; +import com.att.research.xacml.std.json.JsonResponseTranslator; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Iterator; import org.junit.Before; import org.junit.Test; +import org.onap.policy.common.utils.resources.ResourceUtils; public class TestXacmlJsonMessageBodyHandler { private static final String PRIMARY_TYPE = "application"; private static final String SUB_TYPE = "xacml+json"; + @SuppressWarnings("rawtypes") + private static final Class REQUEST_CLASS = Request.class; + @SuppressWarnings("rawtypes") + private static final Class RESPONSE_CLASS = Response.class; + private XacmlJsonMessageBodyHandler hdlr; @Before @@ -43,8 +62,12 @@ public class TestXacmlJsonMessageBodyHandler { } @Test - public void testWriteTo() throws IOException, DOMStructureException { - //TODO: placeholder for JsonResponseTranslator + public void testWriteTo() throws IOException, DOMStructureException, JSONStructureException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Response resp = DOMResponse.load(ResourceUtils.getResourceAsString( + "src/test/resources/decisions/decision.native.response.xml")); + hdlr.writeTo(resp, RESPONSE_CLASS, RESPONSE_CLASS, null, null, null, stream); + assertEquals(resp, JsonResponseTranslator.load(new ByteArrayInputStream(stream.toByteArray()))); } @Test @@ -53,7 +76,28 @@ public class TestXacmlJsonMessageBodyHandler { } @Test + @SuppressWarnings("unchecked") public void testReadFrom() throws IOException { - //TODO: placeholder for JsonRequestTranslator + Request req = hdlr.readFrom(REQUEST_CLASS, REQUEST_CLASS, null, null, null, ResourceUtils.getResourceAsStream( + "src/test/resources/decisions/decision.native.request.json")); + assertFalse(req.getCombinedDecision()); + assertFalse(req.getReturnPolicyIdList()); + assertTrue(req.getRequestAttributes().size() == 3); + Iterator iter = req.getRequestAttributes().iterator(); + + RequestAttributes firstRequestAttributes = iter.next(); + assertTrue(firstRequestAttributes.getAttributes().size() == 1); + assertEquals("Julius Hibbert", firstRequestAttributes.getAttributes().iterator().next() + .getValues().iterator().next().getValue().toString()); + + RequestAttributes secondRequestAttributes = iter.next(); + assertTrue(secondRequestAttributes.getAttributes().size() == 1); + assertEquals("http://medico.com/record/patient/BartSimpson", secondRequestAttributes.getAttributes() + .iterator().next().getValues().iterator().next().getValue().toString()); + + RequestAttributes thirdRequestAttributes = iter.next(); + assertTrue(thirdRequestAttributes.getAttributes().size() == 1); + assertEquals("read", thirdRequestAttributes.getAttributes().iterator().next() + .getValues().iterator().next().getValue().toString()); } } \ No newline at end of file diff --git a/main/src/test/resources/decisions/decision.native.request.json b/main/src/test/resources/decisions/decision.native.request.json new file mode 100644 index 00000000..5e593bc9 --- /dev/null +++ b/main/src/test/resources/decisions/decision.native.request.json @@ -0,0 +1,41 @@ +{ + "Request": { + "ReturnPolicyIdList": false, + "CombinedDecision": false, + "AccessSubject": [ + { + "Attribute": [ + { + "IncludeInResult": false, + "AttributeId": "subject-id", + "Value": "Julius Hibbert" + } + ] + } + ], + "Resource": [ + { + "Attribute": [ + { + "IncludeInResult": false, + "AttributeId": "resource-id", + "Value": "http://medico.com/record/patient/BartSimpson", + "DataType": "anyURI" + } + ] + } + ], + "Action": [ + { + "Attribute": [ + { + "IncludeInResult": false, + "AttributeId": "action-id", + "Value": "read" + } + ] + } + ], + "Environment": [] + } +} \ No newline at end of file -- cgit 1.2.3-korg