You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2020/03/11 16:15:42 UTC

[plc4x] branch rel/0.6 updated (6471721 -> b397736)

This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a change to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


    from 6471721  Merge pull request #130 from apache/fix-OPC-wrong-paramhandling
     new 65ad21b  Fixed NPE when no params are given.
     new 0f192f5  Initial Support for Certs.
     new 1906a64  Added parsing for username / passwort + Basic Auth.
     new 1b549ba  [OPCUA] Finished work on Certificate integartion.
     new 09cec6c  Typo / Commented out unused stuff.
     new b397736  [OPCUA] Minor Fixes.

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 plc4j/drivers/opcua/pom.xml                        |  59 +++---
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |   7 +-
 .../opcua/connection/BaseOpcuaPlcConnection.java   |  36 +++-
 .../java/opcua/connection/KeyStoreLoader.java      | 200 +++++++++++++++++++++
 .../opcua/connection/OpcuaTcpPlcConnection.java    |  93 +++++++++-
 pom.xml                                            |   2 +-
 6 files changed, 360 insertions(+), 37 deletions(-)
 create mode 100644 plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java


[plc4x] 02/06: Initial Support for Certs.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 0f192f5aa89bcdbfa6bc8c67797b1a11b1aba5c1
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 3 21:55:35 2020 +0100

    Initial Support for Certs.
---
 plc4j/drivers/opcua/pom.xml                        |  26 ++++--
 .../java/opcua/connection/KeyStoreLoader.java      | 100 +++++++++++++++++++++
 .../opcua/connection/OpcuaTcpPlcConnection.java    |  31 +++++++
 pom.xml                                            |   2 +-
 4 files changed, 149 insertions(+), 10 deletions(-)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index 1c89f13..43ef5ca 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -59,12 +59,10 @@
       <artifactId>stack-client</artifactId>
       <version>0.3.6</version>
     </dependency>
-
     <dependency>
       <groupId>org.eclipse.milo</groupId>
       <artifactId>server-examples</artifactId>
       <version>0.3.6</version>
-      <scope>test</scope>
     </dependency>
 
     <dependency>
@@ -73,14 +71,24 @@
     </dependency>
 
 
-  <dependency>
-    <groupId>org.osgi</groupId>
-    <artifactId>osgi.cmpn</artifactId>
-    <version>6.0.0</version>
-    <scope>provided</scope>
-  </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>osgi.cmpn</artifactId>
+      <version>6.0.0</version>
+      <scope>provided</scope>
+    </dependency>
 
-</dependencies>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>${bouncycastle.version}</version>
+    </dependency>
+  </dependencies>
 
 
 <!--
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
new file mode 100644
index 0000000..821f58d
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
@@ -0,0 +1,100 @@
+package org.apache.plc4x.java.opcua.connection;
+
+import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.regex.Pattern;
+
+/**
+ * Copied from Eclipse Milo Project:
+ * https://github.com/eclipse/milo/blob/master/milo-examples/server-examples/src/main/java/org/eclipse/milo/examples/server/KeyStoreLoader.java
+ */
+public class KeyStoreLoader {
+
+    private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
+        "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
+
+    private static final String CLIENT_ALIAS = "client-ai";
+    private static final char[] PASSWORD = "password".toCharArray();
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    private X509Certificate clientCertificate;
+    private KeyPair clientKeyPair;
+
+    KeyStoreLoader load(Path baseDir) throws Exception {
+        KeyStore keyStore = KeyStore.getInstance("PKCS12");
+
+        Path serverKeyStore = baseDir.resolve("example-client.pfx");
+
+        logger.info("Loading KeyStore at {}", serverKeyStore);
+
+        if (!Files.exists(serverKeyStore)) {
+            keyStore.load(null, PASSWORD);
+
+            KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
+
+            SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
+                .setCommonName("Eclipse Milo Example Client")
+                .setOrganization("digitalpetri")
+                .setOrganizationalUnit("dev")
+                .setLocalityName("Folsom")
+                .setStateName("CA")
+                .setCountryCode("US")
+                .setApplicationUri("urn:eclipse:milo:examples:client")
+                .addDnsName("localhost")
+                .addIpAddress("127.0.0.1");
+
+            // Get as many hostnames and IP addresses as we can listed in the certificate.
+            for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
+                if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
+                    builder.addIpAddress(hostname);
+                } else {
+                    builder.addDnsName(hostname);
+                }
+            }
+
+            X509Certificate certificate = builder.build();
+
+            keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
+            try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
+                keyStore.store(out, PASSWORD);
+            }
+        } else {
+            try (InputStream in = Files.newInputStream(serverKeyStore)) {
+                keyStore.load(in, PASSWORD);
+            }
+        }
+
+        Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
+        if (serverPrivateKey instanceof PrivateKey) {
+            clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
+            PublicKey serverPublicKey = clientCertificate.getPublicKey();
+            clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
+        }
+
+        return this;
+    }
+
+    X509Certificate getClientCertificate() {
+        return clientCertificate;
+    }
+
+    KeyPair getClientKeyPair() {
+        return clientKeyPair;
+    }
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
index 75d77e0..1e9c603 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
@@ -52,8 +52,12 @@ import org.eclipse.milo.opcua.stack.core.types.structured.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
 import java.math.BigInteger;
 import java.net.InetAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.time.Duration;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
