Access Rule Model (normative) General The introduction in Chapter Introduction has explained in detail the background for AAS Security.The use of Identity Providers and Authentication Flows have been shown, which provide an access token to the client user application. Such access token contains claims as subject attributes which can be used in the Access Rule Model as defined below. In addition, the Access Rule Model contains further ABAC attributes like global attributes or object attributes. Figure XX gives an overview of the Access Rule Model. Section xx defines the text serialization of the Access Rule Model. Section xx defines the JSON schema of the Access Rule Model. The Access Rule Model allows to define Access Rules in a modular way, so that parts can be reused. Attribute Groups can be defined to reuse combinations of attributes. Object Groups can be defined to reuse combinations of objects. Access Control Lists (ACLs) can be defined to reuse combinations of attributes and access rights. Each Access Rule can define an own ACL or reuse an existing one. Each Access Rule can provide access to single objects or object groups. Each Access Rule can define an own Formula or reuse an existing one. The formula decides, if an Access Rule becomes active or not. Only if the overall result of the Formula is valid and true, the Access Rule becomes active. A formula can include nested boolean expressions, comparisons and string operations. A special operation match allows to work with tuples in lists, e.g. specificAssetId. The AAS Query Language and the AAS Access Rules share the same BNF grammar for formula expressions. In addition to the text below, the further details of the formula expressions are explained in https://admin-shell-io.github.io/aas-specs-antora/IDTA-01002/v3.1/general.html#query-language . Grammar for Access Rule Model BNF grammar of Access Rules The following BNF (Backus-Naur-Form) grammar defines the AAS Access Rule Model in a technology neutral form. The grammar includes whitespaces, so that the examples in Examples of Access Rules in text serialization can be validated. The Security Model is explained step by step in the following Chapter Explanation of the Access Rule Model BNF. Examples can be found in Examples of Access Rules in text serialization. The grammar has been tested with BNF playground (*https://bnfplayground.pauliankline.com/). BNF playground allows to check and test the grammar itself and if expressions are correct according to the grammar.* The tested BNF is: <AllAccessPermissionRules> ::= ( "DEFATTRIBUTES" <ws> <StringLiteral> <ws> <AttributeGroup> <ws> )* ( "DEFACLS" <ws> <StringLiteral> <ws> <ACL> <ws> )* ( "DEFOBJECTS" <ws> <StringLiteral> <ws> <ObjectGroup> <ws> )* ( "DEFFORMULAS" <ws> <StringLiteral> <ws> <Condition> <ws> )* ( <AccessPermissionRule> <ws> )* <AccessPermissionRule> ::= "ACCESSRULE:" <ws> ( <ACL> | <UseACL> ) <ws> "OBJECTS:" <ws> ( <SingleObject> <ws> )* ( <UseObjectGroup> <ws> )* "FORMULA:" <ws> ( <Condition> | <UseFormula> ) <ws> ( "FILTER:" <ws> <FragmentObject> <ws> ( <Condition> | <UseFormula> ) <ws> )? <ACL> ::= "ATTRIBUTES:" <ws> ( <SingleAttribute> <ws> )* ( <UseAttributeGroup> <ws> )* "RIGHTS:" <ws> <Right> <ws> ( <Right> <ws> )* "ACCESS:" <ws> <Access> <ws> <UseACL> ::= "USEACLS" <ws> <StringLiteral> <ws> <Right> ::= "CREATE" | "READ" | "UPDATE" | "DELETE" | "EXECUTE" | "VIEW" | "ALL" | "TREE" <Access> ::= "ALLOW" | "DISABLED" <SingleAttribute> ::= <ClaimAttribute> | <GlobalAttribute> | <ReferenceAttribute> <ClaimAttribute> ::= "CLAIM" <ws> "(" <ws> <ClaimLiteral> <ws> ")" <GlobalAttribute> ::= "GLOBAL" <ws> "(" <ws> ( "LOCALNOW" | "UTCNOW" | "CLIENTNOW" | "ANONYMOUS" ) <ws> ")" <ReferenceAttribute> ::= "REFERENCE" <ws> "(" <ws> <ReferenceLiteral> <ws> ")" <AttributeGroup> ::= ( <SingleAttribute> <ws> )* ( <UseAttributeGroup> <ws> )* <UseAttributeGroup> ::= "USEATTRIBUTES" <ws> <StringLiteral> <ws> <SingleObject> ::= <RouteObject> | <IdentifiableObject> | <ReferableObject> | <FragmentObject> | <DescriptorObject> <RouteObject> ::= "ROUTE" <ws> <RouteLiteral> <ws> <IdentifiableObject> ::= "IDENTIFIABLE" <ws> <IdentifiableLiteral> <ws> <ReferableObject> ::= "REFERABLE" <ws> <ReferableLiteral> <ws> <FragmentObject> ::= "FRAGMENT" <ws> <FragmentLiteral> <ws> <DescriptorObject> ::= "DESCRIPTOR" <ws> <DescriptorLiteral> <ws> <ObjectGroup> ::= ( <SingleObject> <ws> )* | ( <UseObjectGroup> <ws> )* <UseObjectGroup> ::= "USEOBJECTS" <ws> <StringLiteral> <ws> <UseFormula> ::= "USEFORMULAS" <ws> <StringLiteral> <ws> <Condition> ::= <logicalExpression> <ws> <logicalExpression> ::= <logicalNestedExpression> | <logicalOrExpression> | <logicalAndExpression> | <logicalNotExpression> | <matchExpression> | <BoolLiteral> | <castToBool> | <singleComparison> <logicalNestedExpression> ::= "(" <ws> <logicalExpression> ")" <ws> <logicalOrExpression> ::= "$or" <ws> "(" <ws> <logicalExpression> ( "," <ws> <logicalExpression> )+ ")" <ws> <logicalAndExpression> ::= "$and" <ws> "(" <ws> <logicalExpression> ( "," <ws> <logicalExpression> )+ ")" <ws> <logicalNotExpression> ::= "$not" <ws> "(" <ws> <logicalExpression> ")" <ws> <matchExpression> ::= ( "$match" <ws> "(" <ws> ( <singleComparison> | <matchExpression> ) ( "," <ws> ( <singleComparison> | <matchExpression> ) )* ")" <ws> ) <singleComparison> ::= <stringComparison> | <numericalComparison> | <hexComparison> | <boolComparison> | <dateTimeComparison> | <timeComparison> <allComparisons> ::= ( "$eq" | "$ne" | "$gt" | "$lt" | "$ge" | "$le" ) <stringComparison> ::= ( ( "$starts-with" | "ends-with" | "$contains" | "$regex") <ws> "(" <ws> <stringOperand> <ws> "," <ws> <stringOperand> <ws> ")" <ws> ) | ( <stringOperand> <ws> <allComparisons> <ws> <stringOperand> <ws> ) | ( <stringOperand> <ws> <allComparisons> <ws> <FieldIdentifierString> <ws> ) | ( <FieldIdentifierString> <ws> <allComparisons> <ws> <stringOperand> <ws> ) <numericalComparison> ::= ( <numericalOperand> <ws> <allComparisons> <ws> <numericalOperand> <ws> ) | ( <numericalOperand> <ws> <allComparisons> <ws> <FieldIdentifierString> <ws> ) | ( <FieldIdentifierString> <ws> <allComparisons> <ws> <numericalOperand> <ws> ) <hexComparison> ::= <hexOperand> <ws> <allComparisons> <ws> <hexOperand> <ws> <boolComparison> ::= <boolOperand> <ws> ( "$eq" | "$ne" ) <ws> <boolOperand> <ws> <dateTimeComparison> ::= <dateTimeOperand> <ws> <allComparisons> <ws> <dateTimeOperand> <ws> <dateTimeToNum> ::= ( "$dayOfWeek" | "$dayOfMonth" | "$month" | "$year" ) <ws> "(" <ws> <dateTimeOperand> <ws> ")" <ws> <timeComparison> ::= <timeOperand> <ws> <allComparisons> <ws> <timeOperand> <ws> <operand> ::= <stringOperand> | <numericalOperand> | <hexOperand> | <boolOperand> | <dateTimeOperand> | <timeOperand> <stringOperand> ::= <FieldIdentifierString> | <StringLiteral> | <castToString> | <SingleAttribute> <numericalOperand> ::= <NumericalLiteral> | <castToNumerical> | <dateTimeToNum> <hexOperand> ::= <HexLiteral> | <castToHex> <boolOperand> ::= <BoolLiteral> | <castToBool> <dateTimeOperand> ::= <DateTimeLiteral> | <castToDateTime> | <GlobalAttribute> <timeOperand> ::= <TimeLiteral> | <castToTime> <castToString> ::= "str" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToNumerical> ::= "num" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToHex> ::= "hex" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToBool> ::= "bool" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToDateTime> ::= "dateTime" <ws> "(" <ws> <stringOperand> <ws> ")" <ws> <castToTime> ::= "time" <ws> "(" <ws> ( <stringOperand> | <dateTimeOperand> ) <ws> ")" <ws> <DateTimeLiteral> ::= <datetime> <ws> <TimeLiteral> ::= <time> <ws> <datetime> ::= <date> <ws> ( "T" | " " ) <ws> <time> <ws> ( <timezone> <ws> )? <date> ::= <year> <ws> "-" <ws> <month> <ws> "-" <ws> <day> <ws> <year> ::= <digit> <ws> <digit> <ws> <digit> <ws> <digit> <ws> <month> ::= <digit> <ws> <digit> <ws> <day> ::= <digit> <ws> <digit> <ws> <time> ::= <hour> <ws> ":" <ws> <minute> <ws> ( ":" <ws> <second> <ws> )? ( "." <ws> <fraction> <ws> )? <timezone> ::= ( "Z" | ( "+" | "-" ) <ws> <hour> <ws> ":" <ws> <minute> <ws> ) <hour> ::= <digit> <ws> <digit> <ws> <minute> ::= <digit> <ws> <digit> <ws> <second> ::= <digit> <ws> <digit> <ws> <fraction> ::= <digit>+ <ws> <digit> ::= [0-9] <ws> <StringLiteral> ::= "\"" ( [A-Z] | [a-z] | [0-9] | "/" | "*" | "[" | "]" | "(" | ")" | " " | "_" | "@" | "#" | "\\" | "+" | "-" | "." | "," | ":" | "$" | "^" | "*" )+ "\"" <ClaimLiteral> ::= <StringLiteral> <ReferenceLiteral> ::= <StringLiteral> <RouteLiteral> ::= <StringLiteral> <IdentifiableLiteral> ::= <StringLiteral> <ReferableLiteral> ::= <StringLiteral> <FragmentLiteral> ::= <StringLiteral> <DescriptorLiteral> ::= <StringLiteral> <NumericalLiteral> ::= ( "+" | "-" )? ( [0-9]+ ( "." [0-9]* )? | "." [0-9]+ ) ( ( "e" | "E" )? [0-9]+ ) <HexLiteral> ::= "16#" ( [0-9] | [A-F] )+ <BoolLiteral> ::= "true" | "false" <FieldIdentifier> ::= <FieldIdentifierString> <FieldIdentifierString> ::= <FieldIdentifierAAS> | <FieldIdentifierSM> | <FieldIdentifierSME> | <FieldIdentifierCD> | <FieldIdentifierAasDescriptor> | <FieldIdentifierSmDescriptor> <FieldIdentifierAAS> ::= "$aas#" ( "idShort" | "id" | "assetInformation.assetKind" | "assetInformation.assetType" | "assetInformation.globalAssetId" | "assetInformation." <SpecificAssetIdsClause> | "submodels." <ReferenceClause> ) <FieldIdentifierSM> ::= "$sm#" ( <SemanticIdClause> | "idShort" | "id" ) <FieldIdentifierSME> ::= "$sme" ( "." <idShortPath> )? "#" ( <SemanticIdClause> | "idShort" | "value" | "valueType" | "language" ) <FieldIdentifierCD> ::= "$cd#" ( "idShort" | "id" ) <ws> <FieldIdentifierAasDescriptor> ::= "$aasdesc#" ( "idShort" | "id" | "assetKind" | "assetType" | "globalAssetId" | <SpecificAssetIdsClause> | "endpoints" ( "[" ( [0-9]* ) "]" )? "." <EndpointClause> | "submodelDescriptors" ( "[" ( [0-9]* ) "]" )? "." <SmDescriptorClause> ) <FieldIdentifierSmDescriptor> ::= "$smdesc#" <SmDescriptorClause> <SmDescriptorClause> ::= ( <SemanticIdClause> | "idShort" | "id" | "endpoints" ( "[" ( [0-9]* ) "]" )? "." <EndpointClause> ) <EndpointClause> ::= "interface" | "protocolinformation.href" <ReferenceClause> ::= ( "type" | "keys" ( "[" ( [0-9]* ) "]" )? ( ".type" | ".value" ) ) <SemanticIdClause> ::= ( "semanticId" | "semanticId." <ReferenceClause> ) <SpecificAssetIdsClause> ::= ( "specificAssetIds" ( "[" ( [0-9]* ) "]" )? ( ".name" | ".value" | ".externalSubjectId" | ".externalSubjectId." <ReferenceClause> ) ) <idShortPath> ::= ( <idShort> ("[" ( [0-9]* ) "]" )? ( "." <idShortPath> )* ) <idShort> ::= ( ( [a-z] | [A-Z] ) ( [a-z] | [A-Z] | [0-9] | "_" )* ) <ws> ::= ( " " | "\t" | "\r" | "\n" )* Explanation of the Access Rule Model BNF General The AAS Access Rule Model can be used to describe access rules. Whether and how access rules are enforced is beyond the specification of the model for access control. The parties involved are supposed to agree on governance and policies. The AAS Access Rule Model uses Attribute Based Access Control (ABAC), i.e. Attributes are used in access rules. By ABAC also Role Based Access Control (RBAC) can be implemented by defining role attributes. Subject Attributes and Roles may be provided as claims in Access Tokens. Attributes in access rules are either claims from an Access Token provided by an Identity Provider, global attributes like actual DATETIME or from a Submodel like a property for a machine state. Objects to be protected are either API Routes, Identifiables (e.g. AAS or Submodel), Referables (e.g. SubmodelElements), Descriptors or Fragments of all those (e.g. AssetId, SemanticId, SpecificAssetId). Reuse The AAS Access Rule Model allows to define modular parts which can be reused in different access rules. The first concept of reuse is groups. Both attributes (DEFATTRIBUTES) and objects (DEFOBJECTS) can be combined into related groups, which may also be used in other groups. The second concept of reuse is Access Control Lists (DEFACLS). An ACL defines which access rights are given for a certain combination of attributes. The third concept of reuse are FORMULAs (DEFFORMULAS), which define a Boolean result when an Access Rule is enabled/disabled. FORMULAs allow to express only expressions with Boolean results, e.g. comparisons. Arithmetic in FORMULAS is currently not supported. Access Rule Model <AllAccessPermissionRules> ::= ( "DEFATTRIBUTES" <ws> <StringLiteral> <ws> <AttributeGroup> <ws> )* ( "DEFACLS" <ws> <StringLiteral> <ws> <ACL> <ws> )* ( "DEFOBJECTS" <ws> <StringLiteral> <ws> <ObjectGroup> <ws> )* ( "DEFFORMULAS" <ws> <StringLiteral> <ws> <Condition> <ws> )* ( <AccessPermissionRule> <ws> )* <AccessPermissionRule> ::= "ACCESSRULE:" <ws> ( <ACL> | <UseACL> ) <ws> "OBJECTS:" <ws> ( <SingleObject> <ws> )* ( <UseObjectGroup> <ws> )* "FORMULA:" <ws> ( <Condition> | <UseFormula> ) <ws> ( "FILTER:" <ws> <FragmentObject> <ws> ( <Condition> | <UseFormula> ) <ws> )? An Access Rule Model defines a list of Access Rules. For reuse in multiple Access Rules it also contains lists of Attribute Groups (DEFATTRIBUTES), Object Groups (DEFOBJECTS), ACLs (DEFACLS) and Formulas (DEFFORMULAS). Such elements defined for reuse get a name. One Access Rule must either directly define an ACL or reuse an existing ACL definition. One access rule may directly list Single Objects or may reuse defined Object Groups. One access rule may directly define a Formula or may reuse a Formula definition. An access rule may optionally include a FILTER, which can be used to further restrict the returned objects. A FILTER is an additional FORMULA, which enables by its boolean expression, which part(s) of the given object(s) can be accessed, i.e. without a FILTER the complete objects are accessed. The FILTER contains a FragmentObject, which defines which part of the accessed object has to be filtered. The related FragmentLiteral defines the Prefix of a FieldIdentifier to be filtered, e.g. "$aasdesc#assetInformation.specificAssetIds[]" defines that the specificAssetIds part shall be filtered. ACL <ACL> ::= "ATTRIBUTES:" <ws> ( <SingleAttribute> <ws> )* ( <UseAttributeGroup> <ws> )* "RIGHTS:" <ws> <Right> <ws> ( <Right> <ws> )* "ACCESS:" <ws> <Access> <ws> <UseACL> ::= "USEACLS" <ws> <StringLiteral> <ws> <Right> ::= "CREATE" | "READ" | "UPDATE" | "DELETE" | "EXECUTE" | "VIEW" | "ALL" | "TREE" <Access> ::= "ALLOW" | "DISABLED" An ACL (Access Control List) defines which access rights are given for a certain combination of attributes. Attributes can be provided as a list of single attributes and/or as a list of names of other attribute groups. The rights in ACLs essentially use the CRUDX pattern, i.e. rights for CREATE, READ, UPDATE, DELETE and EXECUTE can be defined. Without an ALLOW rule any access is forbidden by default. For testing and alternative configuration purposes, an access rule may be DISABLED. To avoid complex conflicting situations, deny rules are not supported. In addition, VIEW allows to see the existence of an element as Id or idShort, but not to read its values and its further attributes. In addition, TREE defines, that further access rules exist within its child elements, which must be processed. ALL is an abbreviation to define all rights. Attributes <SingleAttribute> ::= <ClaimAttribute> | <GlobalAttribute> | <ReferenceAttribute> <ClaimAttribute> ::= "CLAIM" <ws> "(" <ws> <ClaimLiteral> <ws> ")" <GlobalAttribute> ::= "GLOBAL" <ws> "(" <ws> ( "LOCALNOW" | "UTCNOW" | "CLIENTNOW" | "ANONYMOUS" ) <ws> ")" <ReferenceAttribute> ::= "REFERENCE" <ws> "(" <ws> <ReferenceLiteral> <ws> ")" <AttributeGroup> ::= ( <SingleAttribute> <ws> )* ( <UseAttributeGroup> <ws> )* <UseAttributeGroup> ::= "USEATTRIBUTES" <ws> <StringLiteral> <ws> Single Attributes are either claims from an Access Token provided by an Identity Provider, global attributes like actual DATETIME or references to a SubmodelElement e.g. to a property for a machine state. An Attribute Group defines a list of single attributes and/or a list of names of other attribute groups. Global Attributes are: LOCALNOW - Date and time of server according ISO 8601 in local time zone UTCNOW - Date and time of server according ISO 8601 as UTC time CLIENTNOW - Date and time of client according ISO 8601, provided as claim in access token ANONYMOUS - Tag for anonymous and non-authenticated user, i.e. no access token References in ReferenceAttributes are defined in Section 5.2.1.8 “Text Serialization of Values of Type Reference”. Objects <SingleObject> ::= <RouteObject> | <IdentifiableObject> | <ReferableObject> | <FragmentObject> | <DescriptorObject> <RouteObject> ::= "ROUTE" <ws> <RouteLiteral> <ws> <IdentifiableObject> ::= "IDENTIFIABLE" <ws> <IdentifiableLiteral> <ws> <ReferableObject> ::= "REFERABLE" <ws> <ReferableLiteral> <ws> <FragmentObject> ::= "FRAGMENT" <ws> <FragmentLiteral> <ws> <DescriptorObject> ::= "DESCRIPTOR" <ws> <DescriptorLiteral> <ws> <ObjectGroup> ::= ( <SingleObject> <ws> )* | ( <UseObjectGroup> <ws> )* <UseObjectGroup> ::= "USEOBJECTS" <ws> <StringLiteral> <ws> Objects to be protected are either API Routes, Identifiables (e.g. AAS or Submodel), Referables (e.g. SubmodelElements), Descriptors or Fragments of those (e.g. AssetId, SemanticId, SpecificAssetId). Routes may use * or end with a *, which means that all routes with a given prefix are valid. References to IdentifiableObjects, ReferableObjects, FragmentObjects and DescriptorObjects are defined in Section 5.2.1.8 “Text Serialization of Values of Type Reference”. An Object Group defines a list of single objects and/or a list of names of other object groups. Formulas <UseFormula> ::= "USEFORMULAS" <ws> <StringLiteral> <ws> <Condition> ::= <logicalExpression> <ws> <logicalExpression> ::= <logicalNestedExpression> | <logicalOrExpression> | <logicalAndExpression> | <logicalNotExpression> | <matchExpression> | <BoolLiteral> | <castToBool> | <singleComparison> <logicalNestedExpression> ::= "(" <ws> <logicalExpression> ")" <ws> <logicalOrExpression> ::= "$or" <ws> "(" <ws> <logicalExpression> ( "," <ws> <logicalExpression> )+ ")" <ws> <logicalAndExpression> ::= "$and" <ws> "(" <ws> <logicalExpression> ( "," <ws> <logicalExpression> )+ ")" <ws> <logicalNotExpression> ::= "$not" <ws> "(" <ws> <logicalExpression> ")" <ws> <matchExpression> ::= ( "$match" <ws> "(" <ws> ( <singleComparison> | <matchExpression> ) ( "," <ws> ( <singleComparison> | <matchExpression> ) )* ")" <ws> ) <singleComparison> ::= <stringComparison> | <numericalComparison> | <hexComparison> | <boolComparison> | <dateTimeComparison> | <timeComparison> <allComparisons> ::= ( "$eq" | "$ne" | "$gt" | "$lt" | "$ge" | "$le" ) <stringComparison> ::= ( ( "$starts-with" | "ends-with" | "$contains" | "$regex") <ws> "(" <ws> <stringOperand> <ws> "," <ws> <stringOperand> <ws> ")" <ws> ) | ( <stringOperand> <ws> <allComparisons> <ws> <stringOperand> <ws> ) | ( <stringOperand> <ws> <allComparisons> <ws> <FieldIdentifierString> <ws> ) | ( <FieldIdentifierString> <ws> <allComparisons> <ws> <stringOperand> <ws> ) <numericalComparison> ::= ( <numericalOperand> <ws> <allComparisons> <ws> <numericalOperand> <ws> ) | ( <numericalOperand> <ws> <allComparisons> <ws> <FieldIdentifierString> <ws> ) | ( <FieldIdentifierString> <ws> <allComparisons> <ws> <numericalOperand> <ws> ) <hexComparison> ::= <hexOperand> <ws> <allComparisons> <ws> <hexOperand> <ws> <boolComparison> ::= <boolOperand> <ws> ( "$eq" | "$ne" ) <ws> <boolOperand> <ws> <dateTimeComparison> ::= <dateTimeOperand> <ws> <allComparisons> <ws> <dateTimeOperand> <ws> <dateTimeToNum> ::= ( "$dayOfWeek" | "$dayOfMonth" | "$month" | "$year" ) <ws> "(" <ws> <dateTimeOperand> <ws> ")" <ws> <timeComparison> ::= <timeOperand> <ws> <allComparisons> <ws> <timeOperand> <ws> <operand> ::= <stringOperand> | <numericalOperand> | <hexOperand> | <boolOperand> | <dateTimeOperand> | <timeOperand> <stringOperand> ::= <FieldIdentifierString> | <StringLiteral> | <castToString> | <SingleAttribute> <numericalOperand> ::= <NumericalLiteral> | <castToNumerical> | <dateTimeToNum> <hexOperand> ::= <HexLiteral> | <castToHex> <boolOperand> ::= <BoolLiteral> | <castToBool> <dateTimeOperand> ::= <DateTimeLiteral> | <castToDateTime> | <GlobalAttribute> <timeOperand> ::= <TimeLiteral> | <castToTime> <castToString> ::= "str" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToNumerical> ::= "num" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToHex> ::= "hex" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToBool> ::= "bool" <ws> "(" <ws> <operand> <ws> ")" <ws> <castToDateTime> ::= "dateTime" <ws> "(" <ws> <stringOperand> <ws> ")" <ws> <castToTime> ::= "time" <ws> "(" <ws> ( <stringOperand> | <dateTimeOperand> ) <ws> ")" <ws> FORMULAs define a logical expression with a Boolean result when an Access Rule is enabled/disabled. FORMULAs allow to express only expressions with Boolean results. Arithmetic in FORMULAS is currently not supported. Nesting Operations create combinations of several expression, where any, all or none of the combined formula needs to be enabled: <logicalNestedExpression>, <logicalOrExpression>, <logicalAndExpression>, <logicalNotExpression>. String Comparison Operations compare or match the first given argument (left argument) with the second given argument (right argument). $eq, $ne, $gt, $lt, $ge, $le make an alphabetic string comparison. $starts-with, $ends-with, $contains and $regex check, if the first given argument is part of the second argument or if the first argument matches with the given REGEX. Numerical Comparison Operations compare the first given argument (left argument) with the second given argument (right argument). Since AAS also supports XS Datatypes Hex, Bool, DateTime and Time, related comparisons are available accordingly. For specific comparisons datatypes can be casted to the other datatypes. Specific operations exist to extract parts from DateTime, i.e. $dayOfWeek, $dayOfMonth, $month, $year. This enables access rules related to week days or specific times in the year. An important special operation is $match, which can be used with any element containing a list of elements, e.g. semanticId[], specificAssetId[], SubmodelElementList or SubmodelElementCollection. The list element is written with [] to express, that $match shall check if a certain expression is true for at least one element in the list. Text Serialization of Values of Type Reference References are used in ReferenceAttributes, IdentifiableObjects, ReferableObjects, FragmentObjects and DescriptorObjects for the corresponding ReferenceLiterals, IdentifiableLiterals, ReferableLiterals, FragmentLiterals and DescriptorLiterals. Such references use the Part 1 Mapping in Section “Text Serialization of Values of Type Reference” for specific instances of elements, e.g. an AAS, a Submodel, a ConceptDescription or a specific SubmodelElement. See: https://admin-shell-io.github.io/aas-specs-antora/IDTA-01001/v3.1/mappings/mappings.html#reference-serialization Access Rules may also be defined for all Identifiables of the Keytypes AssetAdministrationShell, Submodel or ConceptDescription. In this case an IdentifiableLiteral uses the format “(AssetAdministrationShell)*”, “(Submodel)*” and “(ConceptDescription)*”. Access Rules extend the Keytypes of Part 1 by “(aasDesc)” for AAS Descriptors and “(smdesc)” for submodel descriptors. To define all descriptors “(aasDesc)*” or “(smdesc)*” may be used in DescriptorLiterals accordingly. JSON Serialization of Access Rule Model The AAS Access Rule model can also be defined as a JSON schema. Since the related JSON schema shall also allow automatic code generation, specific constraints must be fulfilled by such JSON schema. The use of “oneof” is limited and type information for objects must be available. It shall also be possible to check a JSON with the JSON schema. Examples can be found in Examples of Access Rules in JSON serialization. The following schema meets such constraints: { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Common JSON Schema for AAS Queries and Access Rules", "description": "This schema contains all classes that are shared between the AAS Query Language and the AAS Access Rule Language.", "definitions": { "standardString": { "type": "string", "pattern": "^(?!\\$).*" }, "modelStringPattern": { "type": "string", "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.(?:specificAssetIds\\[[0-9]*\\](?:\\.(?:name|value|externalSubjectId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(?:type|value))?)?)?)|submodels\\.(?:type|keys\\[\\d*\\](?:\\.(?:type|value))?))|submodels\\.(type|keys\\[\\d*\\](?:\\.(type|value))?))|(?:\\$sm#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id))|(?:\\$sme(?:\\.[a-zA-Z][a-zA-Z0-9_]*\\[[0-9]*\\]?(?:\\.[a-zA-Z][a-zA-Z0-9_]*\\[[0-9]*\\]?)*)?#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|value|valueType|language))|(?:\\$cd#(?:idShort|id)))|(?:\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]?(?:\\.(name|value|externalSubjectId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?)?)|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href))))|(?:\\$smdesc#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href)))$" }, "hexLiteralPattern": { "type": "string", "pattern": "^16#[0-9A-F]+$" }, "dateTimeLiteralPattern": { "type": "string", "format": "date-time" }, "timeLiteralPattern": { "type": "string", "pattern": "^[0-9][0-9]:[0-9][0-9](:[0-9][0-9])?$" }, "Value": { "type": "object", "properties": { "$field": { "$ref": "#/definitions/modelStringPattern" }, "$strVal": { "$ref": "#/definitions/standardString" }, "$attribute": { "$ref": "#/definitions/attributeItem" }, "$numVal": { "type": "number" }, "$hexVal": { "$ref": "#/definitions/hexLiteralPattern" }, "$dateTimeVal": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$timeVal": { "$ref": "#/definitions/timeLiteralPattern" }, "$boolean": { "type": "boolean" }, "$strCast": { "$ref": "#/definitions/Value" }, "$numCast": { "$ref": "#/definitions/Value" }, "$hexCast": { "$ref": "#/definitions/Value" }, "$boolCast": { "$ref": "#/definitions/Value" }, "$dateTimeCast": { "$ref": "#/definitions/Value" }, "$timeCast": { "$ref": "#/definitions/Value" }, "$dayOfWeek": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$dayOfMonth": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$month": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$year": { "$ref": "#/definitions/dateTimeLiteralPattern" } }, "oneOf": [ { "required": [ "$field" ] }, { "required": [ "$strVal" ] }, { "required": [ "$attribute" ] }, { "required": [ "$numVal" ] }, { "required": [ "$hexVal" ] }, { "required": [ "$dateTimeVal" ] }, { "required": [ "$timeVal" ] }, { "required": [ "$boolean" ] }, { "required": [ "$strCast" ] }, { "required": [ "$numCast" ] }, { "required": [ "$hexCast" ] }, { "required": [ "$boolCast" ] }, { "required": [ "$dateTimeCast" ] }, { "required": [ "$timeCast" ] }, { "required": [ "$dayOfWeek" ] }, { "required": [ "$dayOfMonth" ] }, { "required": [ "$month" ] }, { "required": [ "$year" ] } ], "additionalProperties": false }, "stringValue": { "type": "object", "properties": { "$field": { "$ref": "#/definitions/modelStringPattern" }, "$strVal": { "$ref": "#/definitions/standardString" }, "$strCast": { "$ref": "#/definitions/Value" }, "$attribute": { "$ref": "#/definitions/attributeItem" } }, "oneOf": [ { "required": [ "$field" ] }, { "required": [ "$strVal" ] }, { "required": [ "$strCast" ] }, { "required": [ "$attribute" ] } ], "additionalProperties": false }, "comparisonItems": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "$ref": "#/definitions/Value" } }, "stringItems": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "$ref": "#/definitions/stringValue" } }, "matchExpression": { "type": "object", "properties": { "$match": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/matchExpression" } }, "$eq": { "$ref": "#/definitions/comparisonItems" }, "$ne": { "$ref": "#/definitions/comparisonItems" }, "$gt": { "$ref": "#/definitions/comparisonItems" }, "$ge": { "$ref": "#/definitions/comparisonItems" }, "$lt": { "$ref": "#/definitions/comparisonItems" }, "$le": { "$ref": "#/definitions/comparisonItems" }, "$contains": { "$ref": "#/definitions/stringItems" }, "$starts-with": { "$ref": "#/definitions/stringItems" }, "$ends-with": { "$ref": "#/definitions/stringItems" }, "$regex": { "$ref": "#/definitions/stringItems" }, "$boolean": { "type": "boolean" } }, "oneOf": [ { "required": [ "$eq" ] }, { "required": [ "$ne" ] }, { "required": [ "$gt" ] }, { "required": [ "$ge" ] }, { "required": [ "$lt" ] }, { "required": [ "$le" ] }, { "required": [ "$contains" ] }, { "required": [ "$starts-with" ] }, { "required": [ "$ends-with" ] }, { "required": [ "$regex" ] }, { "required": [ "$boolean" ] }, { "required": [ "$match" ] } ], "additionalProperties": false }, "logicalExpression": { "type": "object", "properties": { "$and": { "type": "array", "minItems": 2, "items": { "$ref": "#/definitions/logicalExpression" } }, "$match": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/matchExpression" } }, "$or": { "type": "array", "minItems": 2, "items": { "$ref": "#/definitions/logicalExpression" } }, "$not": { "$ref": "#/definitions/logicalExpression" }, "$eq": { "$ref": "#/definitions/comparisonItems" }, "$ne": { "$ref": "#/definitions/comparisonItems" }, "$gt": { "$ref": "#/definitions/comparisonItems" }, "$ge": { "$ref": "#/definitions/comparisonItems" }, "$lt": { "$ref": "#/definitions/comparisonItems" }, "$le": { "$ref": "#/definitions/comparisonItems" }, "$contains": { "$ref": "#/definitions/stringItems" }, "$starts-with": { "$ref": "#/definitions/stringItems" }, "$ends-with": { "$ref": "#/definitions/stringItems" }, "$regex": { "$ref": "#/definitions/stringItems" }, "$boolean": { "type": "boolean" } }, "oneOf": [ { "required": [ "$and" ] }, { "required": [ "$or" ] }, { "required": [ "$not" ] }, { "required": [ "$eq" ] }, { "required": [ "$ne" ] }, { "required": [ "$gt" ] }, { "required": [ "$ge" ] }, { "required": [ "$lt" ] }, { "required": [ "$le" ] }, { "required": [ "$contains" ] }, { "required": [ "$starts-with" ] }, { "required": [ "$ends-with" ] }, { "required": [ "$regex" ] }, { "required": [ "$boolean" ] }, { "required": [ "$match" ] } ], "additionalProperties": false }, "attributeItem": { "oneOf": [ { "required": [ "CLAIM" ] }, { "required": [ "GLOBAL" ] }, { "required": [ "REFERENCE" ] } ], "properties": { "CLAIM": { "type": "string" }, "GLOBAL": { "type": "string", "enum": [ "LOCALNOW", "UTCNOW", "CLIENTNOW", "ANONYMOUS" ] }, "REFERENCE": { "type": "string" } }, "additionalProperties": false }, "objectItem": { "oneOf": [ { "required": [ "ROUTE" ] }, { "required": [ "IDENTIFIABLE" ] }, { "required": [ "REFERABLE" ] }, { "required": [ "FRAGMENT" ] }, { "required": [ "DESCRIPTOR" ] } ], "properties": { "ROUTE": { "type": "string" }, "IDENTIFIABLE": { "type": "string" }, "REFERABLE": { "type": "string" }, "FRAGMENT": { "type": "string" }, "DESCRIPTOR": { "type": "string" } }, "additionalProperties": false }, "rightsEnum": { "type": "string", "enum": [ "CREATE", "READ", "UPDATE", "DELETE", "EXECUTE", "VIEW", "ALL", "TREE" ], "additionalProperties": false }, "ACL": { "type": "object", "properties": { "ATTRIBUTES": { "type": "array", "items": { "$ref": "#/definitions/attributeItem" } }, "USEATTRIBUTES": { "type": "string" }, "RIGHTS": { "type": "array", "items": { "$ref": "#/definitions/rightsEnum" } }, "ACCESS": { "type": "string", "enum": [ "ALLOW", "DISABLED" ] } }, "required": [ "RIGHTS", "ACCESS" ], "oneOf": [ { "required": [ "ATTRIBUTES" ] }, { "required": [ "USEATTRIBUTES" ] } ], "additionalProperties": false }, "AccessPermissionRule": { "type": "object", "properties": { "ACL": { "$ref": "#/definitions/ACL" }, "USEACL": { "type": "string" }, "OBJECTS": { "type": "array", "items": { "$ref": "#/definitions/objectItem" }, "additionalProperties": false }, "USEOBJECTS": { "type": "array", "items": { "type": "string" } }, "FORMULA": { "$ref": "#/definitions/logicalExpression", "additionalProperties": false }, "USEFORMULA": { "type": "string" }, "FRAGMENT": { "type": "string" }, "FILTER": { "$ref": "#/definitions/logicalExpression", "additionalProperties": false }, "USEFILTER": { "type": "string" } }, "oneOf": [ { "required": [ "ACL" ] }, { "required": [ "USEACL" ] } ], "oneOf": [ { "required": [ "OBJECTS" ] }, { "required": [ "USEOBJECTS" ] } ], "oneOf": [ { "required": [ "FORMULA" ] }, { "required": [ "USEFORMULA" ] } ], "additionalProperties": false } }, "type": "object", "properties": { "Query": { "type": "object", "properties": { "$select": { "type": "string", "pattern": "^id$" }, "$condition": { "$ref": "#/definitions/logicalExpression" } }, "required": [ "$condition" ], "additionalProperties": false }, "AllAccessPermissionRules": { "type": "object", "properties": { "DEFATTRIBUTES": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "attributes": { "type": "array", "items": { "$ref": "#/definitions/attributeItem" } } }, "required": [ "name", "attributes" ], "additionalProperties": false } }, "DEFACLS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "acl": { "$ref": "#/definitions/ACL" } }, "required": [ "name", "acl" ], "additionalProperties": false } }, "DEFOBJECTS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "objects": { "type": "array", "items": { "$ref": "#/definitions/objectItem" } }, "USEOBJECTS": { "type": "array", "items": { "type": "string" } } }, "required": [ "name" ], "oneOf": [ { "required": [ "objects" ] }, { "required": [ "USEOBJECTS" ] } ], "additionalProperties": false } }, "DEFFORMULAS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "formula": { "$ref": "#/definitions/logicalExpression" } }, "required": [ "name", "formula" ], "additionalProperties": false } }, "rules": { "type": "array", "items": { "$ref": "#/definitions/AccessPermissionRule" } } }, "required": [ "rules" ], "additionalProperties": false } }, "oneOf": [ { "required": [ "Query" ] }, { "required": [ "AllAccessPermissionRules" ] } ], "additionalProperties": false } Explanation of the Access Rule Model JSON schema General The AAS Access Rule Model can be used to describe access rules. Whether and how access rules are enforced is beyond the specification of the model for access control. The parties involved are supposed to agree on governance and policies. Access Rule Model The Access Rules BNF grammar is expressed in JSON schema syntax. Please refer to the detailed step by step explanation of the grammar. { "definitions": { "attributeItem": { "oneOf": [ { "required": [ "CLAIM" ] }, { "required": [ "GLOBAL" ] }, { "required": [ "REFERENCE" ] } ], "properties": { "CLAIM": { "type": "string" }, "GLOBAL": { "type": "string", "enum": [ "LOCALNOW", "UTCNOW", "CLIENTNOW", "ANONYMOUS" ] }, "REFERENCE": { "type": "string" } }, "additionalProperties": false }, "objectItem": { "oneOf": [ { "required": [ "ROUTE" ] }, { "required": [ "IDENTIFIABLE" ] }, { "required": [ "REFERABLE" ] }, { "required": [ "FRAGMENT" ] }, { "required": [ "DESCRIPTOR" ] } ], "properties": { "ROUTE": { "type": "string" }, "IDENTIFIABLE": { "type": "string" }, "REFERABLE": { "type": "string" }, "FRAGMENT": { "type": "string" }, "DESCRIPTOR": { "type": "string" } }, "additionalProperties": false }, "rightsEnum": { "type": "string", "enum": [ "CREATE", "READ", "UPDATE", "DELETE", "EXECUTE", "VIEW", "ALL", "TREE" ], "additionalProperties": false }, "ACL": { "type": "object", "properties": { "ATTRIBUTES": { "type": "array", "items": { "$ref": "#/definitions/attributeItem" } }, "USEATTRIBUTES": { "type": "string" }, "RIGHTS": { "type": "array", "items": { "$ref": "#/definitions/rightsEnum" } }, "ACCESS": { "type": "string", "enum": [ "ALLOW", "DISABLED" ] } }, "required": [ "RIGHTS", "ACCESS" ], "oneOf": [ { "required": [ "ATTRIBUTES" ] }, { "required": [ "USEATTRIBUTES" ] } ], "additionalProperties": false }, "AccessPermissionRule": { "type": "object", "properties": { "ACL": { "$ref": "#/definitions/ACL" }, "USEACL": { "type": "string" }, "OBJECTS": { "type": "array", "items": { "$ref": "#/definitions/objectItem" }, "additionalProperties": false }, "USEOBJECTS": { "type": "array", "items": { "type": "string" } }, "FORMULA": { "$ref": "#/definitions/logicalExpression", "additionalProperties": false }, "USEFORMULA": { "type": "string" }, "FRAGMENT": { "type": "string" }, "FILTER": { "$ref": "#/definitions/logicalExpression", "additionalProperties": false }, "USEFILTER": { "type": "string" } }, "oneOf": [ { "required": [ "ACL" ] }, { "required": [ "USEACL" ] } ], "oneOf": [ { "required": [ "OBJECTS" ] }, { "required": [ "USEOBJECTS" ] } ], "oneOf": [ { "required": [ "FORMULA" ] }, { "required": [ "USEFORMULA" ] } ], "additionalProperties": false } }, "type": "object", "properties": { "Query": { "type": "object", "properties": { "$select": { "type": "string", "pattern": "^id$" }, "$condition": { "$ref": "#/definitions/logicalExpression" } }, "required": [ "$condition" ], "additionalProperties": false }, "AllAccessPermissionRules": { "type": "object", "properties": { "DEFATTRIBUTES": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "attributes": { "type": "array", "items": { "$ref": "#/definitions/attributeItem" } } }, "required": [ "name", "attributes" ], "additionalProperties": false } }, "DEFACLS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "acl": { "$ref": "#/definitions/ACL" } }, "required": [ "name", "acl" ], "additionalProperties": false } }, "DEFOBJECTS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "objects": { "type": "array", "items": { "$ref": "#/definitions/objectItem" } }, "USEOBJECTS": { "type": "array", "items": { "type": "string" } } }, "required": [ "name" ], "oneOf": [ { "required": [ "objects" ] }, { "required": [ "USEOBJECTS" ] } ], "additionalProperties": false } }, "DEFFORMULAS": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "formula": { "$ref": "#/definitions/logicalExpression" } }, "required": [ "name", "formula" ], "additionalProperties": false } }, "rules": { "type": "array", "items": { "$ref": "#/definitions/AccessPermissionRule" } } }, "required": [ "rules" ], "additionalProperties": false } }, "oneOf": [ { "required": [ "Query" ] }, { "required": [ "AllAccessPermissionRules" ] } ], "additionalProperties": false } Formulas and logical expressions A detailed step by step explanation follows below the JSON schema code. "definitions": { "standardString": { "type": "string", "pattern": "^(?!\\$).*" }, "modelStringPattern": { "type": "string", "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.(?:specificAssetIds\\[[0-9]*\\](?:\\.(?:name|value|externalSubjectId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(?:type|value))?)?)?)|submodels\\.(?:type|keys\\[\\d*\\](?:\\.(?:type|value))?))|submodels\\.(type|keys\\[\\d*\\](?:\\.(type|value))?))|(?:\\$sm#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id))|(?:\\$sme(?:\\.[a-zA-Z][a-zA-Z0-9_]*\\[[0-9]*\\]?(?:\\.[a-zA-Z][a-zA-Z0-9_]*\\[[0-9]*\\]?)*)?#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|value|valueType|language))|(?:\\$cd#(?:idShort|id)))|(?:\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]?(?:\\.(name|value|externalSubjectId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?)?)|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href))))|(?:\\$smdesc#(?:semanticId(?:\\.type|\\.keys\\[\\d*\\](?:\\.(type|value))?)?|idShort|id|endpoints\\[[0-9]*\\]\\.(interface|protocolinformation\\.href)))$" }, "hexLiteralPattern": { "type": "string", "pattern": "^16#[0-9A-F]+$" }, "dateTimeLiteralPattern": { "type": "string", "format": "date-time" }, "timeLiteralPattern": { "type": "string", "pattern": "^[0-9][0-9]:[0-9][0-9](:[0-9][0-9])?$" }, "Value": { "type": "object", "properties": { "$field": { "$ref": "#/definitions/modelStringPattern" }, "$strVal": { "$ref": "#/definitions/standardString" }, "$attribute": { "$ref": "#/definitions/attributeItem" }, "$numVal": { "type": "number" }, "$hexVal": { "$ref": "#/definitions/hexLiteralPattern" }, "$dateTimeVal": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$timeVal": { "$ref": "#/definitions/timeLiteralPattern" }, "$boolean": { "type": "boolean" }, "$strCast": { "$ref": "#/definitions/Value" }, "$numCast": { "$ref": "#/definitions/Value" }, "$hexCast": { "$ref": "#/definitions/Value" }, "$boolCast": { "$ref": "#/definitions/Value" }, "$dateTimeCast": { "$ref": "#/definitions/Value" }, "$timeCast": { "$ref": "#/definitions/Value" }, "$dayOfWeek": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$dayOfMonth": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$month": { "$ref": "#/definitions/dateTimeLiteralPattern" }, "$year": { "$ref": "#/definitions/dateTimeLiteralPattern" } }, "oneOf": [ { "required": [ "$field" ] }, { "required": [ "$strVal" ] }, { "required": [ "$attribute" ] }, { "required": [ "$numVal" ] }, { "required": [ "$hexVal" ] }, { "required": [ "$dateTimeVal" ] }, { "required": [ "$timeVal" ] }, { "required": [ "$boolean" ] }, { "required": [ "$strCast" ] }, { "required": [ "$numCast" ] }, { "required": [ "$hexCast" ] }, { "required": [ "$boolCast" ] }, { "required": [ "$dateTimeCast" ] }, { "required": [ "$timeCast" ] }, { "required": [ "$dayOfWeek" ] }, { "required": [ "$dayOfMonth" ] }, { "required": [ "$month" ] }, { "required": [ "$year" ] } ], "additionalProperties": false }, "stringValue": { "type": "object", "properties": { "$field": { "$ref": "#/definitions/modelStringPattern" }, "$strVal": { "$ref": "#/definitions/standardString" }, "$strCast": { "$ref": "#/definitions/Value" }, "$attribute": { "$ref": "#/definitions/attributeItem" } }, "oneOf": [ { "required": [ "$field" ] }, { "required": [ "$strVal" ] }, { "required": [ "$strCast" ] }, { "required": [ "$attribute" ] } ], "additionalProperties": false }, "comparisonItems": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "$ref": "#/definitions/Value" } }, "stringItems": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "$ref": "#/definitions/stringValue" } }, "matchExpression": { "type": "object", "properties": { "$match": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/matchExpression" } }, "$eq": { "$ref": "#/definitions/comparisonItems" }, "$ne": { "$ref": "#/definitions/comparisonItems" }, "$gt": { "$ref": "#/definitions/comparisonItems" }, "$ge": { "$ref": "#/definitions/comparisonItems" }, "$lt": { "$ref": "#/definitions/comparisonItems" }, "$le": { "$ref": "#/definitions/comparisonItems" }, "$contains": { "$ref": "#/definitions/stringItems" }, "$starts-with": { "$ref": "#/definitions/stringItems" }, "$ends-with": { "$ref": "#/definitions/stringItems" }, "$regex": { "$ref": "#/definitions/stringItems" }, "$boolean": { "type": "boolean" } }, "oneOf": [ { "required": [ "$eq" ] }, { "required": [ "$ne" ] }, { "required": [ "$gt" ] }, { "required": [ "$ge" ] }, { "required": [ "$lt" ] }, { "required": [ "$le" ] }, { "required": [ "$contains" ] }, { "required": [ "$starts-with" ] }, { "required": [ "$ends-with" ] }, { "required": [ "$regex" ] }, { "required": [ "$boolean" ] }, { "required": [ "$match" ] } ], "additionalProperties": false }, "logicalExpression": { "type": "object", "properties": { "$and": { "type": "array", "minItems": 2, "items": { "$ref": "#/definitions/logicalExpression" } }, "$match": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/matchExpression" } }, "$or": { "type": "array", "minItems": 2, "items": { "$ref": "#/definitions/logicalExpression" } }, "$not": { "$ref": "#/definitions/logicalExpression" }, "$eq": { "$ref": "#/definitions/comparisonItems" }, "$ne": { "$ref": "#/definitions/comparisonItems" }, "$gt": { "$ref": "#/definitions/comparisonItems" }, "$ge": { "$ref": "#/definitions/comparisonItems" }, "$lt": { "$ref": "#/definitions/comparisonItems" }, "$le": { "$ref": "#/definitions/comparisonItems" }, "$contains": { "$ref": "#/definitions/stringItems" }, "$starts-with": { "$ref": "#/definitions/stringItems" }, "$ends-with": { "$ref": "#/definitions/stringItems" }, "$regex": { "$ref": "#/definitions/stringItems" }, "$boolean": { "type": "boolean" } }, "oneOf": [ { "required": [ "$and" ] }, { "required": [ "$or" ] }, { "required": [ "$not" ] }, { "required": [ "$eq" ] }, { "required": [ "$ne" ] }, { "required": [ "$gt" ] }, { "required": [ "$ge" ] }, { "required": [ "$lt" ] }, { "required": [ "$le" ] }, { "required": [ "$contains" ] }, { "required": [ "$starts-with" ] }, { "required": [ "$ends-with" ] }, { "required": [ "$regex" ] }, { "required": [ "$boolean" ] }, { "required": [ "$match" ] } ], "additionalProperties": false } } The provided JSON schema includes a modelStringPattern starting with a $, so that the syntax of model elements can be checked by the schema, e.g. $sm.idShort. String, number and boolean are supported by JSON itself. Specific patterns with regular expressions are provided for datatypes Hex, DateTime and Time: hexLiteralPattern, dateTimeLiteralPattern and timeLiteralPattern. Value is used for comparisons and StringValue is used for the specific string operations. For type safety and automatic code generation, each possible type is available as an own object: String values can be given by $field, $strVal, $attribute oder $strCast. Numerical values can be given by $numVal or $numCast. Hex values can be given by $hexVal or $hexCast. Bool values can be given by $boolean or $boolCast. DateTime values can be given by $dateTimeVal or $dateTimeCast. Time values can be given by $timeVal or $timeCast. Casts allow any of the values as input and convert this to the given type if possible. Parts of DateTime values can be extracted as numbers: $dayOfWeek extracts the day of week as number, starting with 0 for Sunday. $dayOfMonth, $month, $year extract the related part as number. If a conversion or any other operation is invalid, the complete expression has to be treated as invalid. An error message shall be generated and the result of the complete expression becomes FALSE, so that the access is not allowed and/or the filter is empty. To allow the use of different types in operations, arrays are used for parameters. comparisonItems is used for comparisons and stringItems is used for specific string operations. logicalExpressions and match can be recursively nested. Exchange of Access Rules Business Partners may be interested to exchange Access Rules. As explained as an example above, a robot manufacturer suggests that for the robot the following roles shall be defined: machine setter, operator and a maintenance role. He also suggests permissions for these roles, e.g. an installer (integrator) does have write-access to the program of the robot, but an operator does not. Providing such suggested access rules, makes the integration of the operator much easier. The oprator can copy and paste the access rules into his AAS implementation and only needs to make adjustments. The enforcement of Acess Rules is implementation specific. This specification defines the text serialization of access rules and the JSON schema serialization of access rules. The support of both is optional and not mandatory. The JSON schema serialization is recommended. Such serialization provides the possibility to exchange access rules. An implementation may even store such serialized access rules in submodel elements BLOB or FILE, so that these can be accessed by the API and can be protected by access rules itself. API Queries and Access Rules Version 3.1 of the AAS API defines queries and uses the same grammar and same JSON schema to define queries. The JSON schema serialization is used in the related API operations. In addition, using the same concepts will be needed for large amounts of AAS data. Querying such large amounts of data and protecting such data with Access Rules requires optimized access of data. Database queries may combine the filter expression provided by the client query with the FOMULAs of the Access Rules on the server.