Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication Feature need to be Added #46

Open
vadivelk2023 opened this issue Apr 3, 2024 · 10 comments
Open

Authentication Feature need to be Added #46

vadivelk2023 opened this issue Apr 3, 2024 · 10 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@vadivelk2023
Copy link

Username and Password based authentication need to be added.

@vadivelk2023 vadivelk2023 added the enhancement New feature or request label Apr 3, 2024
@jiekechoo
Copy link
Contributor

@vadivelk2023
Can you describe the details? Give us more information, please.

@vadivelk2023
Copy link
Author

@vadivelk2023 Can you describe the details? Give us more information, please.

The OPC UA Protocol supports Authentication mechanisms such as Username/Password, X509 Certificate, JWT token based authentication. For more details please visit https://reference.opcfoundation.org/Core/Part2/v105/docs/5.2.3

Please consider these auth mechanisms for OPC UA device service.

@cloudxxx8 cloudxxx8 added the help wanted Extra attention is needed label Apr 3, 2024
@jiekechoo
Copy link
Contributor

OK, I see.
The device service device-opc-ua has supported X509 Certificate, I'll try to add Username/Password, JWT token based authentication.
If you can contribute, welcome. 😄

@vadivelk2023
Copy link
Author

Thanks for the Invite :) However, the library used in the device-opc-ua (https://github.com/gopcua/opcua) supports all these authentication mechanisms. The only thing that needs to be done is adding additional keys to get these values in config and adding two more functions to pass the credentials to the underlying Native gopcua library based on the auth mode mentioned in config.

I have another doubt and please consider this as a suggestion as well. The authentication information is mentioned in configuration.yml file. Whenever a new device is added to the device-opc-ua service its auth details need to be added to the configuration.yml file. As of now based on my understanding there is no API to change/update the content of the configuration.yml file (Example is App Service Configurable completely works based on the configuration.yml file - The only way to update the file content is rebuilding the image or mounting the file from local file system - This also requires deleting the metadata volume). My suggestion is why don't we get these details from the device file itself? If it is maintained in the device file it can be updated through Core metadata API.

Like below

Path:cmd/res/devices/Simple-Devices.yaml

deviceList:

  • name: SimulationServer
    profileName: OPCUA-Server
    description: OPCUA device
    labels:
    • OPCUA
    • TEST
      protocols:
      opcua:
      Endpoint: "opc.tcp://192.168.123.21:53530/OPCUA/SimulationServer"
      Policy: None
      Mode: None
      CertFile: ''
      KeyFile: ''
      Writable:
      Resources: 'Counter,Random'

@jiekechoo
Copy link
Contributor

The suggestion as you mentioned in the second paragraph, it's a good idea. Maybe we'll refactor it in the next release v3.2 or later.

@cloudxxx8
Copy link
Member

The credentials should not be stored in core-metadata, but in the secret store.
The core-metadata should only persist the secret name in the protocol properties, and the device service should implement the logic to access secret store.
This feature could be implemented when we have any volunteer.

@Ldsystem
Copy link

@vadivelk2023 I have do something about what you've mention, you can find it here Ldsystem/device-opc-ua.
I've made some updates as follow:

  1. introduce connection pool to manage ua connections.
  2. accept SecurityPolicy and SecurityMode options from ProtocolProperties, so that user can specify different security policy for each opc server. In this case, opc server's cert is also needed for asymetric encryption, I also take it from ProtocolProperties with a new field RemotePemCert.
  3. Username authentication support.

But I'm totally new to golang and I've made a massive change of the code, so it is difficult for me to bring it back to this repo. you can try it before the updates come to life.

@vadivelk2023
Copy link
Author

@cloudxxx8 I agree with you regarding credential management.

@jiekechoo The device-opc-ua has provision to add certificate and key in configuration.yml. validation also fine. But it is not properly passed or handled in getClient function in subscriptionlistener.go file. My suggestions to improve this is

  1. Adding additional keys under OPCUASERVER in configuration file such a way that
    OPCUAServer:
    DeviceName: SimulationServer
    Auth: None #Options - None / UserNamePassword / Certificate
    Policy: None
    Mode: None
    CertFile: ''
    KeyFile: ''
    UserName: ''
    PassWord: ''
    Writable:
    Resources: 'Counter,Random'

  2. Checking the Auth value in getClient. Based on Auth value adding options to opts[]. here is the sample
    //common
    opcua.SecurityPolicy(policy),
    opcua.SecurityModeString(mode),
    //Auth None
    opcua.AuthAnonymous(),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeAnonymous),
    //Auth Username Password
    opcua.AuthUsername(UserName,Password),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeUserName),
    //Auth Certificate
    opcua.CertificateFile(certFile),
    opcua.PrivateKeyFile(keyFile),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeCertificate),

