From 1e23e7e09b252381cf12d6753aa5fe713bb715d5 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Mon, 29 Jun 2026 09:25:20 +0200 Subject: [PATCH 01/13] DR-003-ARCH-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 ec6e52068fc74de5388054f409fa4733b4db4c25 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 16:36:28 +0200 Subject: [PATCH 02/13] DR-003-ARCH-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 ed0f8caca6ae74480da96559e48f740d131f45b3 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:08:04 +0200 Subject: [PATCH 03/13] DR-003-ARC-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 320ff37face8fb4d4c46272cd18c5ace8758d289 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:18:42 +0200 Subject: [PATCH 04/13] DR-003-ARCH-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 12ac851e3e540cfb7c9b3e976ec79e2cccdaa21b Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 17:48:52 +0200 Subject: [PATCH 05/13] DR-003-ARCH-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 fb3ab2ca05b5a9947d5caaa3febec3769142a088 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:03:55 +0200 Subject: [PATCH 06/13] DR-003-ARCH-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 fbb86607a641b159318357fc7644f3c8d5c4d8de Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:10:20 +0200 Subject: [PATCH 07/13] DR-003-ARCH-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 1e64d775da9a0f8dc8d26f785ae6bd129d4d94f2 Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 18:15:38 +0200 Subject: [PATCH 08/13] DR-003-ARCH-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 From 6c3e23e44bfb18ab81c68f8e5312cc164caf2c4d Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 19:01:53 +0200 Subject: [PATCH 09/13] DR-003-ARCH-ACL-Concept: Fix#7 Raname of DR file 009 --> 003 Signed-off-by: Christian Becker --- .../DR-009-arch-ACL-Concept.md | 553 ------------------ 1 file changed, 553 deletions(-) delete mode 100644 docs/design_decisions/DR-009-arch-ACL-Concept.md diff --git a/docs/design_decisions/DR-009-arch-ACL-Concept.md b/docs/design_decisions/DR-009-arch-ACL-Concept.md deleted file mode 100644 index dea4de38c6a..00000000000 --- a/docs/design_decisions/DR-009-arch-ACL-Concept.md +++ /dev/null @@ -1,553 +0,0 @@ -# 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 -``` - - 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 (example): - - -```json -{ - "policyVersion": 1, - "policyId": "example-acl-policy-001", - "defaultEffect": "deny", - "generatedBy": "install-update-manager", - "generatedAt": "2026-06-17T14:28:00Z", - - "services": - { - "111": - { - "serviceName": "someservice", - "serviceInstances": { - "500": - { - "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": {}} - } - } - } - } - } - }, - "crypto": - { - "0": - { - "keyspaceName": "tls_auth", - "keys": - { - "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", - "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 - ------------------------------ - open \ No newline at end of file From 6ce5a4008efc501426784c43f969d60c17dca6dd Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Wed, 1 Jul 2026 19:07:52 +0200 Subject: [PATCH 10/13] DR-003-ARCH-ACL-Concept: Fix#8 Raname of DR file 009 --> 003 Signed-off-by: Christian Becker --- .../DR-003-arch-ACL-Concept.md | 553 ++++++++++++++++++ 1 file changed, 553 insertions(+) create mode 100644 docs/design_decisions/DR-003-arch-ACL-Concept.md diff --git a/docs/design_decisions/DR-003-arch-ACL-Concept.md b/docs/design_decisions/DR-003-arch-ACL-Concept.md new file mode 100644 index 00000000000..dea4de38c6a --- /dev/null +++ b/docs/design_decisions/DR-003-arch-ACL-Concept.md @@ -0,0 +1,553 @@ +# 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 +``` + + 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 (example): + + +```json +{ + "policyVersion": 1, + "policyId": "example-acl-policy-001", + "defaultEffect": "deny", + "generatedBy": "install-update-manager", + "generatedAt": "2026-06-17T14:28:00Z", + + "services": + { + "111": + { + "serviceName": "someservice", + "serviceInstances": { + "500": + { + "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": {}} + } + } + } + } + } + }, + "crypto": + { + "0": + { + "keyspaceName": "tls_auth", + "keys": + { + "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", + "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 + ------------------------------ + open \ No newline at end of file From 0b1e55e12fedf124c37402555dd39b83eb117aab Mon Sep 17 00:00:00 2001 From: christianbe9 Date: Thu, 9 Jul 2026 13:38:27 +0200 Subject: [PATCH 11/13] PR - suggested changes Co-authored-by: Guruprasad Bhat <30743494+GuruprasadBhatL@users.noreply.github.com> Signed-off-by: christianbe9 --- docs/design_decisions/DR-003-arch-ACL-Concept.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design_decisions/DR-003-arch-ACL-Concept.md b/docs/design_decisions/DR-003-arch-ACL-Concept.md index dea4de38c6a..234b230d4a8 100644 --- a/docs/design_decisions/DR-003-arch-ACL-Concept.md +++ b/docs/design_decisions/DR-003-arch-ACL-Concept.md @@ -16,7 +16,7 @@ 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 + - SOME/IP 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? From 258e834547b31345d578ae0da9b3639fb761b8d6 Mon Sep 17 00:00:00 2001 From: christianbe9 Date: Thu, 9 Jul 2026 13:38:43 +0200 Subject: [PATCH 12/13] PR - suggested changes Co-authored-by: Guruprasad Bhat <30743494+GuruprasadBhatL@users.noreply.github.com> Signed-off-by: christianbe9 --- docs/design_decisions/DR-003-arch-ACL-Concept.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design_decisions/DR-003-arch-ACL-Concept.md b/docs/design_decisions/DR-003-arch-ACL-Concept.md index 234b230d4a8..db749f029de 100644 --- a/docs/design_decisions/DR-003-arch-ACL-Concept.md +++ b/docs/design_decisions/DR-003-arch-ACL-Concept.md @@ -29,7 +29,7 @@ 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: + To prevent each component from implementing compeletley own mechanism for persmission enforcement; the decision should 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: From cd6c8bc8bb6f8c16231ba75dc6736c70431e1fcf Mon Sep 17 00:00:00 2001 From: Christian Becker Date: Sat, 25 Jul 2026 00:24:45 +0200 Subject: [PATCH 13/13] DR-003-ARCH-ACL-Concept: Updated the schema according to review findings Changes applied: - example moved to bottom - rights enum in seperate schema - access control rate limiting for jobs and memory - updated read, use and write right structure - renamed tlsenable, ipsecenable, macsecenable for better understanding to precondition_*enabled Singed-off-by: Christian Becker --- .../DR-003-arch-ACL-Concept.md | 437 ++++++++++-------- 1 file changed, 246 insertions(+), 191 deletions(-) diff --git a/docs/design_decisions/DR-003-arch-ACL-Concept.md b/docs/design_decisions/DR-003-arch-ACL-Concept.md index db749f029de..78b585c2bd7 100644 --- a/docs/design_decisions/DR-003-arch-ACL-Concept.md +++ b/docs/design_decisions/DR-003-arch-ACL-Concept.md @@ -1,9 +1,9 @@ -# DR-009-ACL-Concept: Common ACL format for all components +# DR-003-ARCH-ACL-Concept: Common Access Control format for all components -```{dec_rec} One Format for Access Control List(s) (ACL) +```{dec_rec} One Format for Access Control (and following the Access Control List (ACL)) :id: dec_rec__platform__acl_concept :status: proposed - :context: Common ACL format for all components + :context: Common Access Control format for all components :decision: open ``` @@ -29,96 +29,27 @@ Consequences ------------ - To prevent each component from implementing compeletley own mechanism for persmission enforcement; the decision should be an alignment on a common ACL format, so that all components can use: + To prevent each component from implementing completley own mechanism for permission enforcement; the decision should 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 + - updates due to parser vulnerabilities can be centralized 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 (example): - -```json -{ - "policyVersion": 1, - "policyId": "example-acl-policy-001", - "defaultEffect": "deny", - "generatedBy": "install-update-manager", - "generatedAt": "2026-06-17T14:28:00Z", - - "services": - { - "111": - { - "serviceName": "someservice", - "serviceInstances": { - "500": - { - "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": {}} - } - } - } - } - } - }, - "crypto": - { - "0": - { - "keyspaceName": "tls_auth", - "keys": - { - "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 format & properties (example at the bottom): - proposed json scheme: + proposed json scheme: ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/acl-policy.schema.json", + "$id": "acl-policy.schema.json", "title": "ACL Configuration Schema", "type": "object", "additionalProperties": false, @@ -170,15 +101,36 @@ }, "crypto": { "type": "object", - "propertyNames": { - "$ref": "#/$defs/uint16Key" - }, - "additionalProperties": { - "$ref": "#/$defs/keyspace" + "additionalProperties": false, + "properties": { + "generic": { + "$ref": "#/$defs/cryptoLimits" + } + }, + "patternProperties": { + "^(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])$": { + "$ref": "#/$defs/keyspace" + } } } }, "$defs": { + "version": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + { + "type": "string", + "maxLength": 128 + } + ] + } + }, "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])$" @@ -187,17 +139,6 @@ "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": [ @@ -205,19 +146,6 @@ 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", @@ -286,11 +214,10 @@ "additionalProperties": false, "required": [ "providerName", - "criticality", "version", - "tlsenable", - "ipsecenable", - "macsecenable", + "precondition_tlsenabled", + "precondition_ipsecenabled", + "precondition_macsecenabled", "specifics", "allow" ], @@ -300,21 +227,18 @@ "minLength": 1, "maxLength": 128 }, - "criticality": { - "$ref": "#/$defs/criticality" - }, "version": { "type": "integer", "minimum": 0, "maximum": 65535 }, - "tlsenable": { + "precondition_tlsenabled": { "$ref": "#/$defs/binaryFlag" }, - "ipsecenable": { + "precondition_ipsecenabled": { "$ref": "#/$defs/binaryFlag" }, - "macsecenable": { + "precondition_macsecenabled": { "$ref": "#/$defs/binaryFlag" }, "specifics": { @@ -359,8 +283,6 @@ "required": [ "name", "rights", - "version", - "criticality", "specifics" ], "properties": { @@ -370,26 +292,10 @@ "maxLength": 128 }, "rights": { - "$ref": "#/$defs/rights" + "$ref": "com.rights.schema.json" }, "version": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "integer", - "minimum": 0, - "maximum": 65535 - }, - { - "type": "string", - "maxLength": 128 - } - ] - } - }, - "criticality": { - "$ref": "#/$defs/criticality" + "$ref": "#/$defs/version" }, "specifics": { "$ref": "#/$defs/specifics" @@ -402,7 +308,6 @@ "required": [ "name", "rights", - "criticality", "specifics" ], "properties": { @@ -412,13 +317,13 @@ "maxLength": 128 }, "rights": { - "$ref": "#/$defs/rights" - }, - "criticality": { - "$ref": "#/$defs/criticality" + "$ref": "com.rights.schema.json" }, "specifics": { "$ref": "#/$defs/specifics" + }, + "version": { + "$ref": "#/$defs/version" } } }, @@ -480,73 +385,223 @@ "maxLength": 128 }, "read": { - "$ref": "#/$defs/keyAccessList" + "$ref": "#/$defs/keyAccessMap" }, "use": { - "$ref": "#/$defs/keyAccessList" + "$ref": "#/$defs/keyAccessMap" }, "write": { - "$ref": "#/$defs/keyAccessList" + "$ref": "#/$defs/keyAccessMap" } } }, - "keyAccessList": { - "type": "array", - "items": { - "$ref": "#/$defs/keyAccessEntry" - } - }, - "keyAccessEntry": { + "subjectKey": { + "type": "string", + "maxLength": 512, + "description": "Canonical access subject key. Components use '=' and are separated by '|'. Fixed order: otherid, vmid, uid, policy. Components in one key have AND semantics.", + "oneOf": [ + { + "description": "UID only, optionally followed by policy", + "pattern": "^uid=(-1|0|[1-9][0-9]{0,9})(\\|policy=[A-Za-z0-9._-]+)?$" + }, + { + "description": "VMID and UID, optionally followed by policy", + "pattern": "^vmid=(0|[1-9][0-9]{0,9})\\|uid=(-1|0|[1-9][0-9]{0,9})(\\|policy=[A-Za-z0-9._-]+)?$" + }, + { + "description": "Other ID alone, or with UID, optionally followed by policy", + "pattern": "^otherid=[A-Za-z0-9._-]+(\\|uid=(-1|0|[1-9][0-9]{0,9}))?(\\|policy=[A-Za-z0-9._-]+)?$" + }, + { + "description": "Other ID, VMID and UID, optionally followed by policy", + "pattern": "^otherid=[A-Za-z0-9._-]+\\|vmid=(0|[1-9][0-9]{0,9})\\|uid=(-1|0|[1-9][0-9]{0,9})(\\|policy=[A-Za-z0-9._-]+)?$" + }, + { + "description": "Policy only", + "pattern": "^policy=[A-Za-z0-9._-]+$" + } + ] + }, + "cryptoOperation": { + "type": "string", + "enum": [ + "hash", + "encrypt", + "decrypt", + "sign", + "verify", + "keyderive", + "wrap", + "unwrap", + "mac", + "random" + ] + }, + "keyAccessOptions": { + "type": "object", + "additionalProperties": false, + "properties": { + "operations": { + "description": "Optional restriction to the listed cryptographic operations. If absent, the access category itself is not further restricted by operation.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/cryptoOperation" + } + } + } + }, + "keyAccessMap": { "type": "object", - "additionalProperties": false, + "propertyNames": { + "$ref": "#/$defs/subjectKey" + }, + "additionalProperties": { + "$ref": "#/$defs/keyAccessOptions" + } + }, + "cryptoLimits": { + "type": "object", + "propertyNames": { + "$ref": "#/$defs/subjectKey" + }, + "additionalProperties": { + "type": "object", + "additionalProperties": false, + "properties": { + "job_limit": { + "type": "integer", + "minimum": 0 + }, + "memory_limit_bytes": { + "type": "integer", + "minimum": 0 + } + } + } + } + } +} +``` + Own rights schema which (can be if required adapted) for communication (IPC, SOME/IP) + Default support for: + read := subscribe/1:1/consume/request aka receive response + write := publish/1:1/produce/send response + monitor := observe, without ability to lock while reading or influence the program flow - "anyOf": [ - { - "required": ["uid"] - }, - { - "required": ["policy"] - }, - { - "required": ["vmid", "uid"] - }, - { - "required": ["otherid"] - } - ], +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "com.rights.schema.json", + "title": "Access Control for Communication Schema", + "description": "Allowed access rights for communication.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "read", + "write", + "monitor" + ], + "maxLength": 128 + }, + "uniqueItems": true +} - "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 + Example: + +```json +{ + "policyVersion": 1, + "policyId": "example-acl-policy-001", + "defaultEffect": "deny", + "generatedBy": "install-update-manager", + "generatedAt": "2026-06-17T14:28:00Z", + + "services": + { + "111": + { + "serviceName": "someservice", + "serviceInstances": { + "500": + { + "providerName": "fancy_name", + "version": 5, + "precondition_tlsenabled": 1, + "precondition_ipsecenabled": 1, + "precondition_macsecenabled":1, + "specifics": {}, + "allow": + { + "uids": + { + "101":{"rights": ["write"],"name": "oem.app.1","version": [],"specifics": {}}, + "102":{"rights": ["read"],"name": "oem.app.2","version": [],"specifics": {}}, + "103":{"rights": ["read"],"name": "tier1.daemon.1","version": [],"specifics": {}} + }, + "ips": + { + "10.1.15.2":{"name": "ecu_1","rights": ["write"],"version": [],"specifics": {}}, + "10.1.15.3":{"name": "ecu_2_app3","rights": ["read"],"version": [],"specifics": {}} + } + } } } } - + }, + "crypto": + { + "generic": + { + "uid=1": {"job_limit":5, "memory_limit_bytes": 8178}, + "vmid=3|uid=1": {"job_limit": 3, "memory_limit_bytes": 128}, + "otherid=someipd": {"job_limit":10, "memory_limit_bytes": 20000} + }, + "0": + { + "keyspaceName": "tls_auth", + "keys": + { + "1": + { + "name": "tls_auth_priv", + "read": {}, + "use": + { + "otherid=special_handling_1|uid=1": {}, + "vmid=4|uid=2": {"operations": ["hash"]} + }, + "write": + { + "uid=1|policy=someipd_t": {} + } + }, + "2": + { + "name": "tls_auth_pub", + "read": + { + "uid=-1":{} + }, + "use": + { + "uid=1": {}, + "vmid=4|uid=2": {} + }, + "write": + { + "uid=1|policy=someipd_t":{} + } + } + } + } } } ``` - Justification for the Decision ------------------------------