feat(install): historian TCP env + firewall rule
Replace OTOPCUA_HISTORIAN_PIPE/OTOPCUA_ALLOWED_SID with TCP transport env (OTOPCUA_HISTORIAN_TCP_PORT, OTOPCUA_HISTORIAN_BIND, OTOPCUA_HISTORIAN_TLS_ENABLED, OTOPCUA_HISTORIAN_TLS_CERT/PASSWORD) in Install-Services.ps1; add idempotent Windows Firewall inbound rule for the TCP port. Add new params for all TCP/TLS options with cert provisioning guidance. Update Refresh-Services.ps1 Step 4b comment (PipeServer → TcpFrameServer) and add a Step 5 note clarifying that TCP/TLS env is set at install time, not on refresh.
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Registers the v2 Windows service on a node: OtOpcUaHost (fused binary, .NET 10)
|
||||
and optionally OtOpcUaWonderwareHistorian (Wonderware historian sidecar, net48 x86).
|
||||
and optionally OtOpcUaWonderwareHistorian (Wonderware historian sidecar, net48 x86
|
||||
— communicates over TCP, optionally TLS, instead of a Windows named pipe).
|
||||
|
||||
.DESCRIPTION
|
||||
v2 consolidates the legacy OtOpcUa + OtOpcUaAdmin services into a single role-gated
|
||||
OtOpcUaHost binary. The -Roles parameter sets the OTOPCUA_ROLES service env so
|
||||
Program.cs decides what to mount (admin / driver / both). The Wonderware historian
|
||||
sidecar logic is unchanged from v1; install it with -InstallWonderwareHistorian.
|
||||
sidecar is installed with -InstallWonderwareHistorian; it listens on a TCP port
|
||||
(default 32569, configurable via -HistorianTcpPort) protected by the shared secret.
|
||||
Optional TLS (-HistorianUseTls) is recommended for production cross-host deployments.
|
||||
|
||||
Galaxy access flows through the mxaccessgw sibling repo (separate service); see
|
||||
docs/v2/Galaxy.ParityRig.md for the gateway setup.
|
||||
@@ -39,6 +42,30 @@
|
||||
Per-process secret passed to the historian sidecar via env var. Generated freshly
|
||||
per install when not supplied.
|
||||
|
||||
.PARAMETER HistorianTcpPort
|
||||
TCP port the sidecar listens on (OTOPCUA_HISTORIAN_TCP_PORT). Default 32569. A
|
||||
matching Windows Firewall inbound rule is created automatically.
|
||||
|
||||
.PARAMETER HistorianBind
|
||||
IP address the sidecar binds to (OTOPCUA_HISTORIAN_BIND). Default 0.0.0.0
|
||||
(all interfaces). Set to 127.0.0.1 for loopback-only on same-host deployments.
|
||||
|
||||
.PARAMETER HistorianUseTls
|
||||
When set, enables TLS on the sidecar TCP listener. Supply -HistorianTlsCert with
|
||||
a certificate path or store thumbprint; recommended for cross-host production use.
|
||||
|
||||
.PARAMETER HistorianTlsCert
|
||||
Certificate source for TLS. Either:
|
||||
- Absolute path to a .pfx file (e.g. C:\ProgramData\OtOpcUa\pki\historian.pfx),
|
||||
exported with MachineKeySet so the service account can read the private key; or
|
||||
- A LocalMachine\My store thumbprint (40-hex-char string, no spaces).
|
||||
Do NOT embed a cert path or thumbprint in automation scripts for unattended installs;
|
||||
pass it at call time or from a secrets vault.
|
||||
|
||||
.PARAMETER HistorianTlsCertPassword
|
||||
Password for the .pfx file (if using a pfx path). Leave empty when using a store
|
||||
thumbprint. Never store passwords in scripts or source control.
|
||||
|
||||
.EXAMPLE
|
||||
.\Install-Services.ps1 -InstallRoot 'C:\Program Files\OtOpcUa' `
|
||||
-ServiceAccount 'OTOPCUA\svc-otopcua' -Roles 'admin,driver'
|
||||
@@ -57,12 +84,16 @@ param(
|
||||
[int]$HttpPort = 9000,
|
||||
|
||||
# Wonderware historian sidecar. Optional; gates the OtOpcUaWonderwareHistorian
|
||||
# service. Secret + pipe defaults match the server's Historian:Wonderware appsettings.
|
||||
# service. Secret defaults match the server's Historian:Wonderware appsettings.
|
||||
[switch]$InstallWonderwareHistorian,
|
||||
[string]$HistorianSharedSecret,
|
||||
[string]$HistorianPipeName = 'OtOpcUaWonderwareHistorian',
|
||||
[string]$HistorianServer = 'localhost',
|
||||
[int]$HistorianPort = 32568,
|
||||
[int]$HistorianPort = 32568, # SDK port (OTOPCUA_HISTORIAN_PORT) — Wonderware InSQL connection
|
||||
[int]$HistorianTcpPort = 32569, # TCP listen port for the IPC channel (OTOPCUA_HISTORIAN_TCP_PORT)
|
||||
[string]$HistorianBind = '0.0.0.0',
|
||||
[switch]$HistorianUseTls,
|
||||
[string]$HistorianTlsCert,
|
||||
[string]$HistorianTlsCertPassword,
|
||||
[string[]]$AvevaServiceDependencies = @('NmxSvc', 'aaBootstrap', 'aaGR')
|
||||
)
|
||||
|
||||
@@ -87,29 +118,43 @@ if ($InstallWonderwareHistorian -and -not (Test-Path "$InstallRoot\WonderwareHis
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Resolve the SID — the IPC ACL needs the SID, not the down-level name.
|
||||
$sid = if ($ServiceAccount.StartsWith('S-1-')) {
|
||||
$ServiceAccount
|
||||
} else {
|
||||
(New-Object System.Security.Principal.NTAccount $ServiceAccount).Translate([System.Security.Principal.SecurityIdentifier]).Value
|
||||
}
|
||||
|
||||
# --- OtOpcUaWonderwareHistorian sidecar (optional, unchanged from v1) -------
|
||||
# --- OtOpcUaWonderwareHistorian sidecar (optional, TCP transport) -----------
|
||||
$historianDepend = $null
|
||||
if ($InstallWonderwareHistorian) {
|
||||
# Build the TCP/TLS env block.
|
||||
# The Windows named-pipe transport and OTOPCUA_ALLOWED_SID have been retired;
|
||||
# the sidecar now listens on a TCP port protected by the shared secret.
|
||||
# TLS is optional but strongly recommended for cross-host production deployments.
|
||||
#
|
||||
# Cert provisioning for prod (when -HistorianUseTls):
|
||||
# Option A — pfx file: export with -KeyExportPolicy Exportable -KeyStorageFlags MachineKeySet;
|
||||
# place at e.g. C:\ProgramData\OtOpcUa\pki\historian.pfx;
|
||||
# ACL the file so the service account has Read access.
|
||||
# Option B — store thumbprint: import into LocalMachine\My; grant the service account
|
||||
# Read on the private key via certlm.msc → Manage Private Keys.
|
||||
# Either value is passed via -HistorianTlsCert at install time; NEVER hard-code it here.
|
||||
$historianEnv = @(
|
||||
"OTOPCUA_HISTORIAN_PIPE=$HistorianPipeName"
|
||||
"OTOPCUA_ALLOWED_SID=$sid"
|
||||
"OTOPCUA_HISTORIAN_SECRET=$HistorianSharedSecret"
|
||||
"OTOPCUA_HISTORIAN_ENABLED=true"
|
||||
"OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=true"
|
||||
"OTOPCUA_HISTORIAN_SERVER=$HistorianServer"
|
||||
"OTOPCUA_HISTORIAN_PORT=$HistorianPort"
|
||||
"OTOPCUA_HISTORIAN_TCP_PORT=$HistorianTcpPort"
|
||||
"OTOPCUA_HISTORIAN_BIND=$HistorianBind"
|
||||
)
|
||||
if ($HistorianUseTls) {
|
||||
$historianEnv += "OTOPCUA_HISTORIAN_TLS_ENABLED=true"
|
||||
$historianEnv += "OTOPCUA_HISTORIAN_TLS_CERT=$HistorianTlsCert"
|
||||
if ($HistorianTlsCertPassword) {
|
||||
$historianEnv += "OTOPCUA_HISTORIAN_TLS_CERT_PASSWORD=$HistorianTlsCertPassword"
|
||||
}
|
||||
} else {
|
||||
$historianEnv += "OTOPCUA_HISTORIAN_TLS_ENABLED=false"
|
||||
}
|
||||
|
||||
Write-Host "Installing OtOpcUaWonderwareHistorian..."
|
||||
& sc.exe create OtOpcUaWonderwareHistorian binPath= "`"$InstallRoot\WonderwareHistorian\OtOpcUa.Driver.Historian.Wonderware.exe`"" `
|
||||
DisplayName= 'OtOpcUa Wonderware Historian Sidecar (out-of-process aahClient)' `
|
||||
DisplayName= 'OtOpcUa Wonderware Historian Sidecar (out-of-process aahClient, TCP)' `
|
||||
start= auto `
|
||||
depend= ($AvevaServiceDependencies -join '/') `
|
||||
obj= $ServiceAccount | Out-Null
|
||||
@@ -120,6 +165,11 @@ if ($InstallWonderwareHistorian) {
|
||||
|
||||
& sc.exe failure OtOpcUaWonderwareHistorian reset= 86400 actions= restart/5000/restart/30000/restart/60000 | Out-Null
|
||||
|
||||
# Idempotent Windows Firewall rule for the sidecar TCP port.
|
||||
$fwName = "OtOpcUa Wonderware Historian (TCP $HistorianTcpPort)"
|
||||
Get-NetFirewallRule -DisplayName $fwName -ErrorAction SilentlyContinue | Remove-NetFirewallRule -ErrorAction SilentlyContinue
|
||||
New-NetFirewallRule -DisplayName $fwName -Direction Inbound -Action Allow -Protocol TCP -LocalPort $HistorianTcpPort | Out-Null
|
||||
|
||||
$historianDepend = 'OtOpcUaWonderwareHistorian'
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ Run {
|
||||
# `dotnet publish` above) silently drops the net48 binding-redirect
|
||||
# .exe.config and the transitive runtime DLLs MessagePack needs — most
|
||||
# notably System.Memory.dll. The sidecar then JIT-load-faults inside
|
||||
# PipeServer.RunOneConnectionAsync ("FileNotFoundException: System.Memory,
|
||||
# TcpFrameServer.RunOneConnectionAsync ("FileNotFoundException: System.Memory,
|
||||
# Version=4.0.1.2") and NSSM crash-loops it (exit 2 every ~2 min, ~120 s of
|
||||
# retry backoff before it gives up). Fail loudly here so an incomplete deploy
|
||||
# is caught at publish time instead of by a production crash-loop.
|
||||
@@ -158,6 +158,11 @@ if (-not $WhatIf) {
|
||||
# ------------------------------------------------------------------------
|
||||
# Step 5: Service env block — ensure OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED
|
||||
# is set on the Wonderware historian service (PR C.2 toggle).
|
||||
# Note: the TCP transport env (OTOPCUA_HISTORIAN_TCP_PORT, OTOPCUA_HISTORIAN_BIND,
|
||||
# OTOPCUA_HISTORIAN_TLS_ENABLED, OTOPCUA_HISTORIAN_TLS_CERT) and the Windows
|
||||
# Firewall rule are set once at install time by Install-Services.ps1 and are
|
||||
# not touched here on refresh; re-run Install-Services.ps1 to change them.
|
||||
# OTOPCUA_ALLOWED_SID is no longer used (TCP transport retired the named pipe).
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
if (Test-NssmService 'OtOpcUaWonderwareHistorian') {
|
||||
|
||||
Reference in New Issue
Block a user