-
Notifications
You must be signed in to change notification settings - Fork 2
Proposal for UML‐based agnostic Core model and XML JSON schema mapping rules
Here is a UML class diagram proposed as agnostic model for the Policy syntax, based on the latest discussed issues and XACML 4.0 draft schema (Request/Response data models still need to be added to get a complete XACML model):
This class diagram relies on the new UML profile below for the definitions of the custom stereotypes (RestrictedString, Meta, etc.):
The choice of UML is mainly to have a graphical notation and a corresponding machine-readable data model that can be translated to XML schema and JSON schema as priority targets, but also schemas/grammars for other formats in the future as the need arises (YAML, CBOR...). Note that the JSON schema may be used for YAML as well to some extent.
To explore the UML diagrams in more details, you may import the projects in the ZIP file into Eclipse Papyrus (tested with v6.7.0 - 2024-06).
The next sections detail the mapping rules for mapping this UML model to the XML/JSON schemas (version Draft 2020-12 of JSON schema is used as reference):
Mapping rules for standard UML:
| UML | XML schema | JSON schema |
|---|---|---|
| String | xs:string | string |
| Boolean | xs:boolean | boolean |
| Integer | xs:integer | integer |
A UML class Foo stereotyped as <<RestrictedString>> represents a subtype of String restricted by a regular expression R, and this regex is specified as the pattern property value. The regex delimiters ^$ are implicit in this case, i.e. this pattern is matched against the whole string. (like in XSD simpleType restriction's pattern element).
If the class name is URI (resp. NCName), it is mapped to the standard xs:anyURI (resp. xs:NCName) type.
Else it is mapped to:
<xs:simpleType name="FooType">
<xs:restriction base="xs:string">
<xs:pattern value="R"/>
</xs:restriction>
</xs:simpleType>This covers the following XML types used in XACML schema:
- xs:anyURI,
- xs:NCName,
- xacml:Version,
- xacml:VersionMatch.
If the class name is URI, it is mapped to:
{ "type": "string", "format": "uri" }Else it is mapped to a new subschema (regex delimiters ^$ must be explicit in the pattern expression):
"$defs": {
...
"Foo": { "type": "string", "pattern": "^R$" }
...
}A UML class Foo stereotyped as <<Enumeration>> represents a subtype of String that is an enumeration of string literals X, Y, etc.
<xs:simpleType name="FooType">
<xs:restriction base="xs:string">
<xs:enumeration value="X"/>
<xs:enumeration value="Y"/>
...
</xs:restriction>
</xs:simpleType>This covers the following XML type(s) used in XACML schema:
- xacml:Effect.
If there is at least one Datatype with a non-meta property (i.e. property not stereotyped Meta) of type Foo, then the definition above must be preceded by a definition of an element Foo with type FooType (non-meta properties will be references to this element) as follows:
<xs:element name="Foo" type="xacml:FooType"/>
<xs:simpleType name="FooType">
<xs:restriction base="xs:string">
<xs:enumeration value="X"/>
<xs:enumeration value="Y"/>
...
</xs:restriction>
</xs:simpleType>This covers the following XML types / elements used in XACML schema:
- xacml:DecisionType / xacml:Decision.
"$defs": {
...
"Foo": { "enum": ["X", "Y", ...] }
...
}A UML Datatype here is a class stereotyped as <<Datatype>>, which represents a complex datatype as opposed to Primitive types described in the previous section, i.e. datatypes that can have properties.
Terms:
-
Abstract Datatype: Datatype whose
abstractmodifier is set totrueand the title is italicized on the UML diagram. -
Empty Datatype: a datatype is said empty if it has no property in its definition, regardless of subtypes. E.g.
PolicyCombinedItem,Expression. -
Meta-property / non-meta property: a meta-property is a UML Datatype property stereotyped as
Meta(marked<<Meta>>in the UML diagram). Other properties are referred to as non-meta properties.
If an UML Datatype Foo is an empty abstract Datatype used no more than once as property type in the whole data model (such as PolicyCombinedItem), it is anonymized, i.e. not mapped to any corresponding XML type or element. It is only the (single) property of type Foo of some other Datatype, if there is any, that is mapped to a xs:choice of Foo's subtypes, as explained in the Property mapping rules below. So Foo is completely absent from the resulting XML schema.
Else (Foo is not anonymized):
-
Foois mapped to a globally definedxs:complexTypenamedFooType:<xs:complexType name="FooType">...</xs:complexType>
-
If
Foois stereotyped<<MixedContent>>, this refers to XML Mixed Content (character data interspersed with child elements), i.e.mixed="true"must be specified on thexs:complexType:<xs:complexType name="FooType" mixed="true"> ... </xs:complexType>
This covers the following XML type(s) used in XACML schema:
- xacml:ContentType,
- xacml:AttributeValueType,
- xacml:AttributeAssignmentType.
N.B.: according to the table Complex Type Definition with complex content Schema Component of section 3.4.2 XML Representation of Complex Type Definitions of W3C XML schema specification, the
mixedattribute oncomplexContentis redudant if already defined on parentcomplexType. -
If
Foois abstract, then the attributeabstract="true"must be specified on the complexType:<xs:complexType name="FooType" abstract="true">...</xs:complexType>
This covers the following XML type(s) used in XACML schema:
- xacml:IdReferenceType,
- xacml:ExpressionType.
-
If
Fooinherits from another Datatype - the supertype -Bar(Generalization relationship) that is not anonymized either, then add the correspondingxs:complexContent/xs:extensionto theFooTypecomplexType definition:<xs:complexType name="FooType"> <xs:complexContent> <xs:extension base="xacml:BarType"> ... </xs:extension> </xs:complexContent> </xs:complexType>
-
If there is at least one non-meta property of type
Foo(and again,Foois not an anonymized Datatype as defined earlier), then thexs:complexTypedefinition must be preceded by a globally definedxs:elementnamedFoowith typeFooTypein XACML namespace (so that the other Datatype(s)' non-meta properties can make references to it as explained later in the Property mapping rules) as follows:<xs:element name="Foo" type="xacml:FooType"/> <xs:complexType name="FooType">...</xs:complexType>
-
Plus, this
xs:elementmust also have the attributeabstract="true"specified if the UML Datatype is abstract as mentioned before:<xs:element name="Foo" type="xacml:FooType" abstract="true"/> <xs:complexType name="FooType" abstract="true">...</xs:complexType>
This covers the following XML type(s) / element(s) used in XACML schema:
- xacml:ExpressionType / xacml:Expression.
-
Plus, if
Fooinherits from a DatatypeBarand a global element namedBaris defined according to the the mapping rule #5 above, then add thesubstitutionGroup="xacml:Bar"attribute:<xs:element name="Foo" type="xacml:FooType" substitutionGroup="xacml:Bar"/> <xs:complexType name="FooType"> <xs:complexContent> <xs:extension base="xacml:BarType"> ... </xs:extension> </xs:complexContent> </xs:complexType>
N.B.: the
substitutionGroupattribute can be multi-valued (so multi-inheritance is possible). -
Property mapping rules: for each property in the UML Datatype,
-
8.1. If the property is stereotyped as
<<Meta>>(meta-property), convert to an XML attribute as follows:- The attribute name is the UML property name converted to Pascal case;
- The attribute type is the corresponding XML type according to the mapping rules defined in the previous UML Primitive Types section;
- If the property's multiplicity is
0..1, specifyuse="optional", elseuse="required"; - If the property has a default value, add the same
defaultvalue to the attribute.
For example, a meta-property
myPropertyof typeBoolean, multiplicity0..1, default valuefalsewould translate to:<xs:attribute name="MyProperty" type="xs:boolean" use="optional" default="false"/>
A meta-property
myPropertyof typeEffect, multiplicity1(no default value) would translate to:<xs:attribute name="MyProperty" type="xacml:EffectType" use="required"/>
-
8.2. Else (the property is not stereotyped as
<<Meta>>):-
8.2.1. If the property type - say
PropType- is anonymized (cf. previous section), then map to an XML choice between the XML elements corresponding to allPropType's subtypes. The property's multiplicity is mapped to thexs:choice's minOccurs/maxOccurs similarly to the previous rules for meta-properties:- If the property's multiplicity is
0..1, map tominOccurs="0"(maxOccursis 1 by default); - If the multiplicity is
*, map tominOccurs="0" maxOccurs="unbounded"; - If the multiplicity is
1, do not specify minOccurs/maxOccurs as 1 is the default value for both; - If the multiplicity is
1..*, map tominOccurs="1" maxOccurs="unbounded".
For example, considering that the subtypes of the Datatype
PolicyCombinedItemarePolicy,PolicyReference,VariableDefinitionandRule, thePolicyDatatype'scombinedItems(non-meta) property with typePolicyCombinedItem(abstract) and multiplicity*will be mapped to:<xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element ref="xacml:Policy"/> <xs:element ref="xacml:PolicyReference"/> <xs:element ref="xacml:VariableDefinition"/> <xs:element ref="xacml:Rule"/> </xs:choice>
- If the property's multiplicity is
-
8.2.2. Else (the property type is not abstract or at least one other property in the data model have the same type) convert to an XML element refering to the element that has the same name as the property type, in the XACML namespace, and map the property's multiplicity to minOccurs/maxOccurs values as follows (same as above):
- If the property's multiplicity is
0..1, map tominOccurs="0"(maxOccursis 1 by default); - If the multiplicity is
*, map tominOccurs="0" maxOccurs="unbounded"; - If the multiplicity is
1, do not specify minOccurs/maxOccurs as 1 is the default value for both; - If the multiplicity is
1..*, map tominOccurs="1" maxOccurs="unbounded".
For example, a non-meta property
myPropertyof typeFoo, multiplicity*would translate to:<xs:element ref="xacml:Foo" minOccurs="0" maxOccurs="unbounded"/>
- If the property's multiplicity is
-
-
-
If
Foois stereotyped with<<AnyMetaProperty>>, it allows to have any meta-property besides the meta properties explicitly defined in the class if there is any, which means any XML attribute may be added. This translates to axs:anyAttributeelement at the end of the list of XML attributes:<xs:complexType name="FooType" ...> ... <!-- Other attributes mapped from meta-properties of the UML class, if any. --> <xs:anyAttribute namespace="##any" processContents="lax"/> ... </xs:complexType>
This covers the following XML type(s) used in XACML schema:
- xacml:AttributeValueType.
-
If
Foois stereotyped with<<AnyProperty>>, it allows to have any non-meta property besides the non-meta properties explicitly defined in the class if there is any, which means any child XML element may be added to the element sequence. This translates to axs:anyelement at the end of the XML sequence; and its multiplicity (number of occurrences) depends on the value specified for theAnyPropertystereotype'soneAndOnlyproperty:-
10.1. If
oneAndOnly="true"(default value), this is equivalent to minOccurs = maxOccurs = 1 (one and only one) which may be omitted as these are the default values, so this translates to:<xs:complexType name="FooType" ...> ... <xs:sequence> <!-- Other elements mapped from non-meta properties of the UML class, if any. --> <xs:any namespace="##any" processContents="lax"/> </xs:sequence> ... </xs:complexType>
This covers the following XML type(s) used in XACML schema:
- xacml:ContentType.
-
10.2. If
oneAndOnly="false"(zero or more), this is equivalent to minOccurs=0 and maxOccurs=unbounded:<xs:complexType name="FooType" ...> ... <xs:sequence> <!-- Other elements based on explicit properties of the UML class, if any. --> <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> ... </xs:complexType>
This covers the following XML type(s) used in XACML schema:
- xacml:AttributeValueType,
- xacml:StatusDetailType.
-
-
Apply mapping rules based on the JSON Profile: the JSON schema of certain UML Datatypes is defined by the JSON Profile of XACML 3.0 (the JSON Profile will need some update to align with new XACML 4.0 model):
-
Content: defined as JSON string according to the JSON profile, section 4.2.2, 4.2.3.
{"type": "string"} -
AttributeValue (4.2.4):
"AttributeValue": { "description": "Security warning: this definition allows any JSON object as value. TODO: find a way to validate it somehow. Possible solutions: 1) Modify this schema in production to restrict possible values as much as possible. 2) Any equivalent of XML processContents='strict'. 3) Any JSON processor that enforces a max text length, max number of keys, max object depth.", "anyOf": [ { "type": "boolean" }, { "type": "number" }, { "type": "string" }, { "type": "object" }, { "type": "array", "items": { "type": "boolean" }, "minItems": 0 }, { "type": "array", "items": { "type": ["string","number"] }, "minItems": 0 }, { "type": "array", "items": { "type": "object" }, "minItems": 0 } ] }
-
Attribute (4.2.4):
"Attribute": { "type": "object", "properties": { "AttributeId": { "type": "string", "format": "uri-reference" }, "Issuer": { "type": "string" }, "IncludeInResult": { "type": "boolean" }, "DataType": { "type": "string", "format": "uri-reference" }, "Value": { "$ref": "#/defs/AttributeValue" } }, "required": [ "AttributeId", "Value" ], "additionalProperties": false }
N.B.: according to the resolution of issue #18, the Attribute with IncludeInResult is renamed to RequestAttribute, whereas the Attribute in Result and PolicyIssuer does not have IncludeInResult anymore.
-
To be defined: Request, Response, Result, Status, MissingAttributeDetail, StatusCode, AttributeAssignment.
Note: all
MixedContentDatatypes (Content, AttributeValue, AttributeAssignment ) are already addressed in Special cases above. -
-
Else (the UML Datatype is not in the previous list):
-
1.1. If the UML Datatype is stereotyped
<<MixedContent>>, raise an error Unsupported as no other MixedContent datatype is allowed besides the Content, AttributeValue and AttributeAssignment in the previous list. -
1.2. Else (not MixedContent), skip to the next rule.
-
-
If the UML Datatype
Foois abstract,-
3.1. If
Foois empty (no property) (e.g.Expression,PolicyCombinedItem), map to aoneOfcomposition of the schema references to all ofFoo's subtypes' subschemas, including indirect subtypes', which implies that each subtype ofFoomust have one:"$defs": { ... "Foo": { "oneOf": [ { "$ref": "#/$defs/Subtype1" }, { "$ref": "#/$defs/Subtype2" }, ... ] } ... }
For example, the
ExpressionDatatype is mapped to:"$defs": { ... "Expression": { "oneOf": [ { "$ref": "#/$defs/AttributeValue" }, { "$ref": "#/$defs/AttributeDesignator" }, { "$ref": "#/$defs/Function" }, { "$ref": "#/$defs/Apply" } ... ] } ... }
-
3.2. Else (
Foois not empty, e.g.IdReferenceDatatype),Foois mapped to the following (the subtypes will useFooBasetype as actual subtype in the JSON schema as shown in the next mapping rules):"$defs": { ... "FooBase": { "type": "object", "properties": { ...the properties... }, "required": [...properties with multiplicity 1 or more...], "additionalProperties": false }, "Foo": { "oneOf": [ { "$ref": "#/$defs/Subtype1" }, { "$ref": "#/$defs/Subtype2" }, ... ] } ... }
-
-
Else (
Foois not abstract):- 4.1. If it does not inherit from another Datatype or inherits from an empty (abstract or not) Datatype, then map to a JSON object type as follows (the empty supertype is ignored, and
"additionalProperties": falseby default):"$defs": { ... "Foo": { "type": "object", "properties": { ...the properties... }, "required": [...properties with multiplicity 1 or more...] "additionalProperties": false } ... }
- 4.2. Else (
Fooinherits a non-empty DatatypeBar):-
4.2.1. If the (non-empty) supertype
Baris abstract, considering a newBarBasetype has been defined according to previous rule 3.2, then mapFooto the following schema:"$defs": { ... "Foo": { "allOf": [ { "$ref": "#/$defs/BarBase" }, { "type": "object", "properties": { ...the properties... } "required": [...] "additionalProperties": false } ] } ... }
-
4.2.2. Else (
Barsupertype is not abstract), then useBar(instead ofBarBase) as base type:"$defs": { ... "Foo": { "allOf": [ { "$ref": "#/$defs/Bar" }, { "type": "object", "properties": { ...the properties... } "required": [...] "additionalProperties": false } ] } ... }
-
- 4.1. If it does not inherit from another Datatype or inherits from an empty (abstract or not) Datatype, then map to a JSON object type as follows (the empty supertype is ignored, and
-
Property mapping rules: for each property in the UML Datatype,
- 1.1. The Property is mapped to a JSON property in the JSON object type definition as follows:
-
The JSON property name is the same as the UML property name.
[!NOTE]
Should we use Pascal case like the XACML/XML schema instead? Isn't this awkward for JSON?[!WARNING]
This is not strictly equivalent to the UML model since theMetastereotype is ignored (no difference between meta and non-meta properties in JSON). -
The UML property type
Foois mapped to a JSON subschema or a reference to one, as follows:- If
Foois one of the UML Primitive Types that can be mapped to a JSON standard type/format (see UML Primitive Types section), e.g.string/urifor UMLURItype, then ("format" is optional) use a subschema:
{ "type": "matching_standard_json_datatype", "format": "matching_standard_format_if_necessary" }Else there must be a corresponding subschema
Fooas defined by previous rules, in which case you use a subschema reference instead:{ "$ref": "#/$defs/Foo" } - If
-
- 1.2. The property's multiplicity is mapped as follows:
-
0..1: do not include the property name in therequiredarray of the subschema definition;e.g. for two UML properties, one of which does not have a corresponding standard type/format:"properties": { ... "myProperty": { ...Foo's subschema or subschema ref (see previous rule)... }, ... }
"properties": { "myProperty1": { "type": "string", "format": "uri" }, "myProperty2": { "$ref": "#/$defs/Foo" } }
-
1: same as above, but in this case, the property name must be included in therequiredarray."properties": { ... "myProperty": { ...Foo's subschema or subschema ref (see first property mapping rule)... }, ... }, "required": ["myProperty", ...]
-
*: the JSON property type is an array of theFoo's JSON schema type definition but the property name is not included in therequiredarray of the subschema:e.g. for two multi-valued UML properties, one of which does not have a corresponding standard type/format:"properties": { ... "myProperty": { "type": "array", "items": {...Foo's subschema or subschema ref (see first property mapping rule)...}, "unevaluatedItems": false }, ... }
"properties": { "myProperty1": { "type": "array", "items": {"type": "string", "format": "uri"}, "unevaluatedItems": false }, "myProperty2": { "type": "array", "items": {"$ref": "#/$defs/Foo"}, "unevaluatedItems": false } }
-
1..*: same as above, but the array type definition has"minItems": 1and the property name must be included in therequiredarray of the subschema:"properties": { ... "myProperty": { "type": "array", "minItems": 1, "items": {...Foo's subschema or subschema ref (see previous rule)...}, "unevaluatedItems": false }, ... }, "required": ["myProperty", ...]
-
- 1.3. If the UML property has a default value, use the
defaultkeyword in JSON schema to specify the default value as well.
- 1.1. The Property is mapped to a JSON property in the JSON object type definition as follows:
-
If the UML Datatype
Foois stereotyped as<<AnyMetaProperty>>(allows any meta-property besides defined ones if there is any, i.e. any JSON property may be added), then set"additionalProperties"=truein Foo's subschema.- If
Foois also stereotyped asAnyPropertyand AnyProperty stereotype's propertyoneAndOnlyistrue(one and only one other property is allowed), then return an error Unsupported as this case is not supposed to exist in the data model.
Else (
Foohas noAnyMetaPropertystereotype):- 6.1. If
Foois stereotyped as<<AnyProperty>>(allows any non-meta property besides defined ones), then:-
6.1.1. If AnyProperty stereotype's
oneAndOnly="false"(i.e. it allows any property besides the Datatype's defined properties if there is any, which means any JSON property may be added in the schema), then set"additionalProperties"=truein Foo's schema. -
6.1.2. Else (oneAndOnly=true, i.e. only one other property): set
"additionalProperties"=false, and:- 6.1.2.1. If
Foohas optional properties: return the error Unsupported (not allowed in the data model) (ContentDatatype is the onlyAnyPropertywith oneAndOnly=true in the whole data model and indeed has no optional property) - 6.1.2.2. Else (
Foohas no optional property, only required properties) set"minProperties" = "maxProperties" = number_of_defined_properties + 1in theFoo's schema.
- 6.1.2.1. If
-
- If