I am trying to connect to an opcua server with unknown securityMode and securityPolicy. Probably I have a basic understanding problem, but according to the OPCUA specification I can get the EndpointDescription via the local DiscoveryServer and then open a SecureChannel (session).
Currently I connect to the server without specifying the security settings, read out the endpoints and would then select an appropriate security setting and reconnect.
const getEndpoints = function (endpointUrl) {
return new Promise(function (resolve, reject) {
let client = new opcua.OPCUAClient();
client.connect(endpointUrl, function (err) {
if(err) reject(new Error(err));
client.getEndpointsRequest(function (err,endpoints) {
let reducedEndpoints = endpoints.map(endpoint =>
({
endpointUrl: endpoint.endpointUrl,
securityMode: endpoint.securityMode,
securityPolicy: endpoint.securityPolicyUri,
})
);
resolve(endpoints);
// resolve(reducedEndpoints);
client.disconnect();
})
})
})
}
const connect = function (endpointUrl, options) {
return new Promise(function (resolve, reject) {
const defaultOptions = {
connectionStrategy: {
maxRetry: 6,
},
keepSessionAlive: true,
endpoint_must_exist: false,
securityMode: options.MessageSecurityMode.NONE,
securityPolicy: SecurityPolicy.None,
};
let client = new opcua.OPCUAClient(Object.assign({}, defaultOptions, options));
client.connect(endpointUrl, function (err) {
if(err) {
reject(new Error(err));
}
resolve(client)
});
});
};
That doesn't feel right. It would be nice if someone would help me with an example.
Best Regards
// with node-opcua@0.4.1
const opcua = require("node-opcua");
async function getEndpoints(endpointUrl) {
let client = new opcua.OPCUAClient();
await client.connect(endpointUrl);
const endpoints = await client.getEndpoints();
const reducedEndpoints = endpoints.map(endpoint => ({
endpointUrl: endpoint.endpointUrl,
securityMode: endpoint.securityMode.toString(),
securityPolicy: endpoint.securityPolicyUri.toString(),
}));
await client.disconnect();
return reducedEndpoints;
}
async function main() {
const endpoints = await getEndpoints("opc.tcp://opcuademo.sterfive.com:26543");
console.log(endpoints);
}
main().then();
This code will output:
[ { endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'NONE',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#None' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGN',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGN',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic256' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGN',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGNANDENCRYPT',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGNANDENCRYPT',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic256' },
{ endpointUrl: 'opc.tcp://opcuademo.sterfive.com:26543',
securityMode: 'SIGNANDENCRYPT',
securityPolicy: 'http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256' } ]
This being said, an node-opcua client will automatically query the server endpoint during connect and verifies that the securityMode and securityPolicy requested by the user is available.
// with node-opcua@0.4.1
const opcua = require("node-opcua");
async function verifyEndpointAndConnect(endpointUrl) {
let client = new opcua.OPCUAClient();
await client.connect(endpointUrl);
// note that client has already requested the server endpoints
// during the connection. We can now simply query the Application
// description matching our security settings
const applicationDescription = client.findEndpointForSecurity(
opcua.MessageSecurityMode.SIGN,
opcua.SecurityPolicy.Basic256Sha256
);
await client.disconnect();
if (applicationDescription) {
console.log("Yes! the server support this endpoints:");
console.log(applicationDescription.toString());
}else {
console.log("Sorry! this server do not support the requested security mode");
return;
}
// let recreate our client with the requested security mode
client = new opcua.OPCUAClient({
securityMode: opcua.MessageSecurityMode.SIGN,
securityPolicy: opcua.SecurityPolicy.Basic256Sha256,
});
await client.connect(endpointUrl);
// [...] do something with this connected client.
await client.disconnect();
}
async function main() {
await verifyEndpointAndConnect("opc.tcp://opcuademo.sterfive.com:26543");
console.log("done");
}
main();