Skip to content
Snippets Groups Projects
Commit acaf9d54 authored by cdanger's avatar cdanger
Browse files

Simplied JSON schema loading with new ClasspathAwareSchemaClient from...

Simplied JSON schema loading with new ClasspathAwareSchemaClient from org.everit.json.schema library
parent 982563f5
No related branches found
No related tags found
No related merge requests found
...@@ -17,11 +17,6 @@ ...@@ -17,11 +17,6 @@
*/ */
package org.ow2.authzforce.xacml.json.model; package org.ow2.authzforce.xacml.json.model;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.everit.json.schema.Schema; import org.everit.json.schema.Schema;
import org.everit.json.schema.loader.SchemaClient; import org.everit.json.schema.loader.SchemaClient;
import org.everit.json.schema.loader.SchemaLoader; import org.everit.json.schema.loader.SchemaLoader;
...@@ -29,141 +24,124 @@ import org.json.JSONArray; ...@@ -29,141 +24,124 @@ import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import java.io.IOException;
import java.io.InputStream;
/** /**
* Instances of JSON schema as defined by JSON Profile of XACML 3.0 * Instances of JSON schema as defined by JSON Profile of XACML 3.0
* *
*/ */
public final class XacmlJsonUtils public final class XacmlJsonUtils
{ {
private XacmlJsonUtils() private static final SchemaClient CLASSPATH_AWARE_SCHEMA_CLIENT = SchemaClient.classPathAwareClient();
{ private static Schema loadSchema(String schemaFilenameRelativeToThisClass) {
// hide constructor try (InputStream inputStream = XacmlJsonUtils.class.getResourceAsStream(schemaFilenameRelativeToThisClass))
} {
final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
/** return SchemaLoader.builder().schemaJson(rawSchema).schemaClient(CLASSPATH_AWARE_SCHEMA_CLIENT).resolutionScope("classpath://org/ow2/authzforce/xacml/json/model/").build().load().build();
* JSON schema for validating Requests according to JSON Profile of XACML 3.0 } catch (final IOException e)
*/ {
public static final Schema REQUEST_SCHEMA; throw new RuntimeException(e);
}
}
/** /**
* JSON schema for validating Responses according to JSON Profile of XACML 3.0 * JSON schema for validating Requests according to JSON Profile of XACML 3.0
*/ */
public static final Schema RESPONSE_SCHEMA; public static final Schema REQUEST_SCHEMA;
/** /**
* JSON schema for validating Policies according to AuthzForce/JSON policy format for XACML Policy(Set) (see Policy.schema.json) * JSON schema for validating Responses according to JSON Profile of XACML 3.0
*/ */
public static final Schema POLICY_SCHEMA; public static final Schema RESPONSE_SCHEMA;
static /**
{ * JSON schema for validating Policies according to AuthzForce/JSON policy format for XACML Policy(Set) (see Policy.schema.json)
final Map<String, String> mutableCatalogMap = new HashMap<>(); */
mutableCatalogMap.put("https://raw.githubusercontent.com/authzforce/xacml-json-model/master/src/main/resources/org/ow2/authzforce/xacml/json/model/common-std.schema.json", "classpath:org/ow2/authzforce/xacml/json/model/common-std.schema.json"); public static final Schema POLICY_SCHEMA;
mutableCatalogMap.put("https://raw.githubusercontent.com/authzforce/xacml-json-model/master/src/main/resources/org/ow2/authzforce/xacml/json/model/common-ng.schema.json", "classpath:org/ow2/authzforce/xacml/json/model/common-ng.schema.json");
final SchemaClient schemaClient = new SpringBasedJsonSchemaClient(mutableCatalogMap);
try (InputStream inputStream = SpringBasedJsonSchemaClient.class.getResourceAsStream("Request.schema.json"))
{
final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
// final SchemaLoader schemaLoader = schemaLoaderBuilder.schemaJson(rawSchema).build();
REQUEST_SCHEMA = SchemaLoader.load(rawSchema, schemaClient); // schemaLoader.load().build();
}
catch (final IOException e)
{
throw new RuntimeException(e);
}
try (InputStream inputStream = SpringBasedJsonSchemaClient.class.getResourceAsStream("Response.schema.json")) static
{ {
final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream)); REQUEST_SCHEMA = loadSchema("Request.schema.json");
RESPONSE_SCHEMA = SchemaLoader.load(rawSchema/*, schemaClient*/); RESPONSE_SCHEMA = loadSchema("Response.schema.json");
} POLICY_SCHEMA = loadSchema("Policy.schema.json");
catch (final IOException e) }
{
throw new RuntimeException(e);
}
try (InputStream inputStream = SpringBasedJsonSchemaClient.class.getResourceAsStream("Policy.schema.json")) /**
{ * Canonicalize a XACML/JSON response, typically for comparison with another one. In particular, it removes every Result's status as we choose to ignore the Status. Indeed, a PDP implementation
final JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream)); * might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect.
POLICY_SCHEMA = SchemaLoader.load(rawSchema/*, schemaClient*/); *
} * WARNING: this method modifies the content of {@code xacmlJsonResponse} directly
catch (final IOException e) *
{ * @param xacmlJsonResponse
throw new RuntimeException(e); * input XACML Response
} * @return canonicalized response
} */
public static JSONObject canonicalizeResponse(final JSONObject xacmlJsonResponse)
{
/*
* We iterate over all results, because for each results, we don't compare everything. In particular, we choose to ignore the StatusMessage, StatusDetail and any nested StatusCode. Indeed, a
* PDP implementation might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect.
*/
for (final Object resultObj : xacmlJsonResponse.getJSONArray("Response"))
{
final JSONObject resultJsonObj = (JSONObject) resultObj;
// Status
final JSONObject statusJsonObj = resultJsonObj.optJSONObject("Status");
if (statusJsonObj != null)
{
// remove Status if StatusCode OK (optional, default implicit therefore useless)
final JSONObject statusCodeJsonObj = statusJsonObj.getJSONObject("StatusCode");
final String statusCodeVal = statusCodeJsonObj.getString("Value");
if (statusCodeVal.equals("urn:oasis:names:tc:xacml:1.0:status:ok"))
{
// Status OK is useless, simplify
resultJsonObj.remove("Status");
} else
{
// remove any nested status code, StatusMessage and StatusDetail
statusCodeJsonObj.remove("StatusCode");
statusJsonObj.remove("StatusMessage");
statusJsonObj.remove("StatusDetail");
}
}
/** // remove empty Category array if any
* Canonicalize a XACML/JSON response, typically for comparison with another one. In particular, it removes every Result's status as we choose to ignore the Status. Indeed, a PDP implementation final JSONArray jsonArrayOfAttCats = resultJsonObj.optJSONArray("Category");
* might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. if (jsonArrayOfAttCats != null)
* {
* WARNING: this method modifies the content of {@code xacmlJsonResponse} directly if (jsonArrayOfAttCats.length() == 0)
* {
* @param xacmlJsonResponse resultJsonObj.remove("Category");
* input XACML Response } else
* @return canonicalized response {
*/ /*
public static JSONObject canonicalizeResponse(final JSONObject xacmlJsonResponse) * Remove any IncludeInResult property which is useless and optional in XACML/JSON. (NB.: IncludeInResult is mandatory in XACML/XML schema but optional in JSON Profile).
{ */
/* for (final Object attCatJson : jsonArrayOfAttCats)
* We iterate over all results, because for each results, we don't compare everything. In particular, we choose to ignore the StatusMessage, StatusDetail and any nested StatusCode. Indeed, a {
* PDP implementation might return a perfectly XACML-compliant response but with extra StatusCode/Message/Detail that we would not expect. assert attCatJson instanceof JSONObject;
*/ final JSONObject attCatJsonObj = (JSONObject) attCatJson;
for (final Object resultObj : xacmlJsonResponse.getJSONArray("Response")) final JSONArray jsonArrayOfAtts = attCatJsonObj.optJSONArray("Attribute");
{ if (jsonArrayOfAtts != null)
final JSONObject resultJsonObj = (JSONObject) resultObj; {
// Status jsonArrayOfAtts.forEach(attJson ->
final JSONObject statusJsonObj = resultJsonObj.optJSONObject("Status"); {
if (statusJsonObj != null) assert attJson instanceof JSONObject;
{ final JSONObject attJsonObj = (JSONObject) attJson;
// remove Status if StatusCode OK (optional, default implicit therefore useless) attJsonObj.remove("IncludeInResult");
final JSONObject statusCodeJsonObj = statusJsonObj.getJSONObject("StatusCode"); });
final String statusCodeVal = statusCodeJsonObj.getString("Value"); }
if (statusCodeVal.equals("urn:oasis:names:tc:xacml:1.0:status:ok")) }
{ }
// Status OK is useless, simplify }
resultJsonObj.remove("Status"); }
}
else
{
// remove any nested status code, StatusMessage and StatusDetail
statusCodeJsonObj.remove("StatusCode");
statusJsonObj.remove("StatusMessage");
statusJsonObj.remove("StatusDetail");
}
}
// remove empty Category array if any return xacmlJsonResponse;
final JSONArray jsonArrayOfAttCats = resultJsonObj.optJSONArray("Category"); }
if (jsonArrayOfAttCats != null)
{
if (jsonArrayOfAttCats.length() == 0)
{
resultJsonObj.remove("Category");
}
else
{
/*
* Remove any IncludeInResult property which is useless and optional in XACML/JSON. (NB.: IncludeInResult is mandatory in XACML/XML schema but optional in JSON Profile).
*/
for (final Object attCatJson : jsonArrayOfAttCats)
{
assert attCatJson instanceof JSONObject;
final JSONObject attCatJsonObj = (JSONObject) attCatJson;
final JSONArray jsonArrayOfAtts = attCatJsonObj.optJSONArray("Attribute");
if (jsonArrayOfAtts != null)
{
jsonArrayOfAtts.forEach(attJson -> {
assert attJson instanceof JSONObject;
final JSONObject attJsonObj = (JSONObject) attJson;
attJsonObj.remove("IncludeInResult");
});
}
}
}
}
}
return xacmlJsonResponse; private XacmlJsonUtils()
} {
// hide constructor
}
} }
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
"type": "array", "type": "array",
"items": "items":
{ {
"$ref": "common-std_.schema.json#/definitions/AttributeCategoryType" "$ref": "common-std.schema.json#/definitions/AttributeCategoryType"
}, },
"minItems": 1 "minItems": 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment