From 6c4c5b4b276a4b66e1327c049168123157d76e38 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Mon, 29 Jun 2026 09:25:20 +0200 Subject: [PATCH 1/8] DR-009-ACL-Concept: Generic Format for Access Control List Introducing a common format for an Access Control List (Crypto, SOME/IP, IPC and further potential usecases), such that it is only required to use one common parser, one common format for reviews and also one common "ACL Manager" aka editor for ACLs and also compiler for the ACL into a binary format. Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 124 ++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/design_decisions/DR-009-ACL-Concept.md diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md new file mode 100644 index 00000000000..61c661fc08c --- /dev/null +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -0,0 +1,124 @@ +.. dec_rec:: One Format for Access Control List(s) (ACL) + :id: dec_rec__platform__acl_concept + :status: proposed + :version: 1 + :affects: + + Context + ------- + Access Control is required on multiple components; i.e.: + + - IPC (LoLa) + Who is allowed to publish which services (who can create/modify a file in the according directory) + For Service Providers: Once the IPC Channel/SharedMemory is created, whom to grant which rights to what area (data/control) + This permissions will be based on uid. + + - SOME/IPC + Same to IPC, except the permissions will be based on IP address / netmask. + In addition: Should TLS be enforced for a service? Should IP & MACsec be active as basis for a certain service? + + - Crypto + Needs to know who (which application - i.e. which uid (every application shall run as own user)) + -- created/owns a key + -- is allowed to write/change a key + -- is allowed to use a key for any operations (e.g. sign/verify/encrypt/decrypt/keyderive/etc.) + -- is allowed to read/extract a key (e.g. pub keys) + + Consequences + ------------ + To prevent each component from implementing compeletley own mechanism for persmission enforcement; the decision schould be an alignment on a common ACL format, so that all components can use: + - the same parser as a baselib to read the ACL + - (optionally) the same "ACLHandler" to update/edit and recompile the ACL + One additional big advantage of a harmonized ACL is that: + - it is easier to review (security reviews, etc.) + - it is easier to debug + - only one parser needs to be tested in depth + - updates due to parser vulnerabilities can be centrallized + + The base proposal is as follows: + - a json file as configuration + - for runtime efficiency: compilation of the json file to a flatbuffer/binary file + + Proposed json format & properties: + + { + "policyVersion": 1, + "policyId": "example-acl-policy-001", + "defaultEffect": "deny", + "generatedBy": "install-update-manager", + "generatedAt": "2026-06-17T14:28:00Z", + + "services": + { + 111: //serviceID + { + "serviceName": "someservice", + "serviceInstances": { + 500: //serviceInstanceID + { + "providerName": "fancy_name", + "criticality": "ASIL-B", + "version": 5, + "tlsenable": 1, + "ipsecenable": 1, + "macsecenable ":1, + //specifics is for oem/user specifics: e.g. some state machine aka allow access to everyone if in state X + "specifics": {}, + "allow": + { + "uids": + { + //rights: "write" --> r+w to data & control, e.g. publisher in publish subscribe, m:n --> "m", 1:1 --> both + // "read" --> r to data & rw on control, e.g. subscriber in publish subscribe, m:n --> "n" + // "monitor" --> r to data & control, e.g. some health monitor checking duration of control blockers + //specifics is for oem/user specifics: e.g. allow uid 101 only to write/publish if in state X + 101:{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, + 102:{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, + 103:{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} + }, + "ips": + { + "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"criticality": "QM","specifics": {}}, + "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"criticality": "QM","specifics": {}} + } + } + } + } + } + } +} + + "crypto": + { + //keyspaceID + 0: + { + "keyspaceName": "tls_auth", + "keys": + [ + //keyID + 1: + { + "name": "tls_auth_priv", + "read": [], + "use": [{"uid": 1, "policy": ""},{"uid": 2, "policy": ""}], + "write": [{"uid": 1, "policy": "someipd_t"}] + }, + 2: + { + "name": "tls_auth_pub", + "read": [{"uid": -1, "policy": ""}], + "use": [{"uid": 1, "policy": ""},{"uid": 2, "policy": ""}], + "write": [{"uid": 1, "policy": "someipd_t"}] + } + ] + } + } +} + + + + + Justification for the Decision + ------------------------------ + open \ No newline at end of file From 1969d68b136187c682e3bbe6b9bce81acae5667e Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 16:36:28 +0200 Subject: [PATCH 2/8] DR-009-ACL-Concept: Added json scheme and reformatted example Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 574 +++++++++++++++++--- 1 file changed, 504 insertions(+), 70 deletions(-) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index 61c661fc08c..f73d9d8f55e 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -39,84 +39,518 @@ - a json file as configuration - for runtime efficiency: compilation of the json file to a flatbuffer/binary file - Proposed json format & properties: + Proposed json format & properties (example): - { - "policyVersion": 1, - "policyId": "example-acl-policy-001", - "defaultEffect": "deny", - "generatedBy": "install-update-manager", - "generatedAt": "2026-06-17T14:28:00Z", - - "services": - { - 111: //serviceID + + ```json { - "serviceName": "someservice", - "serviceInstances": { - 500: //serviceInstanceID + "policyVersion": 1, + "policyId": "example-acl-policy-001", + "defaultEffect": "deny", + "generatedBy": "install-update-manager", + "generatedAt": "2026-06-17T14:28:00Z", + + "services": + { + 111: //serviceID { - "providerName": "fancy_name", - "criticality": "ASIL-B", - "version": 5, - "tlsenable": 1, - "ipsecenable": 1, - "macsecenable ":1, - //specifics is for oem/user specifics: e.g. some state machine aka allow access to everyone if in state X - "specifics": {}, - "allow": - { - "uids": - { - //rights: "write" --> r+w to data & control, e.g. publisher in publish subscribe, m:n --> "m", 1:1 --> both - // "read" --> r to data & rw on control, e.g. subscriber in publish subscribe, m:n --> "n" - // "monitor" --> r to data & control, e.g. some health monitor checking duration of control blockers - //specifics is for oem/user specifics: e.g. allow uid 101 only to write/publish if in state X - 101:{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, - 102:{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, - 103:{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} - }, - "ips": - { - "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"criticality": "QM","specifics": {}}, - "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"criticality": "QM","specifics": {}} + "serviceName": "someservice", + "serviceInstances": { + 500: //serviceInstanceID + { + "providerName": "fancy_name", + "criticality": "ASIL-B", + "version": 5, + "tlsenable": 1, + "ipsecenable": 1, + "macsecenable ":1, + //specifics is for oem/user specifics: e.g. some state machine aka allow access to everyone if in state X + "specifics": {}, + "allow": + { + "uids": + { + //rights: "write" --> r+w to data & control, e.g. publisher in publish subscribe, m:n --> "m", 1:1 --> both + // "read" --> r to data & rw on control, e.g. subscriber in publish subscribe, m:n --> "n" + // "monitor" --> r to data & control, e.g. some health monitor checking duration of control blockers + //specifics is for oem/user specifics: e.g. allow uid 101 only to write/publish if in state X + 101:{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, + 102:{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, + 103:{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} + }, + "ips": + { + "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"criticality": "QM","specifics": {}}, + "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"criticality": "QM","specifics": {}} + } + } } - } - } - } - } - } -} - - "crypto": - { - //keyspaceID - 0: + } + } + } + "crypto": + { + //keyspaceID + 0: + { + "keyspaceName": "tls_auth", + "keys": + { + //keyID + 1: + { + "name": "tls_auth_priv", + "read": [], + "use": [{"vmid": None, "uid": 1, "policy": "", "otherid": ""},{"vmid": 4,"uid": 2, "policy": ""}], + "write": [{"vmid": None, "uid": 1, "policy": "someipd_t"}] + }, + 2: + { + "name": "tls_auth_pub", + "read": [{"vmid": None, "uid": -1, "policy": ""}], + "use": [{"vmid": None,"uid": 1, "policy": ""},{"vmid": 4,"uid": 2, "policy": ""}], + "write": [{"vmid": None,"uid": 1, "policy": "someipd_t"}] + } + } + } + } + } + + ``` + + proposed json scheme: + + ```json { - "keyspaceName": "tls_auth", - "keys": - [ - //keyID - 1: - { - "name": "tls_auth_priv", - "read": [], - "use": [{"uid": 1, "policy": ""},{"uid": 2, "policy": ""}], - "write": [{"uid": 1, "policy": "someipd_t"}] - }, - 2: - { - "name": "tls_auth_pub", - "read": [{"uid": -1, "policy": ""}], - "use": [{"uid": 1, "policy": ""},{"uid": 2, "policy": ""}], - "write": [{"uid": 1, "policy": "someipd_t"}] + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/acl-policy.schema.json", + "title": "ACL Configuration Schema", + "type": "object", + "additionalProperties": false, + "required": [ + "policyVersion", + "policyId", + "defaultEffect", + "generatedBy", + "generatedAt", + "services" + ], + "properties": { + "policyVersion": { + "type": "integer", + "minimum": 1 + }, + "policyId": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "defaultEffect": { + "type": "string", + "enum": [ + "deny", + "allow" + ], + "maxLength": 128 + }, + "generatedBy": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "generatedAt": { + "type": "string", + "description": "ISO-8601 UTC timestamp without fractional seconds", + "maxLength": 20, + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$" + }, + "services": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/service" + } + }, + "crypto": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/keyspace" + } + } + }, + "$defs": { + "uint16Key": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" + }, + "uidKey": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-3][0-9]|214748364[0-7])$" + }, + "criticality": { + "type": "string", + "enum": [ + "QM", + "ASIL-A", + "ASIL-B", + "ASIL-C", + "ASIL-D" + ], + "maxLength": 128 + }, + "binaryFlag": { + "type": "integer", + "enum": [ + 0, + 1 + ] + }, + "rights": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "read", + "write", + "monitor" + ], + "maxLength": 128 + }, + "uniqueItems": true + }, + "specifics": { + "description": "OEM-specific or project-specific extension object. Unknown properties are allowed only here.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/specificValue" + } + }, + "specificValue": { + "anyOf": [ + { + "type": "string", + "maxLength": 128 + }, + { + "type": "number" + }, + { + "type": "integer" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/specificValue" + } + }, + { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/specificValue" + } + } + ] + }, + "service": { + "type": "object", + "additionalProperties": false, + "required": [ + "serviceName", + "serviceInstances" + ], + "properties": { + "serviceName": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "serviceInstances": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/serviceInstance" + } + } + } + }, + "serviceInstance": { + "type": "object", + "additionalProperties": false, + "required": [ + "providerName", + "criticality", + "version", + "tlsenable", + "ipsecenable", + "macsecenable", + "specifics", + "allow" + ], + "properties": { + "providerName": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "criticality": { + "$ref": "#/$defs/criticality" + }, + "version": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tlsenable": { + "$ref": "#/$defs/binaryFlag" + }, + "ipsecenable": { + "$ref": "#/$defs/binaryFlag" + }, + "macsecenable": { + "$ref": "#/$defs/binaryFlag" + }, + "specifics": { + "$ref": "#/$defs/specifics" + }, + "allow": { + "$ref": "#/$defs/allow" + } + } + }, + "allow": { + "type": "object", + "additionalProperties": false, + "required": [ + "uids", + "ips" + ], + "properties": { + "uids": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uidKey" + }, + "additionalProperties": { + "$ref": "#/$defs/uidSubject" + } + }, + "ips": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/ipOrCidrKey" + }, + "additionalProperties": { + "$ref": "#/$defs/ipSubject" + } } - ] - } - } -} + } + }, + "uidSubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "rights", + "version", + "criticality", + "specifics" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "rights": { + "$ref": "#/$defs/rights" + }, + "version": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + { + "type": "string", + "maxLength": 128 + } + ] + } + }, + "criticality": { + "$ref": "#/$defs/criticality" + }, + "specifics": { + "$ref": "#/$defs/specifics" + } + } + }, + "ipSubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "rights", + "criticality", + "specifics" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "rights": { + "$ref": "#/$defs/rights" + }, + "criticality": { + "$ref": "#/$defs/criticality" + }, + "specifics": { + "$ref": "#/$defs/specifics" + } + } + }, + "ipOrCidrKey": { + "type": "string", + "maxLength": 128, + "anyOf": [ + { + "description": "IPv4 address", + "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$" + }, + { + "description": "IPv4 CIDR subnet", + "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}\\/(3[0-2]|[1-2]?[0-9])$" + }, + { + "description": "IPv6 address or IPv6 CIDR subnet, simplified validation", + "pattern": "^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}(\\/(12[0-8]|1[0-1][0-9]|[1-9]?[0-9]))?$" + } + ] + }, + "keyspace": { + "type": "object", + "additionalProperties": false, + "required": [ + "keyspaceName", + "keys" + ], + "properties": { + "keyspaceName": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "keys": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/key" + } + } + } + }, + "key": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "read", + "use", + "write" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "read": { + "$ref": "#/$defs/keyAccessList" + }, + "use": { + "$ref": "#/$defs/keyAccessList" + }, + "write": { + "$ref": "#/$defs/keyAccessList" + } + } + }, + "keyAccessList": { + "type": "array", + "items": { + "$ref": "#/$defs/keyAccessEntry" + } + }, + "keyAccessEntry": { + "type": "object", + "additionalProperties": false, + "anyOf": [ + { + "required": ["uid"] + }, + { + "required": ["policy"] + }, + { + "required": ["vmid", "uid"] + }, + { + "required": ["otherid"] + } + ], + + "dependentRequired": { + "vmid": ["uid"] + }, + + "properties": { + "vmid": { + "description": "Optional virtual machine ID. If present, uid is required as well.", + "type": "integer", + "minimum": 0, + "maximum": 2147483647 + }, + "uid": { + "type": "integer", + "minimum": -1, + "maximum": 2147483647 + }, + "policy": { + "type": "string", + "maxLength": 128 + }, + "otherid": { + "description": "Optional additional identifier for project-specific or non-UID based access control.", + "type": "string", + "maxLength": 128 + } + } + } + } + } + ``` Justification for the Decision From 748c7450fb0256f9f41d6c4f771df069894f48ec Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:08:04 +0200 Subject: [PATCH 3/8] DR-009-ACL-Concept: Fixxed json formatting Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 35 +++++++++------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index f73d9d8f55e..bb79dedef9a 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -52,31 +52,26 @@ "services": { - 111: //serviceID + "111": { "serviceName": "someservice", "serviceInstances": { - 500: //serviceInstanceID + "500": { "providerName": "fancy_name", "criticality": "ASIL-B", "version": 5, "tlsenable": 1, "ipsecenable": 1, - "macsecenable ":1, - //specifics is for oem/user specifics: e.g. some state machine aka allow access to everyone if in state X + "macsecenable":1, "specifics": {}, "allow": { "uids": { - //rights: "write" --> r+w to data & control, e.g. publisher in publish subscribe, m:n --> "m", 1:1 --> both - // "read" --> r to data & rw on control, e.g. subscriber in publish subscribe, m:n --> "n" - // "monitor" --> r to data & control, e.g. some health monitor checking duration of control blockers - //specifics is for oem/user specifics: e.g. allow uid 101 only to write/publish if in state X - 101:{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, - 102:{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, - 103:{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} + "101":{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, + "102":{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, + "103":{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} }, "ips": { @@ -87,29 +82,29 @@ } } } - } + }, "crypto": { //keyspaceID - 0: + "0": { "keyspaceName": "tls_auth", "keys": { //keyID - 1: + "1": { "name": "tls_auth_priv", "read": [], - "use": [{"vmid": None, "uid": 1, "policy": "", "otherid": ""},{"vmid": 4,"uid": 2, "policy": ""}], - "write": [{"vmid": None, "uid": 1, "policy": "someipd_t"}] + "use": [{"uid": 1,"otherid": "special_handling_1"},{"vmid": 4,"uid": 2}], + "write": [{"uid": 1, "policy": "someipd_t"}] }, - 2: + "2": { "name": "tls_auth_pub", - "read": [{"vmid": None, "uid": -1, "policy": ""}], - "use": [{"vmid": None,"uid": 1, "policy": ""},{"vmid": 4,"uid": 2, "policy": ""}], - "write": [{"vmid": None,"uid": 1, "policy": "someipd_t"}] + "read": [{"uid": -1}], + "use": [{"uid": 1, "policy": ""},{"vmid": 4,"uid": 2}], + "write": [{uid": 1, "policy": "someipd_t"}] } } } From 55a6c1988d47d75374148b88cc3fe13c0d44ffa7 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:18:42 +0200 Subject: [PATCH 4/8] DR-009-ACL-Concept: Fix#2 for md formatting Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 878 ++++++++++---------- 1 file changed, 439 insertions(+), 439 deletions(-) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index bb79dedef9a..fe2d43a83ac 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -1,8 +1,9 @@ -.. dec_rec:: One Format for Access Control List(s) (ACL) +```{dec_rec} One Format for Access Control List(s) (ACL) :id: dec_rec__platform__acl_concept :status: proposed :version: 1 :affects: +``` Context ------- @@ -42,510 +43,509 @@ Proposed json format & properties (example): - ```json - { - "policyVersion": 1, - "policyId": "example-acl-policy-001", - "defaultEffect": "deny", - "generatedBy": "install-update-manager", - "generatedAt": "2026-06-17T14:28:00Z", +```json +{ + "policyVersion": 1, + "policyId": "example-acl-policy-001", + "defaultEffect": "deny", + "generatedBy": "install-update-manager", + "generatedAt": "2026-06-17T14:28:00Z", - "services": - { - "111": + "services": + { + "111": + { + "serviceName": "someservice", + "serviceInstances": { + "500": { - "serviceName": "someservice", - "serviceInstances": { - "500": + "providerName": "fancy_name", + "criticality": "ASIL-B", + "version": 5, + "tlsenable": 1, + "ipsecenable": 1, + "macsecenable":1, + "specifics": {}, + "allow": + { + "uids": { - "providerName": "fancy_name", - "criticality": "ASIL-B", - "version": 5, - "tlsenable": 1, - "ipsecenable": 1, - "macsecenable":1, - "specifics": {}, - "allow": - { - "uids": - { - "101":{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, - "102":{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, - "103":{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} - }, - "ips": - { - "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"criticality": "QM","specifics": {}}, - "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"criticality": "QM","specifics": {}} - } - } + "101":{"rights": ["write"],"name": "oem.app.1","version": [],"criticality": "ASIL-B","specifics": {}}, + "102":{"rights": ["read"],"name": "oem.app.2","version": [],"criticality": "ASIL-B","specifics": {}}, + "103":{"rights": ["read"],"name": "tier1.daemon.1","version": [],"criticality": "ASIL-B","specifics": {}} + }, + "ips": + { + "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"criticality": "QM","specifics": {}}, + "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"criticality": "QM","specifics": {}} } } } - }, - "crypto": - { - //keyspaceID - "0": + } + } + }, + "crypto": + { + //keyspaceID + "0": + { + "keyspaceName": "tls_auth", + "keys": { - "keyspaceName": "tls_auth", - "keys": - { - //keyID - "1": - { - "name": "tls_auth_priv", - "read": [], - "use": [{"uid": 1,"otherid": "special_handling_1"},{"vmid": 4,"uid": 2}], - "write": [{"uid": 1, "policy": "someipd_t"}] - }, - "2": - { - "name": "tls_auth_pub", - "read": [{"uid": -1}], - "use": [{"uid": 1, "policy": ""},{"vmid": 4,"uid": 2}], - "write": [{uid": 1, "policy": "someipd_t"}] - } + //keyID + "1": + { + "name": "tls_auth_priv", + "read": [], + "use": [{"uid": 1,"otherid": "special_handling_1"},{"vmid": 4,"uid": 2}], + "write": [{"uid": 1, "policy": "someipd_t"}] + }, + "2": + { + "name": "tls_auth_pub", + "read": [{"uid": -1}], + "use": [{"uid": 1, "policy": ""},{"vmid": 4,"uid": 2}], + "write": [{uid": 1, "policy": "someipd_t"}] } } - } } - - ``` + } +} +``` proposed json scheme: - ```json - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/acl-policy.schema.json", - "title": "ACL Configuration Schema", +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/acl-policy.schema.json", + "title": "ACL Configuration Schema", + "type": "object", + "additionalProperties": false, + "required": [ + "policyVersion", + "policyId", + "defaultEffect", + "generatedBy", + "generatedAt", + "services" + ], + "properties": { + "policyVersion": { + "type": "integer", + "minimum": 1 + }, + "policyId": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "defaultEffect": { + "type": "string", + "enum": [ + "deny", + "allow" + ], + "maxLength": 128 + }, + "generatedBy": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "generatedAt": { + "type": "string", + "description": "ISO-8601 UTC timestamp without fractional seconds", + "maxLength": 20, + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$" + }, + "services": { "type": "object", - "additionalProperties": false, - "required": [ - "policyVersion", - "policyId", - "defaultEffect", - "generatedBy", - "generatedAt", - "services" + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/service" + } + }, + "crypto": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/keyspace" + } + } + }, + "$defs": { + "uint16Key": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" + }, + "uidKey": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-3][0-9]|214748364[0-7])$" + }, + "criticality": { + "type": "string", + "enum": [ + "QM", + "ASIL-A", + "ASIL-B", + "ASIL-C", + "ASIL-D" ], - "properties": { - "policyVersion": { - "type": "integer", - "minimum": 1 - }, - "policyId": { + "maxLength": 128 + }, + "binaryFlag": { + "type": "integer", + "enum": [ + 0, + 1 + ] + }, + "rights": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "read", + "write", + "monitor" + ], + "maxLength": 128 + }, + "uniqueItems": true + }, + "specifics": { + "description": "OEM-specific or project-specific extension object. Unknown properties are allowed only here.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/specificValue" + } + }, + "specificValue": { + "anyOf": [ + { "type": "string", - "minLength": 1, "maxLength": 128 }, - "defaultEffect": { - "type": "string", - "enum": [ - "deny", - "allow" - ], - "maxLength": 128 + { + "type": "number" }, - "generatedBy": { - "type": "string", - "minLength": 1, - "maxLength": 128 + { + "type": "integer" }, - "generatedAt": { - "type": "string", - "description": "ISO-8601 UTC timestamp without fractional seconds", - "maxLength": 20, - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$" + { + "type": "boolean" }, - "services": { + { + "type": "null" + }, + { + "type": "array", + "items": { + "$ref": "#/$defs/specificValue" + } + }, + { "type": "object", - "propertyNames": { - "$ref": "#/$defs/uint16Key" - }, "additionalProperties": { - "$ref": "#/$defs/service" + "$ref": "#/$defs/specificValue" } + } + ] + }, + "service": { + "type": "object", + "additionalProperties": false, + "required": [ + "serviceName", + "serviceInstances" + ], + "properties": { + "serviceName": { + "type": "string", + "minLength": 1, + "maxLength": 128 }, - "crypto": { + "serviceInstances": { "type": "object", "propertyNames": { "$ref": "#/$defs/uint16Key" }, "additionalProperties": { - "$ref": "#/$defs/keyspace" + "$ref": "#/$defs/serviceInstance" } } - }, - "$defs": { - "uint16Key": { - "type": "string", - "pattern": "^(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" - }, - "uidKey": { + } + }, + "serviceInstance": { + "type": "object", + "additionalProperties": false, + "required": [ + "providerName", + "criticality", + "version", + "tlsenable", + "ipsecenable", + "macsecenable", + "specifics", + "allow" + ], + "properties": { + "providerName": { "type": "string", - "pattern": "^(0|[1-9][0-9]{0,8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-3][0-9]|214748364[0-7])$" + "minLength": 1, + "maxLength": 128 }, "criticality": { - "type": "string", - "enum": [ - "QM", - "ASIL-A", - "ASIL-B", - "ASIL-C", - "ASIL-D" - ], - "maxLength": 128 + "$ref": "#/$defs/criticality" }, - "binaryFlag": { + "version": { "type": "integer", - "enum": [ - 0, - 1 - ] + "minimum": 0, + "maximum": 65535 }, - "rights": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "read", - "write", - "monitor" - ], - "maxLength": 128 - }, - "uniqueItems": true + "tlsenable": { + "$ref": "#/$defs/binaryFlag" + }, + "ipsecenable": { + "$ref": "#/$defs/binaryFlag" + }, + "macsecenable": { + "$ref": "#/$defs/binaryFlag" }, "specifics": { - "description": "OEM-specific or project-specific extension object. Unknown properties are allowed only here.", + "$ref": "#/$defs/specifics" + }, + "allow": { + "$ref": "#/$defs/allow" + } + } + }, + "allow": { + "type": "object", + "additionalProperties": false, + "required": [ + "uids", + "ips" + ], + "properties": { + "uids": { "type": "object", + "propertyNames": { + "$ref": "#/$defs/uidKey" + }, "additionalProperties": { - "$ref": "#/$defs/specificValue" + "$ref": "#/$defs/uidSubject" } }, - "specificValue": { - "anyOf": [ - { - "type": "string", - "maxLength": 128 - }, - { - "type": "number" - }, - { - "type": "integer" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "type": "array", - "items": { - "$ref": "#/$defs/specificValue" - } - }, - { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/specificValue" - } - } - ] - }, - "service": { + "ips": { "type": "object", - "additionalProperties": false, - "required": [ - "serviceName", - "serviceInstances" - ], - "properties": { - "serviceName": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "serviceInstances": { - "type": "object", - "propertyNames": { - "$ref": "#/$defs/uint16Key" - }, - "additionalProperties": { - "$ref": "#/$defs/serviceInstance" - } - } + "propertyNames": { + "$ref": "#/$defs/ipOrCidrKey" + }, + "additionalProperties": { + "$ref": "#/$defs/ipSubject" } + } + } + }, + "uidSubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "rights", + "version", + "criticality", + "specifics" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 }, - "serviceInstance": { - "type": "object", - "additionalProperties": false, - "required": [ - "providerName", - "criticality", - "version", - "tlsenable", - "ipsecenable", - "macsecenable", - "specifics", - "allow" - ], - "properties": { - "providerName": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "criticality": { - "$ref": "#/$defs/criticality" - }, - "version": { - "type": "integer", - "minimum": 0, - "maximum": 65535 - }, - "tlsenable": { - "$ref": "#/$defs/binaryFlag" - }, - "ipsecenable": { - "$ref": "#/$defs/binaryFlag" - }, - "macsecenable": { - "$ref": "#/$defs/binaryFlag" - }, - "specifics": { - "$ref": "#/$defs/specifics" - }, - "allow": { - "$ref": "#/$defs/allow" - } - } + "rights": { + "$ref": "#/$defs/rights" }, - "allow": { - "type": "object", - "additionalProperties": false, - "required": [ - "uids", - "ips" - ], - "properties": { - "uids": { - "type": "object", - "propertyNames": { - "$ref": "#/$defs/uidKey" - }, - "additionalProperties": { - "$ref": "#/$defs/uidSubject" - } - }, - "ips": { - "type": "object", - "propertyNames": { - "$ref": "#/$defs/ipOrCidrKey" + "version": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 65535 }, - "additionalProperties": { - "$ref": "#/$defs/ipSubject" + { + "type": "string", + "maxLength": 128 } - } + ] } }, - "uidSubject": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "rights", - "version", - "criticality", - "specifics" - ], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "rights": { - "$ref": "#/$defs/rights" - }, - "version": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer", - "minimum": 0, - "maximum": 65535 - }, - { - "type": "string", - "maxLength": 128 - } - ] - } - }, - "criticality": { - "$ref": "#/$defs/criticality" - }, - "specifics": { - "$ref": "#/$defs/specifics" - } - } + "criticality": { + "$ref": "#/$defs/criticality" }, - "ipSubject": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "rights", - "criticality", - "specifics" - ], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "rights": { - "$ref": "#/$defs/rights" - }, - "criticality": { - "$ref": "#/$defs/criticality" - }, - "specifics": { - "$ref": "#/$defs/specifics" - } - } + "specifics": { + "$ref": "#/$defs/specifics" + } + } + }, + "ipSubject": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "rights", + "criticality", + "specifics" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 }, - "ipOrCidrKey": { + "rights": { + "$ref": "#/$defs/rights" + }, + "criticality": { + "$ref": "#/$defs/criticality" + }, + "specifics": { + "$ref": "#/$defs/specifics" + } + } + }, + "ipOrCidrKey": { + "type": "string", + "maxLength": 128, + "anyOf": [ + { + "description": "IPv4 address", + "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$" + }, + { + "description": "IPv4 CIDR subnet", + "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}\\/(3[0-2]|[1-2]?[0-9])$" + }, + { + "description": "IPv6 address or IPv6 CIDR subnet, simplified validation", + "pattern": "^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}(\\/(12[0-8]|1[0-1][0-9]|[1-9]?[0-9]))?$" + } + ] + }, + "keyspace": { + "type": "object", + "additionalProperties": false, + "required": [ + "keyspaceName", + "keys" + ], + "properties": { + "keyspaceName": { "type": "string", - "maxLength": 128, - "anyOf": [ - { - "description": "IPv4 address", - "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}$" - }, - { - "description": "IPv4 CIDR subnet", - "pattern": "^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}\\/(3[0-2]|[1-2]?[0-9])$" - }, - { - "description": "IPv6 address or IPv6 CIDR subnet, simplified validation", - "pattern": "^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}(\\/(12[0-8]|1[0-1][0-9]|[1-9]?[0-9]))?$" - } - ] + "minLength": 1, + "maxLength": 128 }, - "keyspace": { + "keys": { "type": "object", - "additionalProperties": false, - "required": [ - "keyspaceName", - "keys" - ], - "properties": { - "keyspaceName": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "keys": { - "type": "object", - "propertyNames": { - "$ref": "#/$defs/uint16Key" - }, - "additionalProperties": { - "$ref": "#/$defs/key" - } - } + "propertyNames": { + "$ref": "#/$defs/uint16Key" + }, + "additionalProperties": { + "$ref": "#/$defs/key" } + } + } + }, + "key": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "read", + "use", + "write" + ], + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 }, - "key": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "read", - "use", - "write" - ], - "properties": { - "name": { - "type": "string", - "minLength": 1, - "maxLength": 128 - }, - "read": { - "$ref": "#/$defs/keyAccessList" - }, - "use": { - "$ref": "#/$defs/keyAccessList" - }, - "write": { - "$ref": "#/$defs/keyAccessList" - } - } + "read": { + "$ref": "#/$defs/keyAccessList" }, - "keyAccessList": { - "type": "array", - "items": { - "$ref": "#/$defs/keyAccessEntry" - } - }, - "keyAccessEntry": { - "type": "object", - "additionalProperties": false, + "use": { + "$ref": "#/$defs/keyAccessList" + }, + "write": { + "$ref": "#/$defs/keyAccessList" + } + } + }, + "keyAccessList": { + "type": "array", + "items": { + "$ref": "#/$defs/keyAccessEntry" + } + }, + "keyAccessEntry": { + "type": "object", + "additionalProperties": false, - "anyOf": [ - { - "required": ["uid"] - }, - { - "required": ["policy"] - }, - { - "required": ["vmid", "uid"] - }, - { - "required": ["otherid"] - } - ], + "anyOf": [ + { + "required": ["uid"] + }, + { + "required": ["policy"] + }, + { + "required": ["vmid", "uid"] + }, + { + "required": ["otherid"] + } + ], - "dependentRequired": { - "vmid": ["uid"] - }, + "dependentRequired": { + "vmid": ["uid"] + }, - "properties": { - "vmid": { - "description": "Optional virtual machine ID. If present, uid is required as well.", - "type": "integer", - "minimum": 0, - "maximum": 2147483647 - }, - "uid": { - "type": "integer", - "minimum": -1, - "maximum": 2147483647 - }, - "policy": { - "type": "string", - "maxLength": 128 - }, - "otherid": { - "description": "Optional additional identifier for project-specific or non-UID based access control.", - "type": "string", - "maxLength": 128 - } - } + "properties": { + "vmid": { + "description": "Optional virtual machine ID. If present, uid is required as well.", + "type": "integer", + "minimum": 0, + "maximum": 2147483647 + }, + "uid": { + "type": "integer", + "minimum": -1, + "maximum": 2147483647 + }, + "policy": { + "type": "string", + "maxLength": 128 + }, + "otherid": { + "description": "Optional additional identifier for project-specific or non-UID based access control.", + "type": "string", + "maxLength": 128 } - } } - ``` + + } +} +``` Justification for the Decision From 35b2431b9d1d1f5f90b0215a9fa24d7851755285 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:48:52 +0200 Subject: [PATCH 5/8] DR-009-ACL-Concept: Fix#3 for json formatting Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index fe2d43a83ac..4bcbbfa2012 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -1,9 +1,9 @@ -```{dec_rec} One Format for Access Control List(s) (ACL) +.. dec_rec:: One Format for Access Control List(s) (ACL) :id: dec_rec__platform__acl_concept :status: proposed :version: 1 :affects: -``` + Context ------- @@ -86,13 +86,11 @@ }, "crypto": { - //keyspaceID "0": { "keyspaceName": "tls_auth", "keys": { - //keyID "1": { "name": "tls_auth_priv", @@ -105,7 +103,7 @@ "name": "tls_auth_pub", "read": [{"uid": -1}], "use": [{"uid": 1, "policy": ""},{"vmid": 4,"uid": 2}], - "write": [{uid": 1, "policy": "someipd_t"}] + "write": [{"uid": 1, "policy": "someipd_t"}] } } } From 2b0a31145289de53b8f1e87a2b80bf96a98929fb Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:03:55 +0200 Subject: [PATCH 6/8] DR-009-ACL-Concept: Fix#4 DR Template compliance Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index 4bcbbfa2012..fbb1f642ce3 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -1,9 +1,8 @@ -.. dec_rec:: One Format for Access Control List(s) (ACL) +```{dec_rec} One Format for Access Control List(s) (ACL) :id: dec_rec__platform__acl_concept :status: proposed - :version: 1 - :affects: - + :decision: open +``` Context ------- From 370eba3dba07b171ec38be03f55c4e2e79c993b3 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:10:20 +0200 Subject: [PATCH 7/8] DR-009-ACL-Concept: Fix#5 DR Template compliance Signed-off-by: Christian Becker --- docs/design_decisions/DR-009-ACL-Concept.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-ACL-Concept.md index fbb1f642ce3..dea4de38c6a 100644 --- a/docs/design_decisions/DR-009-ACL-Concept.md +++ b/docs/design_decisions/DR-009-ACL-Concept.md @@ -1,6 +1,9 @@ +# DR-009-ACL-Concept: Common ACL format for all components + ```{dec_rec} One Format for Access Control List(s) (ACL) :id: dec_rec__platform__acl_concept :status: proposed + :context: Common ACL format for all components :decision: open ``` From 266ab1c50ed00afd778f0b1167b1efadbafa76a3 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:15:38 +0200 Subject: [PATCH 8/8] DR-009-ACL-Concept: Fix#6 DR Template compliance->dr file name Signed-off-by: Christian Becker  --- .../{DR-009-ACL-Concept.md => DR-009-arch-ACL-Concept.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/design_decisions/{DR-009-ACL-Concept.md => DR-009-arch-ACL-Concept.md} (100%) diff --git a/docs/design_decisions/DR-009-ACL-Concept.md b/docs/design_decisions/DR-009-arch-ACL-Concept.md similarity index 100% rename from docs/design_decisions/DR-009-ACL-Concept.md rename to docs/design_decisions/DR-009-arch-ACL-Concept.md