|
| 1 | + |
| 2 | +# Configuration to connect to secure External OPC UA server |
| 3 | + |
| 4 | +This guide explains how to securely connect your application to an external OPC UA server using TLS/SSL encryption for both data ingestion and alert publishing, replacing the default built-in OPC UA server. |
| 5 | + |
| 6 | + |
| 7 | +## Step 1: Generate TLS Certificates |
| 8 | + |
| 9 | +Follow the below steps to generate the required certificates: |
| 10 | + |
| 11 | +```bash |
| 12 | +# Navigate to the application directory |
| 13 | +cd edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-time-series |
| 14 | + |
| 15 | +# Load environment variables |
| 16 | +source ./.env |
| 17 | + |
| 18 | +# Create and clean the certificates directory |
| 19 | +mkdir -p certs |
| 20 | +sudo rm -rf ./certs/* |
| 21 | +cd certs |
| 22 | + |
| 23 | +# Set your external OPC UA server hostname/IP |
| 24 | +# Replace <YOUR_OPCUA_SERVER_IP> with your actual OPC UA server IP or hostname |
| 25 | +EXTERNAL_OPCUA_SERVER_HOST=<YOUR_OPCUA_SERVER_IP> |
| 26 | +``` |
| 27 | + |
| 28 | +### Generate CA Certificate |
| 29 | +```bash |
| 30 | +# Generate CA private key (3072-bit for better security) |
| 31 | +openssl genrsa -out ca.key 3072 |
| 32 | + |
| 33 | +# Generate CA certificate |
| 34 | +openssl req -new -x509 -days 365 -key ca.key -out ca_cert.pem \ |
| 35 | + -subj "/C=US/ST=State/L=City/O=Organization/OU=OrgUnit/CN=OPCUA-CA" |
| 36 | + |
| 37 | +# Create a copy with the expected filename |
| 38 | +cp ca_cert.pem ca_certificate.pem |
| 39 | +``` |
| 40 | + |
| 41 | +### Generate Server Certificate |
| 42 | +```bash |
| 43 | +# Generate server private key |
| 44 | +openssl genrsa -out opcua_server.key 3072 |
| 45 | + |
| 46 | +# Generate server certificate signing request |
| 47 | +openssl req -new -key opcua_server.key -out server.csr \ |
| 48 | + -subj "/C=US/ST=State/L=City/O=Organization/OU=OrgUnit/CN=$EXTERNAL_OPCUA_SERVER_HOST" |
| 49 | + |
| 50 | +# Create extensions file for Subject Alternative Names |
| 51 | +cat > server.ext << EOF |
| 52 | +[v3_req] |
| 53 | +authorityKeyIdentifier=keyid,issuer |
| 54 | +basicConstraints=CA:FALSE |
| 55 | +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment |
| 56 | +subjectAltName = @alt_names |
| 57 | +
|
| 58 | +[alt_names] |
| 59 | +DNS.1 = $EXTERNAL_OPCUA_SERVER_HOST |
| 60 | +DNS.2 = localhost |
| 61 | +IP.1 = 127.0.0.1 |
| 62 | +EOF |
| 63 | + |
| 64 | +# Generate server certificate |
| 65 | +openssl x509 -req -in server.csr -CA ca_certificate.pem -CAkey ca.key \ |
| 66 | + -CAcreateserial -out opcua_server_certificate.pem -days 365 \ |
| 67 | + -extensions v3_req -extfile server.ext |
| 68 | +``` |
| 69 | + |
| 70 | +### Generate Client Certificate |
| 71 | +```bash |
| 72 | +# Generate client private key |
| 73 | +openssl genrsa -out opcua_client.key 3072 |
| 74 | + |
| 75 | +# Generate client certificate signing request |
| 76 | +openssl req -new -key opcua_client.key -out client.csr \ |
| 77 | + -subj "/C=US/ST=State/L=City/O=Organization/OU=OrgUnit/CN=telegraf-opcua-client" |
| 78 | + |
| 79 | +# Create client extensions file |
| 80 | +cat > client.ext << EOF |
| 81 | +[v3_req] |
| 82 | +authorityKeyIdentifier=keyid,issuer |
| 83 | +basicConstraints=CA:FALSE |
| 84 | +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment |
| 85 | +extendedKeyUsage = clientAuth |
| 86 | +EOF |
| 87 | + |
| 88 | +# Generate client certificate signed by CA |
| 89 | +openssl x509 -req -in client.csr -CA ca_certificate.pem -CAkey ca.key \ |
| 90 | + -CAcreateserial -out opcua_client_certificate.pem -days 365 \ |
| 91 | + -extensions v3_req -extfile client.ext |
| 92 | + |
| 93 | +# Copy client certificates with expected filenames |
| 94 | +cp opcua_client.key client_key.pem |
| 95 | +cp opcua_client_certificate.pem client_certificate.pem |
| 96 | + |
| 97 | +# Set proper ownership and permissions |
| 98 | +sudo chown $TIMESERIES_UID:$TIMESERIES_UID ca_certificate.pem client_key.pem client_certificate.pem |
| 99 | +sudo chmod 664 ca_certificate.pem client_certificate.pem |
| 100 | +sudo chmod 600 client_key.pem |
| 101 | + |
| 102 | +# Clean up temporary files |
| 103 | +rm server.csr client.csr server.ext client.ext |
| 104 | + |
| 105 | +cd .. |
| 106 | +export OPCUA_CLIENT_CERT=client_certificate.pem |
| 107 | +export OPCUA_CLIENT_KEY=client_key.pem |
| 108 | +``` |
| 109 | + |
| 110 | +## Step 2: Configure Docker Services |
| 111 | + |
| 112 | +Make the below changes to the `edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-time-series/docker-compose.yml` file. |
| 113 | + |
| 114 | +### Update docker-compose.yml |
| 115 | + |
| 116 | +Add the CA certificate volume mount to the following services in your `docker-compose.yml`: |
| 117 | + |
| 118 | +```yaml |
| 119 | +ia-telegraf: |
| 120 | + volumes: |
| 121 | + # ... existing volumes ... |
| 122 | + - ./certs/ca_certificate.pem:/run/secrets/ca_certificate.pem:ro |
| 123 | + - ./certs/$OPCUA_CLIENT_KEY:/run/secrets/$OPCUA_CLIENT_KEY:ro |
| 124 | + - ./certs/$OPCUA_CLIENT_CERT:/run/secrets/$OPCUA_CLIENT_CERT:ro |
| 125 | + |
| 126 | +ia-time-series-analytics-microservice: |
| 127 | + volumes: |
| 128 | + # ... existing volumes ... |
| 129 | + - ./certs/ca_certificate.pem:/run/secrets/ca_certificate.pem:ro |
| 130 | + - ./certs/$OPCUA_CLIENT_KEY:/run/secrets/$OPCUA_CLIENT_KEY:ro |
| 131 | + - ./certs/$OPCUA_CLIENT_CERT:/run/secrets/$OPCUA_CLIENT_CERT:ro |
| 132 | + |
| 133 | +``` |
| 134 | + |
| 135 | +### Update Network Configuration |
| 136 | + |
| 137 | +Replace `ia-opcua-server` with your external OPC UA server's hostname/IP in the proxy settings: |
| 138 | + |
| 139 | +```yaml |
| 140 | +ia-telegraf: |
| 141 | + environment: |
| 142 | + no_proxy: "ia-influxdb,ia-mqtt-broker,<YOUR_OPCUA_SERVER_IP>,ia-mqtt-broker,ia-time-series-analytics-microservice,${no_proxy}" |
| 143 | + NO_PROXY: "ia-influxdb,ia-mqtt-broker,<YOUR_OPCUA_SERVER_IP>,ia-mqtt-broker,ia-time-series-analytics-microservice,${no_proxy}" |
| 144 | + |
| 145 | +ia-time-series-analytics-microservice: |
| 146 | + environment: |
| 147 | + no_proxy: "ia-influxdb,ia-mqtt-broker,<YOUR_OPCUA_SERVER_IP>,localhost,${no_proxy}" |
| 148 | + NO_PROXY: "ia-influxdb,ia-mqtt-broker,<YOUR_OPCUA_SERVER_IP>,ia-mqtt-broker,localhost,${no_proxy}" |
| 149 | +``` |
| 150 | +
|
| 151 | +### Configure OPC UA server |
| 152 | +
|
| 153 | +Replace the `<YOUR_OPCUA_SERVER_URL>` with your external OPC UA server URL in `ia-telegraf`. |
| 154 | +Set `OPCUA_SECURE_MODE` to `true` to use TLS/SSL in `ia-time-series-analytics-microservice`. |
| 155 | +Set `OPCUA_SERVER_USERNAME` and `OPCUA_SERVER_PASSWORD` with your OPC UA server credentials |
| 156 | + |
| 157 | +```yaml |
| 158 | +ia-telegraf: |
| 159 | + environment: |
| 160 | + OPCUA_SERVER: <YOUR_OPCUA_SERVER_URL> |
| 161 | + # ... other environment variables ... |
| 162 | +
|
| 163 | +ia-time-series-analytics-microservice: |
| 164 | + environment: |
| 165 | + OPCUA_SECURE_MODE: true |
| 166 | + OPCUA_CLIENT_CERT: $OPCUA_CLIENT_CERT |
| 167 | + OPCUA_CLIENT_KEY: $OPCUA_CLIENT_KEY |
| 168 | + OPCUA_SERVER_USERNAME: <YOUR_OPCUA_USERNAME> |
| 169 | + OPCUA_SERVER_PASSWORD: <YOUR_OPCUA_PASSWORD> |
| 170 | + # ... other environment variables ... |
| 171 | +``` |
| 172 | + |
| 173 | +## Step 3: Configure Application Settings |
| 174 | + |
| 175 | +### 3.1 Update Telegraf Configuration |
| 176 | + |
| 177 | +Edit your Telegraf configuration file: |
| 178 | +`edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-time-series/apps/wind-turbine-anomaly-detection/telegraf-config/Telegraf.conf` |
| 179 | + |
| 180 | +```toml |
| 181 | +[[inputs.opcua]] |
| 182 | + ## Metric name |
| 183 | + name = "opcua" |
| 184 | + name_override = "wind-turbine-data" |
| 185 | +
|
| 186 | + ## OPC UA Endpoint URL |
| 187 | + endpoint = "$OPCUA_SERVER" |
| 188 | + log_level = "debug" |
| 189 | + ## Security policy, one of "None", "Basic128Rsa15", "Basic256", |
| 190 | + ## "Basic256Sha256", or "auto" |
| 191 | + security_policy = "Basic256Sha256" |
| 192 | +
|
| 193 | + ## Security mode, one of "None", "Sign", "SignAndEncrypt", or "auto" |
| 194 | + security_mode = "SignAndEncrypt" |
| 195 | +
|
| 196 | + ## Path to client cert.pem. Required when security mode or policy isn't "None". |
| 197 | + ## If cert path is not supplied, self-signed cert and key will be generated. |
| 198 | + certificate = "/run/secrets/$OPCUA_CLIENT_CERT" |
| 199 | +
|
| 200 | + ## Path to client private key.pem. Required when security mode or policy isn't "None". |
| 201 | + ## If key path is not supplied, self-signed cert and key will be generated. |
| 202 | + private_key = "/run/secrets/$OPCUA_CLIENT_KEY" |
| 203 | +
|
| 204 | + ## Authentication Method, one of "Certificate", "UserName", or "Anonymous". To |
| 205 | + ## authenticate using a specific ID, select 'Certificate' or 'UserName' |
| 206 | + auth_method = "UserName" |
| 207 | +
|
| 208 | + ## Username and password required for auth_method = "UserName" |
| 209 | + username = "<USERNAME>" |
| 210 | + password = "<PASSWORD>" |
| 211 | +
|
| 212 | +
|
| 213 | + [[inputs.opcua.nodes]] |
| 214 | + name = "grid_active_power" |
| 215 | + namespace = "<NAMESPACE>" |
| 216 | + identifier_type = "i" |
| 217 | + identifier = "<IDENTIFIER>" |
| 218 | + default_tags = { source="opcua_merge" } |
| 219 | + # default_tags = { tag1 = "value1", tag2 = "value2" } |
| 220 | + [[inputs.opcua.nodes]] |
| 221 | + name = "wind_speed" |
| 222 | + namespace = "<NAMESPACE>" |
| 223 | + identifier_type = "i" |
| 224 | + identifier = "<IDENTIFIER>" |
| 225 | + default_tags = { source="opcua_merge" } |
| 226 | +
|
| 227 | +``` |
| 228 | + |
| 229 | +**Replace:** |
| 230 | +- `YOUR_OPCUA_SERVER_IP` with your OPC UA server's IP or hostname |
| 231 | +- `NAMESPACE` with your OPC UA server namespace |
| 232 | +- `IDENTIFIER` with your OPC UA server node identifier |
| 233 | +- `USERNAME` and `PASSWORD` with your OPC UA server credentials |
| 234 | + |
| 235 | +> **Note:** |
| 236 | +> Make sure your OPC UA server exposes nodes for both `wind_speed` and `grid_active_power`. These nodes must be available for data collection. |
| 237 | + |
| 238 | +### 3.2 Update Wind Turbine Anomaly Detection Sample app configuration |
| 239 | + |
| 240 | +Edit your sample app config file if you want to send alerts to OPC UA server: |
| 241 | +`edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-time-series/apps/wind-turbine-anomaly-detection/time-series-analytics-config/config.json` |
| 242 | + |
| 243 | +``` |
| 244 | +{ |
| 245 | + "alerts": { |
| 246 | + "opcua": { |
| 247 | + "opcua_server": "YOUR_OPCUA_SERVER", |
| 248 | + "namespace": <NAMESPACE>, |
| 249 | + "node_id": <NODE_ID> |
| 250 | + } |
| 251 | + } |
| 252 | +} |
| 253 | +``` |
| 254 | +
|
| 255 | +**Replace:** |
| 256 | +- `YOUR_OPCUA_SERVER` with your OPC UA server's endpoint URL |
| 257 | +- `NAMESPACE` with your OPC UA server namespace |
| 258 | +- `NODE_ID` with your OPC UA server node identifier |
| 259 | +
|
| 260 | +## Step 4: Configure Your External OPC UA Server |
| 261 | +
|
| 262 | +For OPC UA servers, ensure the following configuration: |
| 263 | +
|
| 264 | +1. **Security Policy**: Set to `Basic256Sha256` or higher |
| 265 | +2. **Security Mode**: Set to `SignAndEncrypt` |
| 266 | +3. **Authentication**: Configure username/password authentication |
| 267 | +4. **CA Certificate**: Install the generated CA certificate as trusted |
| 268 | +5. **Server Certificate**: Use the generated server certificate (`opcua_server_certificate.pem`) |
| 269 | +6. **Client Certificate**: Trust the generated client certificate (`client_certificate.pem`) |
| 270 | +7. **Endpoint URL**: Configure as `opc.tcp://<YOUR_OPCUA_SERVER_IP>:4840/` |
| 271 | +
|
| 272 | +## Step 5: Deploy and Verify |
| 273 | +
|
| 274 | +Deploy the sample application following the steps as mentioned [here](./get-started.md#deploy-with-docker-compose) |
0 commit comments