@@ -194,6 +198,32 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
             .findFirst()
             .orElseThrow(() -> new PlcConnectionException("No desired endpoints from"));
 
+        // Security
+        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
+        try {
+            Files.createDirectories(securityTempDir);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if (!Files.exists(securityTempDir)) {
+            throw new PlcConnectionException("unable to create security dir: " + securityTempDir);
+        }
+        LoggerFactory.getLogger(getClass())
+            .info("security temp dir: {}", securityTempDir.toAbsolutePath());
+
+        KeyStoreLoader loader;
+        try {
+            loader = new KeyStoreLoader().load(securityTempDir);
+        } catch (Exception e) {
+            throw new PlcConnectionException("Unable to load Security!", e);
+        }
+
+        SecurityPolicy securityPolicy = SecurityPolicy.None;
+
+        logger.info("Using endpoint: {} [{}/{}]",
+            endpoint.getEndpointUrl(), securityPolicy, endpoint.getSecurityMode());
+        // End Security
+
         if (this.skipDiscovery) {
             //ApplicationDescription applicationDescription = new ApplicationDescription();
             //endpoint = new EndpointDescription(address.getHostAddress(),applicationDescription , null, MessageSecurityMode.None, SecurityPolicy.None.getUri(), null , TransportProfile.TCP_UASC_UABINARY.getUri(), UByte.valueOf(0));// TODO hier machen wenn fertig
@@ -242,6 +272,7 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
         OpcUaClientConfig config = OpcUaClientConfig.builder()
             .setApplicationName(LocalizedText.english("eclipse milo opc-ua client of the apache PLC4X:PLC4J project"))
             .setApplicationUri("urn:eclipse:milo:plc4x:client")
+            .setCertificate(loader.getClientCertificate())
             .setEndpoint(endpoint)
             .setIdentityProvider(getIdentityProvider())
             .setRequestTimeout(UInteger.valueOf(requestTimeout))
diff --git a/pom.xml b/pom.xml
index c341632..df787b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,7 @@
     <antlr.version>4.7.2</antlr.version>
     <asm.version>5.0.4</asm.version>
     <assertj.version>3.11.1</assertj.version>
-    <bouncycastle.version>1.60</bouncycastle.version>
+    <bouncycastle.version>1.61</bouncycastle.version>
     <boost.version>1.71.0</boost.version>
     <boost.version.underline-short>1_71</boost.version.underline-short>
     <boost.version.underline>${boost.version.underline-short}_0</boost.version.underline>


[plc4x] 06/06: [OPCUA] Minor Fixes.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit b397736e7cbf5fc78d39ddfe5e391c0dced24f6d
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 10 22:46:05 2020 +0100

    [OPCUA] Minor Fixes.
---
 plc4j/drivers/opcua/pom.xml                            |  6 ++++++
 .../plc4x/java/opcua/connection/KeyStoreLoader.java    | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index 54e87c3..62ba2a5 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -61,6 +61,12 @@
       <version>0.3.6</version>
     </dependency>
     <dependency>
+      <groupId>org.eclipse.milo</groupId>
+      <artifactId>server-examples</artifactId>
+      <version>0.3.6</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
index abd2d48..8cd1ffe 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
@@ -1,3 +1,21 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
 package org.apache.plc4x.java.opcua.connection;
 
 import com.google.common.collect.Sets;


[plc4x] 05/06: Typo / Commented out unused stuff.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 09cec6c3d78ed61c78c3f69679c0befe1d85498f
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 10 22:33:42 2020 +0100

    Typo / Commented out unused stuff.
---
 .../plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java  | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
index 5ca6783..f642aa4 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
@@ -67,10 +67,10 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
                             password = paramValue;
                             logger.debug("Found Parameter 'password' with value {}", password);
                             break;
-                        case "certFile":
-                            certFile = paramValue;
-                            logger.debug("Found Parameter 'certFile' with value {}", certFile);
-                            break;
+//                        case "certFile":
+//                            certFile = paramValue;
+//                            logger.debug("Found Parameter 'certFile' with value {}", certFile);
+//                            break;
                         case "securityPolicy":
                             logger.debug("Got value for security policy: '{}', trying to parse", paramValue);
                             try {
@@ -84,10 +84,6 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
                             keyStoreFile = paramValue;
                             logger.debug("Found Parameter 'keyStoreFile' with value {}", keyStoreFile);
                             break;
-//                        case "keyStorePassword":
-//                            keyStorePassword = paramValue;
-//                            logger.debug("Found Parameter 'keyStorePassword' with value {}", keyStorePassword);
-//                            break;
                         default:
                             logger.debug("Unknown parameter {} with value {}", paramName, paramValue);
                     }


[plc4x] 04/06: [OPCUA] Finished work on Certificate integartion.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 1b549ba818ef6cab5048d6a5d9e98f221bdaf57d
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 10 22:32:11 2020 +0100

    [OPCUA] Finished work on Certificate integartion.
---
 plc4j/drivers/opcua/pom.xml                        | 54 ++++++-------
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |  2 +-
 .../opcua/connection/BaseOpcuaPlcConnection.java   | 31 ++++++-
 .../java/opcua/connection/KeyStoreLoader.java      | 94 ++++++++++++++++++++--
 .../opcua/connection/OpcuaTcpPlcConnection.java    | 57 +++++++++----
 5 files changed, 181 insertions(+), 57 deletions(-)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index 7150836..54e87c3 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -17,7 +17,8 @@
   specific language governing permissions and limitations
   under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
 
@@ -60,23 +61,16 @@
       <version>0.3.6</version>
     </dependency>
     <dependency>
-      <groupId>org.eclipse.milo</groupId>
-      <artifactId>server-examples</artifactId>
-      <version>0.3.6</version>
-    </dependency>
-
-    <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
     </dependency>
 
-
-  <dependency>
-    <groupId>org.osgi</groupId>
-    <artifactId>osgi.cmpn</artifactId>
-    <version>6.0.0</version>
-    <scope>provided</scope>
-  </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>osgi.cmpn</artifactId>
+      <version>6.0.0</version>
+      <scope>provided</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.bouncycastle</groupId>
@@ -89,22 +83,22 @@
       <version>${bouncycastle.version}</version>
     </dependency>
 
-</dependencies>
+  </dependencies>
 
 
-<!--
-<build>
-  <plugins>
-    <plugin>
-      <groupId>org.apache.maven.plugins</groupId>
-      <artifactId>maven-dependency-plugin</artifactId>
-      <configuration>
-        <usedDependencies combine.children="append">
-          <usedDependency>org.eclipse.milo:sdk-client</usedDependency>
-        </usedDependencies>
-      </configuration>
-    </plugin>
-  </plugins>
-</build>
--->
+  <!--
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <configuration>
+          <usedDependencies combine.children="append">
+            <usedDependency>org.eclipse.milo:sdk-client</usedDependency>
+          </usedDependencies>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  -->
 </project>
\ No newline at end of file
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 9f3de51..54e51dd 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -47,7 +47,7 @@ public class OpcuaPlcDriver implements PlcDriver {
 
     public static final Pattern INET_ADDRESS_PATTERN = Pattern.compile("tcp://(?<host>[\\w.-]+)(:(?<port>\\d*))?");
     public static final Pattern OPCUA_URI_PARAM_PATTERN = Pattern.compile("(?<param>[(\\?|\\&)([^=]+)\\=([^&]+)]+)?"); //later used for regex filtering of the params
-    public static final Pattern OPCUA_URI_PATTERN = Pattern.compile("^opcua:(" + INET_ADDRESS_PATTERN + ")?" + "(?<params>[\\w/=?&]+)?");
+    public static final Pattern OPCUA_URI_PATTERN = Pattern.compile("^opcua:(" + INET_ADDRESS_PATTERN + ")?" + "(?<params>[\\w/=?&.\\d*-_]+)?");
     private static final int requestTimeout = 10000;
     private OpcuaConnectionFactory opcuaConnectionFactory;
 
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
index ac6fba4..5ca6783 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
@@ -26,6 +26,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.base.connection.AbstractPlcConnection;
 import org.apache.plc4x.java.base.messages.*;
 import org.apache.plc4x.java.opcua.protocol.OpcuaPlcFieldHandler;
+import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,13 +39,15 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
     protected boolean skipDiscovery = false;
     protected String username = null;
     protected String password = null;
-    protected String certFile;
+    protected String certFile = null;
+    protected SecurityPolicy securityPolicy = null;
+    protected String keyStoreFile = null;
+//    protected String keyStorePassword;
 
     /**
      * @param params
      */
     BaseOpcuaPlcConnection(String params) {
-
         if (!StringUtils.isEmpty(params)) {
             for (String param : params.split("&")) {
                 String[] paramElements = param.split("=");
@@ -53,16 +56,38 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
                     String paramValue = paramElements[1];
                     switch (paramName) {
                         case "discovery":
-                            skipDiscovery = !Boolean.valueOf(paramValue);
+                            skipDiscovery = !Boolean.parseBoolean(paramValue);
+                            logger.debug("Found Parameter 'skipDiscovery' with value {}", this.skipDiscovery);
                             break;
                         case "username":
                             username = paramValue;
+                            logger.debug("Found Parameter 'username' with value {}", username);
                             break;
                         case "password":
                             password = paramValue;
+                            logger.debug("Found Parameter 'password' with value {}", password);
                             break;
                         case "certFile":
                             certFile = paramValue;
+                            logger.debug("Found Parameter 'certFile' with value {}", certFile);
+                            break;
+                        case "securityPolicy":
+                            logger.debug("Got value for security policy: '{}', trying to parse", paramValue);
+                            try {
+                                securityPolicy = SecurityPolicy.valueOf(paramValue);
+                                logger.debug("Using Security Policy {}", securityPolicy);
+                            } catch (IllegalArgumentException e) {
+                                logger.warn("Unable to parse policy {}", paramValue);
+                            }
+                            break;
+                        case "keyStoreFile":
+                            keyStoreFile = paramValue;
+                            logger.debug("Found Parameter 'keyStoreFile' with value {}", keyStoreFile);
+                            break;
+//                        case "keyStorePassword":
+//                            keyStorePassword = paramValue;
+//                            logger.debug("Found Parameter 'keyStorePassword' with value {}", keyStorePassword);
+//                            break;
                         default:
                             logger.debug("Unknown parameter {} with value {}", paramName, paramValue);
                     }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
index 821f58d..abd2d48 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/KeyStoreLoader.java
@@ -1,6 +1,6 @@
 package org.apache.plc4x.java.opcua.connection;
 
-import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
+import com.google.common.collect.Sets;
 import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
 import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
 import org.slf4j.Logger;
@@ -8,6 +8,11 @@ import org.slf4j.LoggerFactory;
 
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.security.Key;
@@ -16,6 +21,11 @@ import java.security.KeyStore;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 /**
@@ -27,18 +37,47 @@ public class KeyStoreLoader {
     private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
         "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
 
-    private static final String CLIENT_ALIAS = "client-ai";
-    private static final char[] PASSWORD = "password".toCharArray();
+    private static final String CLIENT_ALIAS = "client-cert";
+    private static final char[] PASSWORD = "plc4x".toCharArray();
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     private X509Certificate clientCertificate;
     private KeyPair clientKeyPair;
 
+//    KeyStoreLoader load(Path baseDir) throws Exception {
+//        return load(baseDir, true);
+//    }
+//
+//    KeyStoreLoader load(Path baseDir, boolean resolve) throws Exception {
+//        return load(baseDir, null, resolve);
+//    }
+//
+//    KeyStoreLoader load(Path file, String password) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
+//        KeyStore keyStore = KeyStore.getInstance("PKCS12");
+//
+//        Path serverKeyStore = file;
+//
+//        logger.info("Loading KeyStore at {}", serverKeyStore);
+//
+//        try (InputStream in = Files.newInputStream(serverKeyStore)) {
+//            keyStore.load(in, password.toCharArray());
+//        }
+//
+//        Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, password.toCharArray());
+//        if (serverPrivateKey instanceof PrivateKey) {
+//            clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
+//            PublicKey serverPublicKey = clientCertificate.getPublicKey();
+//            clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
+//        }
+//
+//        return this;
+//    }
+
     KeyStoreLoader load(Path baseDir) throws Exception {
         KeyStore keyStore = KeyStore.getInstance("PKCS12");
 
-        Path serverKeyStore = baseDir.resolve("example-client.pfx");
+        Path serverKeyStore = baseDir;
 
         logger.info("Loading KeyStore at {}", serverKeyStore);
 
@@ -54,12 +93,13 @@ public class KeyStoreLoader {
                 .setLocalityName("Folsom")
                 .setStateName("CA")
                 .setCountryCode("US")
-                .setApplicationUri("urn:eclipse:milo:examples:client")
+//                .setApplicationUri("urn:eclipse:milo:examples:client")
+                .setApplicationUri("urn:plc4x-client")
                 .addDnsName("localhost")
                 .addIpAddress("127.0.0.1");
 
             // Get as many hostnames and IP addresses as we can listed in the certificate.
-            for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
+            for (String hostname : getHostnames("0.0.0.0", true)) {
                 if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
                     builder.addIpAddress(hostname);
                 } else {
@@ -97,4 +137,46 @@ public class KeyStoreLoader {
         return clientKeyPair;
     }
 
+    public Set<String> getHostnames(String address, boolean includeLoopback) {
+        HashSet hostnames = Sets.newHashSet();
+
+        try {
+            InetAddress inetAddress = InetAddress.getByName(address);
+            if (inetAddress.isAnyLocalAddress()) {
+                try {
+                    Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
+                    Iterator var5 = Collections.list(nis).iterator();
+
+                    while(var5.hasNext()) {
+                        NetworkInterface ni = (NetworkInterface)var5.next();
+                        Collections.list(ni.getInetAddresses()).forEach((ia) -> {
+                            if (ia instanceof Inet4Address) {
+                                boolean loopback = ia.isLoopbackAddress();
+                                if (!loopback || includeLoopback) {
+                                    hostnames.add(ia.getHostName());
+                                    hostnames.add(ia.getHostAddress());
+                                    hostnames.add(ia.getCanonicalHostName());
+                                }
+                            }
+
+                        });
+                    }
+                } catch (SocketException var7) {
+                    logger.warn("Failed to NetworkInterfaces for bind address: {}", address, var7);
+                }
+            } else {
+                boolean loopback = inetAddress.isLoopbackAddress();
+                if (!loopback || includeLoopback) {
+                    hostnames.add(inetAddress.getHostName());
+                    hostnames.add(inetAddress.getHostAddress());
+                    hostnames.add(inetAddress.getCanonicalHostName());
+                }
+            }
+        } catch (UnknownHostException var8) {
+            logger.warn("Failed to get InetAddress for bind address: {}", address, var8);
+        }
+
+        return hostnames;
+    }
+
 }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
index 76db3c0..d1bbf62 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
@@ -198,11 +198,14 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
             }
 
         }
+
         endpoint = endpoints.stream()
             .filter(e -> e.getSecurityPolicyUri().equals(getSecurityPolicy().getUri()))
             .filter(endpointFilter())
             .findFirst()
-            .orElseThrow(() -> new PlcConnectionException("No desired endpoints from"));
+            .orElseThrow(() -> new PlcConnectionException("No desired endpoints found (with right policy)"));
+
+        logger.debug("Using Endpoint {}", endpoint);
 
         // Security
         Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
@@ -219,15 +222,20 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
 
         KeyStoreLoader loader;
         try {
-            loader = new KeyStoreLoader().load(securityTempDir);
+            if (this.keyStoreFile == null) {
+                logger.debug("No KeyStoreFile given, generating...");
+                loader = new KeyStoreLoader().load(securityTempDir.resolve("client-cert.pfx"));
+            } else {
+                logger.debug("KeyStoreFile {} given, loading or generating there...", this.keyStoreFile);
+                loader = new KeyStoreLoader().load(Paths.get(keyStoreFile));
+            }
         } catch (Exception e) {
             throw new PlcConnectionException("Unable to load Security!", e);
         }
 
-        SecurityPolicy securityPolicy = SecurityPolicy.None;
-
+        // Make Security Configurable
         logger.info("Using endpoint: {} [{}/{}]",
-            endpoint.getEndpointUrl(), securityPolicy, endpoint.getSecurityMode());
+            endpoint.getEndpointUrl(), getSecurityPolicy(), endpoint.getSecurityMode());
         // End Security
 
         if (this.skipDiscovery) {
@@ -277,8 +285,9 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
 
         OpcUaClientConfig config = OpcUaClientConfig.builder()
             .setApplicationName(LocalizedText.english("eclipse milo opc-ua client of the apache PLC4X:PLC4J project"))
-            .setApplicationUri("urn:eclipse:milo:plc4x:client")
+            .setApplicationUri("urn:plc4x-client")
             .setCertificate(loader.getClientCertificate())
+            .setKeyPair(loader.getClientKeyPair())
             .setEndpoint(endpoint)
             .setIdentityProvider(getIdentityProvider())
             .setRequestTimeout(UInteger.valueOf(requestTimeout))
@@ -298,6 +307,22 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
         }
     }
 
+//    private X509Certificate getClientCertificate(KeyStoreLoader loader) {
+//        if (this.certFile != null) {
+//            Path path = null;
+//            try {
+//                path = Paths.get(this.certFile);
+//                final X509Certificate x509Certificate = CertificateUtil.decodeCertificate(Files.readAllBytes(path));
+//                logger.info("Using Certificate given by certFile as Client Certificate");
+//                return x509Certificate;
+//            } catch (UaException | IOException e) {
+//                logger.warn("Unable to load given Certificate File {}", path != null ? path.toAbsolutePath().toString() : this.certFile, e);
+//            }
+//        }
+//        logger.info("Using self signed generated Client Certificate");
+//        return loader.getClientCertificate();
+//    }
+
     @Override
     public boolean isConnected() {
         return client != null && isConnected;
@@ -545,7 +570,13 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
     }
 
     private SecurityPolicy getSecurityPolicy() {
-        return SecurityPolicy.None;
+        if (this.securityPolicy == null) {
+            logger.debug("No Security Policy given, using default NONE");
+            return SecurityPolicy.None;
+        } else {
+            logger.debug("Using given SecurityPolicy {}", this.securityPolicy);
+            return this.securityPolicy;
+        }
     }
 
     private IdentityProvider getIdentityProvider() {
@@ -553,18 +584,10 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
             if (this.password == null) {
                 throw new PlcRuntimeException("Username given, but no password. Please Add password by providing &password=");
             }
-            logger.info("Username {} is given and password {}, using Basic Auth now", this.username, this.password);
+            logger.debug("Username {} is given and password {}, using Basic Auth now", this.username, this.password);
             return new UsernameProvider(this.username, this.password);
-//        } else if (this.certFile != null) {
-//            logger.info("Using Certificate Path {}", this.certFile);
-//            try {
-//                final X509Certificate x509Certificate = CertificateUtil.decodeCertificate(Files.readAllBytes(new File(this.certFile).toPath()));
-//                return new X509IdentityProvider(x509Certificate);
-//            } catch (UaException | IOException e) {
-//                throw new PlcRuntimeException("Unable to load or decode Cert with path " + this.certFile);
-//            }
         } else {
-            logger.info("No username / password is given, using anonymous access");
+            logger.debug("No username / password is given, using anonymous access");
             return new AnonymousProvider();
         }
     }


[plc4x] 01/06: Fixed NPE when no params are given.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 65ad21b77281b8310a78c5bdbb11793c881e4bb5
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 3 20:56:39 2020 +0100

    Fixed NPE when no params are given.
---
 .../org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
index 1c9ccb7..75d77e0 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
@@ -516,7 +516,7 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
     }
 
     private static String getSubPathOfParams(String params){
-        if(params.contains("=")){
+        if(params != null && params.contains("=")){
             if(params.contains("?")){
                 return params.split("\\?")[0];
             }else{
@@ -529,7 +529,7 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
     }
 
     private static String getOptionString(String params){
-        if(params.contains("=")){
+        if(params != null && params.contains("=")){
             if(params.contains("?")){
                 return params.split("\\?")[1];
             }else{


[plc4x] 03/06: Added parsing for username / passwort + Basic Auth.

Posted by jf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jfeinauer pushed a commit to branch rel/0.6
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 1906a6450009542c9ac3683c948f697fa2b26c73
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Tue Mar 10 13:33:37 2020 +0100

    Added parsing for username / passwort + Basic Auth.
---
 plc4j/drivers/opcua/pom.xml                        | 15 +++++------
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |  5 ++++
 .../opcua/connection/BaseOpcuaPlcConnection.java   | 11 ++++++++
 .../opcua/connection/OpcuaTcpPlcConnection.java    | 29 +++++++++++++++++++---
 4 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index 43ef5ca..7150836 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -71,12 +71,12 @@
     </dependency>
 
 
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>osgi.cmpn</artifactId>
-      <version>6.0.0</version>
-      <scope>provided</scope>
-    </dependency>
+  <dependency>
+    <groupId>org.osgi</groupId>
+    <artifactId>osgi.cmpn</artifactId>
+    <version>6.0.0</version>
+    <scope>provided</scope>
+  </dependency>
 
     <dependency>
       <groupId>org.bouncycastle</groupId>
@@ -88,7 +88,8 @@
       <artifactId>bcpkix-jdk15on</artifactId>
       <version>${bouncycastle.version}</version>
     </dependency>
-  </dependencies>
+
+</dependencies>
 
 
 <!--
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 185de95..9f3de51 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -25,6 +25,8 @@ import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.opcua.connection.OpcuaConnectionFactory;
 import org.apache.plc4x.java.spi.PlcDriver;
 import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -41,6 +43,7 @@ import java.util.regex.Pattern;
 @Component(service = PlcDriver.class, immediate = true)
 public class OpcuaPlcDriver implements PlcDriver {
 
+    private static final Logger logger = LoggerFactory.getLogger(OpcuaPlcDriver.class);
 
     public static final Pattern INET_ADDRESS_PATTERN = Pattern.compile("tcp://(?<host>[\\w.-]+)(:(?<port>\\d*))?");
     public static final Pattern OPCUA_URI_PARAM_PATTERN = Pattern.compile("(?<param>[(\\?|\\&)([^=]+)\\=([^&]+)]+)?"); //later used for regex filtering of the params
@@ -80,6 +83,8 @@ public class OpcuaPlcDriver implements PlcDriver {
         Integer port = StringUtils.isNotBlank(portString) ? Integer.parseInt(portString) : null;
         String params = matcher.group("params") != null ? matcher.group("params").substring(1) : null;
 
+        logger.info("Path parameters given {}", params);
+
         try {
             return opcuaConnectionFactory.opcuaTcpPlcConnectionOf(InetAddress.getByName(host), port, params, requestTimeout);
         } catch (UnknownHostException e) {
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
index a7a2d43..ac6fba4 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/BaseOpcuaPlcConnection.java
@@ -36,6 +36,9 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
 
     private static final Logger logger = LoggerFactory.getLogger(BaseOpcuaPlcConnection.class);
     protected boolean skipDiscovery = false;
+    protected String username = null;
+    protected String password = null;
+    protected String certFile;
 
     /**
      * @param params
@@ -52,6 +55,14 @@ public abstract class BaseOpcuaPlcConnection extends AbstractPlcConnection imple
                         case "discovery":
                             skipDiscovery = !Boolean.valueOf(paramValue);
                             break;
+                        case "username":
+                            username = paramValue;
+                            break;
+                        case "password":
+                            password = paramValue;
+                            break;
+                        case "certFile":
+                            certFile = paramValue;
                         default:
                             logger.debug("Unknown parameter {} with value {}", paramName, paramValue);
                     }
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
index 1e9c603..76db3c0 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java
@@ -22,6 +22,7 @@ package org.apache.plc4x.java.opcua.connection;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
 import org.apache.plc4x.java.api.model.PlcField;
@@ -36,6 +37,8 @@ import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
 import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
 import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
 import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
+import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
+import org.eclipse.milo.opcua.sdk.client.api.identity.X509IdentityProvider;
 import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
 import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
 import org.eclipse.milo.opcua.stack.client.DiscoveryClient;
@@ -49,15 +52,18 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
 import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
 import org.eclipse.milo.opcua.stack.core.types.structured.*;
+import org.eclipse.milo.opcua.stack.core.util.CertificateUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.cert.X509Certificate;
 import java.time.Duration;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
@@ -171,7 +177,7 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
         EndpointDescription endpoint = null;
 
         try {
-            endpoints = DiscoveryClient.getEndpoints(getEndpointUrl(address, port, getSubPathOfParams(params))).get();
+            endpoints = DiscoveryClient.getEndpoints(getEndpointUrl(address, port, getSubPathOfParams(params) == null ? "" : getSubPathOfParams(params))).get();
             //TODO Exception should be handeled better when the Discovery-API of Milo is stable
         } catch (Exception ex) {
             logger.info("Failed to discover Endpoint with enabled discovery. If the endpoint does not allow a correct discovery disable this option with the nDiscovery=true option. Failed Endpoint: {}", getEndpointUrl(address, port, params));
@@ -288,7 +294,7 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
             throw new PlcConnectionException("The given input values are a not valid OPC UA connection configuration [CONFIG]: " + message);
         } catch (InterruptedException | ExecutionException e) {
             isConnected = false;
-            throw new PlcConnectionException("Error while creation of the connection because of : " + e.getMessage());
+            throw new PlcConnectionException("Error while creation of the connection because of : " + e.getMessage(), e);
         }
     }
 
@@ -543,7 +549,24 @@ public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection {
     }
 
     private IdentityProvider getIdentityProvider() {
-        return new AnonymousProvider();
+        if (this.username != null) {
+            if (this.password == null) {
+                throw new PlcRuntimeException("Username given, but no password. Please Add password by providing &password=");
+            }
+            logger.info("Username {} is given and password {}, using Basic Auth now", this.username, this.password);
+            return new UsernameProvider(this.username, this.password);
+//        } else if (this.certFile != null) {
+//            logger.info("Using Certificate Path {}", this.certFile);
+//            try {
+//                final X509Certificate x509Certificate = CertificateUtil.decodeCertificate(Files.readAllBytes(new File(this.certFile).toPath()));
+//                return new X509IdentityProvider(x509Certificate);
+//            } catch (UaException | IOException e) {
+//                throw new PlcRuntimeException("Unable to load or decode Cert with path " + this.certFile);
+//            }
+        } else {
+            logger.info("No username / password is given, using anonymous access");
+            return new AnonymousProvider();
+        }
     }
 
     private static String getSubPathOfParams(String params){