Skip to content

Commit 5b10917

Browse files
orouletOlivier
andauthored
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>
1 parent 120d2e8 commit 5b10917

19 files changed

+163
-48
lines changed

asyncua/client/client.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
import logging
33
import socket
44
import dataclasses
5-
from cryptography import x509
6-
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
75
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Type, Union, cast, Callable, Coroutine
86
from urllib.parse import urlparse, unquote, ParseResult
97
from pathlib import Path
108

9+
from cryptography import x509
10+
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
11+
1112
import asyncua
1213
from asyncua import ua
1314
from .ua_client import UaClient
@@ -65,9 +66,9 @@ def __init__(self, url: str, timeout: float = 4, watchdog_intervall: float = 1.0
6566
if have_password:
6667
self._password = unquote(password)
6768

68-
self.name = "Pure Python Async. Client"
69+
self.name = "Pure Python Async Client"
6970
self.description = self.name
70-
self.application_uri = "urn:freeopcua:client"
71+
self.application_uri = "urn:example.org:FreeOpcUa:opcua-asyncio"
7172
self.product_uri = "urn:freeopcua.github.io:client"
7273
self.security_policy = security_policies.SecurityPolicyNone()
7374
self.secure_channel_id = None
@@ -497,10 +498,16 @@ async def create_session(self) -> ua.CreateSessionResult:
497498
desc.ApplicationName = ua.LocalizedText(self.name)
498499
desc.ApplicationType = ua.ApplicationType.Client
499500
params = ua.CreateSessionParameters()
501+
params.ServerUri = f"urn:{self.server_url.hostname}{self.server_url.path.replace('/', ':')}"
500502
# at least 32 random bytes for server to prove possession of private key (specs part 4, 5.6.2.2)
501503
nonce = create_nonce(32)
502504
params.ClientNonce = nonce
503-
params.ClientCertificate = self.security_policy.host_certificate
505+
if self.security_policy.host_certificate:
506+
params.ClientCertificate = self.security_policy.host_certificate
507+
elif self.user_certificate:
508+
params.ClientCertificate = uacrypto.der_from_x509(self.user_certificate)
509+
else:
510+
params.ClientCertificate = None
504511
params.ClientDescription = desc
505512
params.EndpointUrl = self.server_url.geturl()
506513
params.SessionName = f"{self.description} Session{self._session_counter}"
@@ -639,7 +646,7 @@ async def activate_session(
639646
"""
640647
Activate session using either username and password or private_key
641648
"""
642-
user_certificate = certificate or self.user_certificate
649+
user_certificate = certificate
643650
params = ua.ActivateSessionParameters()
644651
challenge = b""
645652
if self.security_policy.peer_certificate is not None:
@@ -652,7 +659,7 @@ async def activate_session(
652659
params.ClientSignature.Algorithm = security_policies.SecurityPolicyBasic256.AsymmetricSignatureURI
653660
params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature(challenge)
654661
params.LocaleIds = self._locale
655-
if not username and not user_certificate:
662+
if not username and not (user_certificate and self.user_private_key):
656663
self._add_anonymous_auth(params)
657664
elif user_certificate:
658665
self._add_certificate_auth(params, user_certificate, challenge)

asyncua/client/ua_file_transfer.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ async def create_file(self, file_name: str, request_file_open: bool) -> Tuple[No
219219
and shall be ignored by the caller.
220220
"""
221221
_logger.debug("Request to create file %s in %s", file_name, self._directory_node)
222-
print(f"Request to create file {file_name} in {self._directory_node}")
223222
create_file_node = await self._directory_node.get_child("CreateFile")
224223
arg1_file_name = Variant(file_name, VariantType.String)
225224
arg2_request_file_open = Variant(request_file_open, VariantType.Boolean)

asyncua/common/structures104.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def clean_name(name):
132132
return name
133133
newname = re.sub(r"\W+", "_", name)
134134
newname = re.sub(r"^[0-9]+", r"_\g<0>", newname)
135-
_logger.warning("renamed %s to %s due to Python syntax", name, newname)
135+
_logger.info("renamed %s to %s due to Python syntax", name, newname)
136136
return newname
137137

138138

@@ -363,7 +363,8 @@ def __add_recursion(sdef, desc):
363363
if parent_sdef:
364364
for sfield in reversed(parent_sdef.Fields):
365365
sdef.Fields.insert(0, sfield)
366-
dtypes.append(DataTypeSorter(desc.NodeId, name, desc, sdef))
366+
if isinstance(sdef, ua.StructureDefinition):
367+
dtypes.append(DataTypeSorter(desc.NodeId, name, desc, sdef))
367368
return _recursive_parse(
368369
server,
369370
server.get_node(desc.NodeId),

asyncua/crypto/permission_rules.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from enum import Enum
2+
from dataclasses import dataclass
3+
from typing import Optional
4+
15
from asyncua import ua
2-
from asyncua.server.users import UserRole
36

47
ADMIN_TYPES = [
58
ua.ObjectIds.RegisterServerRequest_Encoding_DefaultBinary,
@@ -37,6 +40,22 @@
3740
]
3841

3942

43+
class UserRole(Enum):
44+
"""
45+
User Roles
46+
"""
47+
48+
Admin = 0
49+
Anonymous = 1
50+
User = 3
51+
52+
53+
@dataclass
54+
class User:
55+
role: UserRole = UserRole.Anonymous
56+
name: Optional[str] = None
57+
58+
4059
class PermissionRuleset:
4160
"""
4261
Base class for permission ruleset

asyncua/crypto/truststore.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,8 @@ def is_trusted(self, certificate: x509.Certificate) -> bool:
139139
store_ctx.verify_certificate()
140140
_logger.debug("Use trusted certificate : '%s'", _certificate.get_subject().CN)
141141
return True
142-
except crypto.X509StoreContextError as exp:
143-
print(exp)
144-
_logger.warning('Not trusted certificate used: "%s"', _certificate.get_subject().CN)
142+
except crypto.X509StoreContextError:
143+
_logger.exception('Not trusted certificate used: "%s"', _certificate.get_subject().CN)
145144
return False
146145

147146
async def _load_trust_location(self, location: Path):

asyncua/server/address_space.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
] # FIXME Check, if there are missing attribute types.
3434

3535
from asyncua import ua
36+
from asyncua.crypto.permission_rules import User, UserRole
3637

37-
from .users import User, UserRole
3838

3939
_logger = logging.getLogger(__name__)
4040

asyncua/server/internal_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from .address_space import NodeData, AddressSpace, AttributeService, ViewService, NodeManagementService, MethodService
2121
from .subscription_service import SubscriptionService
2222
from .standard_address_space import standard_address_space
23-
from .users import User, UserRole
23+
from asyncua.crypto.permission_rules import User, UserRole
2424
from .internal_session import InternalSession
2525
from .event_generator import EventGenerator
2626
from ..crypto.validator import CertificateValidatorMethod

asyncua/server/internal_session.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ..common.utils import create_nonce, ServiceError
1111
from ..crypto.uacrypto import x509
1212
from .address_space import AddressSpace
13-
from .users import User, UserRole
13+
from asyncua.crypto.permission_rules import User, UserRole
1414
from .subscription_service import SubscriptionService
1515

1616
if TYPE_CHECKING:

asyncua/server/user_managers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Union
44

55
from asyncua.crypto import uacrypto
6-
from asyncua.server.users import User, UserRole
6+
from asyncua.crypto.permission_rules import User, UserRole
77

88

99
class UserManager:

asyncua/server/users.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)