Skip to content

Commit

Permalink
refactor(AID): reflect latest security representation (eclipse-thingw…
Browse files Browse the repository at this point in the history
…eb#1150)

using list of References
  • Loading branch information
danielpeintner authored Nov 7, 2023
1 parent e25cbd9 commit cc46531
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 22 deletions.
54 changes: 45 additions & 9 deletions packages/td-tools/src/util/asset-interface-description.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ export class AssetInterfaceDescriptionUtil {
const submdelElements = [];
for (const protocol of protocols) {
// use protocol binding prefix like "http" for name
const submodelElementIdShort = protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase();
const submodelElementIdShort = this.sanitizeIdShort(
protocol === undefined ? "Interface" : "Interface" + protocol.toUpperCase()
);

const supplementalSemanticIds = [this.createSemanticId("https://www.w3.org/2019/wot/td")];
if (protocol !== undefined) {
Expand All @@ -159,7 +161,7 @@ export class AssetInterfaceDescriptionUtil {
}

const submdelElement = {
idShort: this.sanitizeIdShort(submodelElementIdShort),
idShort: submodelElementIdShort,
semanticId: this.createSemanticId(
"https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface"
),
Expand All @@ -174,7 +176,7 @@ export class AssetInterfaceDescriptionUtil {
semanticId: this.createSemanticId("https://www.w3.org/2019/wot/td#title"),
},
// created, modified, support ?
this.createEndpointMetadata(td), // EndpointMetadata like base, security and securityDefinitions
this.createEndpointMetadata(td, aidID, submodelElementIdShort), // EndpointMetadata like base, security and securityDefinitions
this.createInterfaceMetadata(td, protocol), // InterfaceMetadata like properties, actions and events
{
idShort: "ExternalDescriptor",
Expand Down Expand Up @@ -382,8 +384,16 @@ export class AssetInterfaceDescriptionUtil {
} else if (v.idShort === "security") {
if (v.value instanceof Array) {
for (const securityValue of v.value) {
if (securityValue.value != null) {
security.push(securityValue.value);
if (securityValue.value != null && securityValue.value.keys instanceof Array) {
// e.g.,
// {
// "type": "SubmodelElementCollection",
// "value": "nosec_sc"
// }
const key = securityValue.value.keys[securityValue.value.keys.length - 1]; // last path
if (key.value != null) {
security.push(key.value);
}
}
}
}
Expand Down Expand Up @@ -822,7 +832,11 @@ export class AssetInterfaceDescriptionUtil {
return JSON.stringify(thing);
}

private createEndpointMetadata(td: ThingDescription): Record<string, unknown> {
private createEndpointMetadata(
td: ThingDescription,
submodelIdShort: string,
submodelElementIdShort: string
): Record<string, unknown> {
const values: Array<unknown> = [];

// base ?
Expand Down Expand Up @@ -851,9 +865,31 @@ export class AssetInterfaceDescriptionUtil {
if (td.security != null) {
for (const secKey of td.security) {
securityValues.push({
valueType: "xs:string",
value: secKey,
modelType: "Property",
value: {
type: "ModelReference",
keys: [
{
type: "Submodel",
value: submodelIdShort,
},
{
type: "SubmodelElementCollection",
value: submodelElementIdShort,
},
{
type: "SubmodelElementCollection",
value: "EndpointMetadata",
},
{
type: "SubmodelElementCollection",
value: "securityDefinitions",
},
{
type: "SubmodelElementCollection",
value: secKey,
},
],
},
});
}
}
Expand Down
42 changes: 36 additions & 6 deletions packages/td-tools/test/AssetInterfaceDescriptionTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,11 @@ class AssetInterfaceDescriptionUtilTest {
.to.have.property("value")
.to.be.an("array")
.to.have.lengthOf.greaterThan(0);
expect(endpointMetadataValue.value[0].value).to.equal("nosec_sc");
expect(endpointMetadataValue.value[0]).to.have.property("value");
const modelReferenceValue = endpointMetadataValue.value[0].value;
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("nosec_sc");
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
hasSecurityDefinitions = true;
expect(endpointMetadataValue)
Expand Down Expand Up @@ -472,6 +476,7 @@ class AssetInterfaceDescriptionUtilTest {
td1: ThingDescription = {
"@context": "https://www.w3.org/2022/wot/td/v1.1",
title: "testTD",
id: "urn:uuid:0804d572-cce8-422a-bb7c-4412fcd56f03",
securityDefinitions: {
basic_sc: {
scheme: "basic",
Expand Down Expand Up @@ -517,9 +522,11 @@ class AssetInterfaceDescriptionUtilTest {

const smObj = JSON.parse(sm);
expect(smObj).to.have.property("idShort").that.equals("AssetInterfacesDescription");
expect(smObj).to.have.property("id");
expect(smObj).to.have.property("semanticId");
expect(smObj).to.have.property("submodelElements").to.be.an("array").to.have.lengthOf.greaterThan(0);
const smInterface = smObj.submodelElements[0];
expect(smInterface).to.have.property("idShort");
expect(smInterface).to.have.property("value").to.be.an("array").to.have.lengthOf.greaterThan(0);
expect(smInterface)
.to.have.property("semanticId")
Expand Down Expand Up @@ -557,7 +564,28 @@ class AssetInterfaceDescriptionUtilTest {
.to.have.property("value")
.to.be.an("array")
.to.have.lengthOf.greaterThan(0);
expect(endpointMetadataValue.value[0].value).to.equal("basic_sc");
expect(endpointMetadataValue.value[0]).to.have.property("value");
const modelReferenceValue = endpointMetadataValue.value[0].value;
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
expect(modelReferenceValue.keys[0]).to.have.property("type").to.equal("Submodel");
expect(modelReferenceValue.keys[0]).to.have.property("value").to.equal(smObj.id);
expect(modelReferenceValue.keys[1])
.to.have.property("type")
.to.equal("SubmodelElementCollection");
expect(modelReferenceValue.keys[1]).to.have.property("value").to.equal(smInterface.idShort);
expect(modelReferenceValue.keys[2])
.to.have.property("type")
.to.equal("SubmodelElementCollection");
expect(modelReferenceValue.keys[2]).to.have.property("value").to.equal("EndpointMetadata");
expect(modelReferenceValue.keys[3])
.to.have.property("type")
.to.equal("SubmodelElementCollection");
expect(modelReferenceValue.keys[3]).to.have.property("value").to.equal("securityDefinitions");
expect(modelReferenceValue.keys[4])
.to.have.property("type")
.to.equal("SubmodelElementCollection");
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("basic_sc");
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
hasSecurityDefinitions = true;
expect(endpointMetadataValue)
Expand Down Expand Up @@ -725,11 +753,9 @@ class AssetInterfaceDescriptionUtilTest {
expect(hasInterfaceMetadata, "No InterfaceMetadata").to.equal(true);

// Test to use all possible prefixes -> in this case it is only https
// Note: id is autogenerated (if not present) -> needs to be exluded/removed/set in TD
const sm2 = this.assetInterfaceDescriptionUtil.transformTD2SM(JSON.stringify(this.td1));
const sm2Obj = JSON.parse(sm2);
// Note: id is autogenerated and needs to be exluded/removed
delete smObj.id;
delete sm2Obj.id;
expect(smObj).to.eql(sm2Obj);
}

Expand Down Expand Up @@ -837,7 +863,11 @@ class AssetInterfaceDescriptionUtilTest {
.to.have.property("value")
.to.be.an("array")
.to.have.lengthOf.greaterThan(0);
expect(endpointMetadataValue.value[0].value).to.equal("nosec_sc");
expect(endpointMetadataValue.value[0]).to.have.property("value");
const modelReferenceValue = endpointMetadataValue.value[0].value;
expect(modelReferenceValue).to.have.property("type").to.equal("ModelReference");
expect(modelReferenceValue).to.have.property("keys").to.be.an("array").to.have.lengthOf(5);
expect(modelReferenceValue.keys[4]).to.have.property("value").to.equal("nosec_sc");
} else if (endpointMetadataValue.idShort === "securityDefinitions") {
hasSecurityDefinitions = true;
}
Expand Down
29 changes: 26 additions & 3 deletions packages/td-tools/test/util/counterHTTP.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,32 @@
"typeValueListElement": "SubmodelElement",
"value": [
{
"valueType": "xs:string",
"value": "nosec_sc",
"modelType": "Property"
"value": {
"type": "ModelReference",
"keys": [
{
"type": "Submodel",
"value": "https://example.com/ids/sm/4333_9041_7022_4184"
},
{
"type": "SubmodelElementCollection",
"value": "InterfaceHTTP"
},
{
"type": "SubmodelElementCollection",
"value": "EndpointMetadata"
},
{
"type": "SubmodelElementCollection",
"value": "securityDefinitions"
},
{
"type": "SubmodelElementCollection",
"value": "nosec_sc"
}
]
},
"modelType": "ReferenceElement"
}
],
"modelType": "SubmodelElementList"
Expand Down
32 changes: 28 additions & 4 deletions packages/td-tools/test/util/inverterModbus.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
],
"submodelElements": [
{
"idShort": "InterfaceMODBUS+TCP",
"idShort": "InterfaceMODBUS_TCP",
"value": [
{
"idShort": "title",
Expand All @@ -50,11 +50,35 @@
},
{
"idShort": "security",
"typeValueListElement": "SubmodelElement",
"value": [
{
"valueType": "xs:string",
"value": "nosec_sc",
"modelType": "Property"
"value": {
"type": "ModelReference",
"keys": [
{
"type": "Submodel",
"value": "uri:dev:inverter"
},
{
"type": "SubmodelElementCollection",
"value": "InterfaceMODBUS_TCP"
},
{
"type": "SubmodelElementCollection",
"value": "EndpointMetadata"
},
{
"type": "SubmodelElementCollection",
"value": "securityDefinitions"
},
{
"type": "SubmodelElementCollection",
"value": "nosec_sc"
}
]
},
"modelType": "ReferenceElement"
}
],
"modelType": "SubmodelElementCollection"
Expand Down

0 comments on commit cc46531

Please sign in to comment.