Search code examples
opcopc-uanode-opcua

How to get connected clients and client certificate in node-opcua server


I have a node-opcua server setup with 2 clients connected to it with Security Mode set to SignAndEncrypt. Now, I have 2 questions:

  1. Is there a way for the server to find out how many clients are connected to it?
  2. The server application will like to know the identity of a connected client, is there an API to get the client certificate obtained during OpenSecureChannel?

Solution

  • OPCUA Server can expose such information under the RootFolder.Server.ServerDiagnostics node, and the information you need shall be accessible through OPCUA.

    This little node-opcua client program will show you how to do.

    note:

    • that certain data such as security diagnostics requires a secure connection and a non-anonymous user

    client_extract_server_diagnostic.ts

    // this script is typescript and can be run this way
    // $ npx ts-node client_extract_server_diagnostic.ts
    
    import { 
        AttributeIds,
        OPCUAClient,
        ClientSession, 
        StatusCodes,
        MessageSecurityMode,
        SecurityPolicy,
        UserIdentityInfoUserName,
        UserTokenType   
    } from "node-opcua";
    
    // the opcua server to connect to
    const endpointUrl = "opc.tcp://localhost:48010";
    
    // the credential 
    const userIdentityToken: UserIdentityInfoUserName = {
        password: "secret",
        userName: "root",
        type: UserTokenType.UserName
    };
    
    async function extractServerStatistics(session: ClientSession) {
    
        const nodesToRead = [
            { 
                attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_EnabledFlag" 
            },
            { 
                attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_ServerDiagnosticsSummary_CurrentSessionCount" //i=2277 
            },
            {
                attributeIds: AttributeIds.Value, nodeId:"Server_ServerDiagnostics_ServerDiagnosticsSummary_CurrentSubscriptionCount" // i=2285 
            },
            {
                attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_ServerDiagnosticsSummary_CumulatedSessionCount" // i=2278 
            },
            {
                attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_ServerDiagnosticsSummary_CumulatedSubscriptionCount" // i=2278 
            },
            {
                attributeIds: AttributeIds.Value, nodeId: "Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray" // i=3708 
            }
    
        ];
        const dataValues = await session.read(nodesToRead);
    
        console.log("Diagnostic enabled ?         = ", dataValues[0].value.value);
        console.log("Current Session Count        = ", dataValues[1].value.value);
        console.log("Current Subscription Count   = ", dataValues[2].value.value);
        console.log("Cumulated Session Count      = ", dataValues[3].value.value);
        console.log("Cumulated Subscription Count = ", dataValues[4].value.value);
    
        // note reading SessionSecurityDiagnotiscArray may requires authenticated session to succeed
        console.log("SessionSecurityDiagnotiscArray       = ");
    
        if (dataValues[5].statusCode === StatusCodes.Good) {
            const sessionSecurityDiagnosticArray = dataValues[5].value.value;
            // console.log(dataValues[5].value.value.toString());
            for (const sessionSecurityDiagnostic of sessionSecurityDiagnosticArray)  {
                console.log(" session client certificate ", sessionSecurityDiagnostic.clientCertificate.toString("base64"));
                console.log();
            }
        } else {
            console.log(dataValues[5].toString());
        }
    }
    ( async () => {
    
        try {
            const client = OPCUAClient.create({
                endpoint_must_exist: false,
                securityMode: MessageSecurityMode.SignAndEncrypt,
                securityPolicy: SecurityPolicy.Basic256Sha256,
    
            });
            client.on("backoff",() => console.log("still trying to connec to ", endpointUrl));
    
            await client.connect(endpointUrl);
    
            const session = await client.createSession(userIdentityToken);
    
            await extractServerStatistics(session);
    
            await session.close();
            await client.disconnect();
            console.log("done");
        } catch(err) {
            console.log("Err" , err.message);
            process.exit(1);
        }
    })();