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/03 20:55:51 UTC

[plc4x] branch feature/PLC4X-185-cert-support-opc-ua created (now 2423f36)

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

jfeinauer pushed a change to branch feature/PLC4X-185-cert-support-opc-ua
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


      at 2423f36  Initial Support for Certs.

This branch includes the following new commits:

     new 56f0ce1  Fixed NPE when no params are given.
     new 2423f36  Initial Support for Certs.

The 2 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.



[plc4x] 01/02: 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 feature/PLC4X-185-cert-support-opc-ua
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 56f0ce16a63d405d075bcd1f1503c5bbd9abe1fa
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] 02/02: 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 feature/PLC4X-185-cert-support-opc-ua
in repository https://gitbox.apache.org/repos/asf/plc4x.git

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

    Initial Support for Certs.
---
 .../java/opcua/connection/KeyStoreLoader.java      | 100 +++++++++++++++++++++
 .../opcua/connection/OpcuaTcpPlcConnection.java    |  31 +++++++
 .../apache/plc4x/java/opcua/ManualPLC4XOpcua.java  |   3 +-
 3 files changed, 133 insertions(+), 1 deletion(-)

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/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
index 89146db..57410cd 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualPLC4XOpcua.java
@@ -73,7 +73,8 @@ public class ManualPLC4XOpcua {
         PlcField field = fieldH.createField("ns=2;i=10855");
         try {
             opcuaConnection = (OpcuaTcpPlcConnection)
-                new PlcDriverManager().getConnection("opcua:tcp://localhost:4843?discovery=true");
+                // new PlcDriverManager().getConnection("opcua:tcp://localhost:4843?discovery=true");
+                new PlcDriverManager().getConnection("opcua:tcp://opcuaserver.com:48010");//?discovery=true");
 
         } catch (PlcConnectionException e) {
             e.printStackTrace();