mirror of
https://github.com/FreeOpcUa/opcua-asyncio
synced 2025-10-29 17:07:18 +08:00
fix connecting to new prosys opcua server (#1827)
* make prosys accept our certificate again in examples * allow to send certificate without encryption or user identification as prosys now requires. Had to fix a few new bugs that sudently appeared... * clean imports * remove leftover prints, less verbose when renaming struct * remove unused variable --------- Co-authored-by: Olivier <olivier@helitech>
This commit is contained in:
@@ -2,12 +2,13 @@ import asyncio
|
||||
import logging
|
||||
import socket
|
||||
import dataclasses
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
|
||||
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Type, Union, cast, Callable, Coroutine
|
||||
from urllib.parse import urlparse, unquote, ParseResult
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
|
||||
|
||||
import asyncua
|
||||
from asyncua import ua
|
||||
from .ua_client import UaClient
|
||||
@@ -65,9 +66,9 @@ class Client:
|
||||
if have_password:
|
||||
self._password = unquote(password)
|
||||
|
||||
self.name = "Pure Python Async. Client"
|
||||
self.name = "Pure Python Async Client"
|
||||
self.description = self.name
|
||||
self.application_uri = "urn:freeopcua:client"
|
||||
self.application_uri = "urn:example.org:FreeOpcUa:opcua-asyncio"
|
||||
self.product_uri = "urn:freeopcua.github.io:client"
|
||||
self.security_policy = security_policies.SecurityPolicyNone()
|
||||
self.secure_channel_id = None
|
||||
@@ -497,10 +498,16 @@ class Client:
|
||||
desc.ApplicationName = ua.LocalizedText(self.name)
|
||||
desc.ApplicationType = ua.ApplicationType.Client
|
||||
params = ua.CreateSessionParameters()
|
||||
params.ServerUri = f"urn:{self.server_url.hostname}{self.server_url.path.replace('/', ':')}"
|
||||
# at least 32 random bytes for server to prove possession of private key (specs part 4, 5.6.2.2)
|
||||
nonce = create_nonce(32)
|
||||
params.ClientNonce = nonce
|
||||
params.ClientCertificate = self.security_policy.host_certificate
|
||||
if self.security_policy.host_certificate:
|
||||
params.ClientCertificate = self.security_policy.host_certificate
|
||||
elif self.user_certificate:
|
||||
params.ClientCertificate = uacrypto.der_from_x509(self.user_certificate)
|
||||
else:
|
||||
params.ClientCertificate = None
|
||||
params.ClientDescription = desc
|
||||
params.EndpointUrl = self.server_url.geturl()
|
||||
params.SessionName = f"{self.description} Session{self._session_counter}"
|
||||
@@ -639,7 +646,7 @@ class Client:
|
||||
"""
|
||||
Activate session using either username and password or private_key
|
||||
"""
|
||||
user_certificate = certificate or self.user_certificate
|
||||
user_certificate = certificate
|
||||
params = ua.ActivateSessionParameters()
|
||||
challenge = b""
|
||||
if self.security_policy.peer_certificate is not None:
|
||||
@@ -652,7 +659,7 @@ class Client:
|
||||
params.ClientSignature.Algorithm = security_policies.SecurityPolicyBasic256.AsymmetricSignatureURI
|
||||
params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature(challenge)
|
||||
params.LocaleIds = self._locale
|
||||
if not username and not user_certificate:
|
||||
if not username and not (user_certificate and self.user_private_key):
|
||||
self._add_anonymous_auth(params)
|
||||
elif user_certificate:
|
||||
self._add_certificate_auth(params, user_certificate, challenge)
|
||||
|
||||
@@ -219,7 +219,6 @@ class UaDirectory:
|
||||
and shall be ignored by the caller.
|
||||
"""
|
||||
_logger.debug("Request to create file %s in %s", file_name, self._directory_node)
|
||||
print(f"Request to create file {file_name} in {self._directory_node}")
|
||||
create_file_node = await self._directory_node.get_child("CreateFile")
|
||||
arg1_file_name = Variant(file_name, VariantType.String)
|
||||
arg2_request_file_open = Variant(request_file_open, VariantType.Boolean)
|
||||
|
||||
@@ -132,7 +132,7 @@ def clean_name(name):
|
||||
return name
|
||||
newname = re.sub(r"\W+", "_", name)
|
||||
newname = re.sub(r"^[0-9]+", r"_\g<0>", newname)
|
||||
_logger.warning("renamed %s to %s due to Python syntax", name, newname)
|
||||
_logger.info("renamed %s to %s due to Python syntax", name, newname)
|
||||
return newname
|
||||
|
||||
|
||||
@@ -363,7 +363,8 @@ async def _recursive_parse(server, base_node, dtypes, parent_sdef=None, add_exis
|
||||
if parent_sdef:
|
||||
for sfield in reversed(parent_sdef.Fields):
|
||||
sdef.Fields.insert(0, sfield)
|
||||
dtypes.append(DataTypeSorter(desc.NodeId, name, desc, sdef))
|
||||
if isinstance(sdef, ua.StructureDefinition):
|
||||
dtypes.append(DataTypeSorter(desc.NodeId, name, desc, sdef))
|
||||
return _recursive_parse(
|
||||
server,
|
||||
server.get_node(desc.NodeId),
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from enum import Enum
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from asyncua import ua
|
||||
from asyncua.server.users import UserRole
|
||||
|
||||
ADMIN_TYPES = [
|
||||
ua.ObjectIds.RegisterServerRequest_Encoding_DefaultBinary,
|
||||
@@ -37,6 +40,22 @@ USER_TYPES = [
|
||||
]
|
||||
|
||||
|
||||
class UserRole(Enum):
|
||||
"""
|
||||
User Roles
|
||||
"""
|
||||
|
||||
Admin = 0
|
||||
Anonymous = 1
|
||||
User = 3
|
||||
|
||||
|
||||
@dataclass
|
||||
class User:
|
||||
role: UserRole = UserRole.Anonymous
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
class PermissionRuleset:
|
||||
"""
|
||||
Base class for permission ruleset
|
||||
|
||||
@@ -139,9 +139,8 @@ class TrustStore:
|
||||
store_ctx.verify_certificate()
|
||||
_logger.debug("Use trusted certificate : '%s'", _certificate.get_subject().CN)
|
||||
return True
|
||||
except crypto.X509StoreContextError as exp:
|
||||
print(exp)
|
||||
_logger.warning('Not trusted certificate used: "%s"', _certificate.get_subject().CN)
|
||||
except crypto.X509StoreContextError:
|
||||
_logger.exception('Not trusted certificate used: "%s"', _certificate.get_subject().CN)
|
||||
return False
|
||||
|
||||
async def _load_trust_location(self, location: Path):
|
||||
|
||||
@@ -33,8 +33,8 @@ if TYPE_CHECKING:
|
||||
] # FIXME Check, if there are missing attribute types.
|
||||
|
||||
from asyncua import ua
|
||||
from asyncua.crypto.permission_rules import User, UserRole
|
||||
|
||||
from .users import User, UserRole
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ from .history import HistoryManager
|
||||
from .address_space import NodeData, AddressSpace, AttributeService, ViewService, NodeManagementService, MethodService
|
||||
from .subscription_service import SubscriptionService
|
||||
from .standard_address_space import standard_address_space
|
||||
from .users import User, UserRole
|
||||
from asyncua.crypto.permission_rules import User, UserRole
|
||||
from .internal_session import InternalSession
|
||||
from .event_generator import EventGenerator
|
||||
from ..crypto.validator import CertificateValidatorMethod
|
||||
|
||||
@@ -10,7 +10,7 @@ from ..common.callback import CallbackType, ServerItemCallback
|
||||
from ..common.utils import create_nonce, ServiceError
|
||||
from ..crypto.uacrypto import x509
|
||||
from .address_space import AddressSpace
|
||||
from .users import User, UserRole
|
||||
from asyncua.crypto.permission_rules import User, UserRole
|
||||
from .subscription_service import SubscriptionService
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
@@ -3,7 +3,7 @@ from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
from asyncua.crypto import uacrypto
|
||||
from asyncua.server.users import User, UserRole
|
||||
from asyncua.crypto.permission_rules import User, UserRole
|
||||
|
||||
|
||||
class UserManager:
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
"""
|
||||
Implement user management here.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class UserRole(Enum):
|
||||
"""
|
||||
User Roles
|
||||
"""
|
||||
|
||||
Admin = 0
|
||||
Anonymous = 1
|
||||
User = 3
|
||||
|
||||
|
||||
@dataclass
|
||||
class User:
|
||||
role: UserRole = UserRole.Anonymous
|
||||
name: Optional[str] = None
|
||||
18
examples/cert-config.cnf
Normal file
18
examples/cert-config.cnf
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_md = sha512
|
||||
distinguished_name = req_distinguished_name
|
||||
x509_extensions = v3_ext
|
||||
prompt = no
|
||||
|
||||
[req_distinguished_name]
|
||||
CN= freeopcua@somewhere
|
||||
O= My Organization
|
||||
DC= helitack
|
||||
|
||||
[ v3_ext ]
|
||||
subjectAltName = URI:urn:example.org:FreeOpcUa:opcua-asyncio
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
extendedKeyUsage = clientAuth, serverAuth
|
||||
basicConstraints = critical, CA:false
|
||||
@@ -17,13 +17,15 @@ class SubHandler:
|
||||
|
||||
|
||||
async def main():
|
||||
url = "opc.tcp://localhost:53530/OPCUA/SimulationServer/"
|
||||
url = "opc.tcp://localhost:53530/OPCUA/SimulationServer"
|
||||
# url = "opc.tcp://olivier:olivierpass@localhost:53530/OPCUA/SimulationServer/"
|
||||
async with Client(url=url) as client:
|
||||
client = Client(url=url)
|
||||
await client.load_client_certificate("my_cert.der")
|
||||
async with client:
|
||||
await client.load_data_type_definitions(overwrite_existing=True)
|
||||
print("Root children are", await client.nodes.root.get_children())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.WARN)
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -9,7 +9,7 @@ from asyncua import Client
|
||||
|
||||
async def main():
|
||||
client = Client("opc.tcp://localhost:53530/OPCUA/SimulationServer/")
|
||||
await client.set_security_string("Basic256Sha256,Sign,certificate-example.der,private-key-example.pem")
|
||||
await client.set_security_string("Basic256Sha256,Sign,my_cert.der,my_private_key.pem")
|
||||
client.session_timeout = 2000
|
||||
async with client:
|
||||
root = client.nodes.root
|
||||
|
||||
@@ -38,5 +38,13 @@ Step 3: openssl req -x509 -days 365 -new -out certificate.pem -key key.pem -conf
|
||||
this way is proved with Siemens OPC UA Client/Server!
|
||||
'
|
||||
|
||||
openssl req -x509 -newkey rsa:4096 -sha256 -keyout my_private_key.pem -out my_cert.pem -days 3650 -nodes -addext "subjectAltName = URI:urn:example.org:FreeOpcUa:python-opcua"
|
||||
|
||||
|
||||
|
||||
# Step 1: Generate PEM certificate and private key with correct extensions
|
||||
openssl req -x509 -newkey rsa:4096 -sha512 \
|
||||
-keyout my_private_key.pem -out my_cert.pem \
|
||||
-days 3650 -nodes -config cert-config.cnf
|
||||
|
||||
# Step 2: Convert certificate to DER format for OPC UA
|
||||
openssl x509 -outform der -in my_cert.pem -out my_cert.der
|
||||
|
||||
BIN
examples/my_cert.der
Normal file
BIN
examples/my_cert.der
Normal file
Binary file not shown.
33
examples/my_cert.pem
Normal file
33
examples/my_cert.pem
Normal file
@@ -0,0 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
52
examples/my_private_key.pem
Normal file
52
examples/my_private_key.pem
Normal file
@@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
+uSCWvvuNLawTWfq56DriXUkrXxQn/Y=
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from asyncua import Client, Server, ua
|
||||
from asyncua.server.users import UserRole, User
|
||||
from asyncua.crypto.permission_rules import UserRole, User
|
||||
|
||||
uri = "opc.tcp://127.0.0.1:48517/baz/server"
|
||||
uri_creds = "opc.tcp://foobar:hR%26yjjGhP%246%40nQ4e@127.0.0.1:48517/baz/server"
|
||||
|
||||
@@ -4,7 +4,7 @@ import pytest
|
||||
from asyncua import Client
|
||||
from asyncua import Server
|
||||
from asyncua import ua
|
||||
from asyncua.server.users import UserRole
|
||||
from asyncua.crypto.permission_rules import UserRole
|
||||
from asyncua.server.user_managers import CertificateUserManager
|
||||
from asyncua.crypto import security_policies
|
||||
|
||||
|
||||
Reference in New Issue
Block a user