The certificate paths were directly referring configuration.yml file content not secretstore. This need to be improved.

@Ldsystem I appreciate your effort. But in my experience I have seen connection pool for databases only not for OPCUA Servers. I am not sure it is required or not. please do a performance testing with and without connection pool. If there is some positive results we may consider connection pool as well.

@jiekechoo
Copy link
Contributor

The credentials should not be stored in core-metadata, but in the secret store. The core-metadata should only persist the secret name in the protocol properties, and the device service should implement the logic to access secret store. This feature could be implemented when we have any volunteer.

I see.

@Ldsystem
Copy link

Ldsystem commented Apr 26, 2024

@cloudxxx8 I agree with you regarding credential management.

@jiekechoo The device-opc-ua has provision to add certificate and key in configuration.yml. validation also fine. But it is not properly passed or handled in getClient function in subscriptionlistener.go file. My suggestions to improve this is

  1. Adding additional keys under OPCUASERVER in configuration file such a way that
    OPCUAServer:
    DeviceName: SimulationServer
    Auth: None #Options - None / UserNamePassword / Certificate
    Policy: None
    Mode: None
    CertFile: ''
    KeyFile: ''
    UserName: ''
    PassWord: ''
    Writable:
    Resources: 'Counter,Random'
  2. Checking the Auth value in getClient. Based on Auth value adding options to opts[]. here is the sample
    //common
    opcua.SecurityPolicy(policy),
    opcua.SecurityModeString(mode),
    //Auth None
    opcua.AuthAnonymous(),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeAnonymous),
    //Auth Username Password
    opcua.AuthUsername(UserName,Password),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeUserName),
    //Auth Certificate
    opcua.CertificateFile(certFile),
    opcua.PrivateKeyFile(keyFile),
    opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeCertificate),

The certificate paths were directly referring configuration.yml file content not secretstore. This need to be improved.

@Ldsystem I appreciate your effort. But in my experience I have seen connection pool for databases only not for OPCUA Servers. I am not sure it is required or not. please do a performance testing with and without connection pool. If there is some positive results we may consider connection pool as well.

@vadivelk2023 I did performance tests indeed, here are the results:

  1. Without reusable client:
goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_WithoutReuseClient
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_WithoutReuseClient-8   	     638	   1699040 ns/op
PASS
  1. With 1 reusable client, no encryption:
goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_ReuseClient
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_ReuseClient-8   	    8966	    128933 ns/op
PASS
  1. With 4 reusable clients, no encryption:
goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_ReuseClientAsync
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_ReuseClientAsync-8   	   12667	     92111 ns/op
PASS
  1. With 1 reusable client and Basic256Sha256 signing and encryption:
goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_ReuseClientWithEncryption
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_ReuseClientWithEncryption-8   	    5190	    216897 ns/op
PASS
  1. With 4 reusable clients and Basic256Sha256 signing and encryption:
goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_ReuseClientWithEncryptionAsync
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_ReuseClientWithEncryptionAsync-8   	    6984	    150175 ns/op
PASS

I also try #48 on my local computer, it performs nearly the same as my single reusable client test case:

goos: darwin
goarch: arm64
pkg: github.com/edgexfoundry/device-opc-ua/internal/driver
Benchmark_HandleReadCommands_ReuseClient
Listening on 0.0.0.0:48408
Benchmark_HandleReadCommands_ReuseClient-8   	    9033	    128572 ns/op
PASS

As we can see, when running with SecurityPolicyNone, connection pool reduces ns per op by 30000 ns. when running with SecurityPolicyBasic256Sha256 signing and ecryption, pool reduce ns/op by 60000ns. Despite the small effect, it is still helpful for reducing race condition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants