c3c1f6e870
docker/seed-sites.sh and docker-env2/seed-sites.sh hard-coded the windev gateway API key. They now read MXGW_APIKEY from the environment, or from a private file (default ~/.config/scadabridge/windev-mxgw-apikey, override MXGW_APIKEY_FILE). With no key the MxGateway connection step is skipped and the rest of the seed runs. READMEs note where to put it. The key remains in git history (2 commits), so it should be rotated on the windev gateway. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
149 lines
6.6 KiB
Bash
Executable File
149 lines
6.6 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Seed the three test sites with Akka and gRPC addresses.
|
|
# Run after deploy.sh once the central cluster is healthy.
|
|
#
|
|
# Prerequisites:
|
|
# - Infrastructure services running (infra/docker-compose up -d)
|
|
# - Application containers running (docker/deploy.sh)
|
|
# - Central cluster healthy (curl http://localhost:9000/health/ready)
|
|
#
|
|
# Usage:
|
|
# docker/seed-sites.sh
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
CLI="dotnet run --project $PROJECT_ROOT/src/ZB.MOM.WW.ScadaBridge.CLI --"
|
|
AUTH="--username multi-role --password password"
|
|
URL="--url http://localhost:9000"
|
|
|
|
echo "=== Seeding ScadaBridge Sites ==="
|
|
|
|
echo ""
|
|
echo "Creating Site-A (Test Plant A)..."
|
|
$CLI $URL $AUTH site create \
|
|
--name "Test Plant A" \
|
|
--identifier "site-a" \
|
|
--description "Test site A - two-node cluster" \
|
|
--node-a-address "akka.tcp://scadabridge@scadabridge-site-a-a:8082" \
|
|
--node-b-address "akka.tcp://scadabridge@scadabridge-site-a-b:8082" \
|
|
--grpc-node-a-address "http://scadabridge-site-a-a:8083" \
|
|
--grpc-node-b-address "http://scadabridge-site-a-b:8083" \
|
|
|| echo " (Site-A may already exist)"
|
|
|
|
echo ""
|
|
echo "Creating Site-B (Test Plant B)..."
|
|
$CLI $URL $AUTH site create \
|
|
--name "Test Plant B" \
|
|
--identifier "site-b" \
|
|
--description "Test site B - two-node cluster" \
|
|
--node-a-address "akka.tcp://scadabridge@scadabridge-site-b-a:8082" \
|
|
--node-b-address "akka.tcp://scadabridge@scadabridge-site-b-b:8082" \
|
|
--grpc-node-a-address "http://scadabridge-site-b-a:8083" \
|
|
--grpc-node-b-address "http://scadabridge-site-b-b:8083" \
|
|
|| echo " (Site-B may already exist)"
|
|
|
|
echo ""
|
|
echo "Creating Site-C (Test Plant C)..."
|
|
$CLI $URL $AUTH site create \
|
|
--name "Test Plant C" \
|
|
--identifier "site-c" \
|
|
--description "Test site C - two-node cluster" \
|
|
--node-a-address "akka.tcp://scadabridge@scadabridge-site-c-a:8082" \
|
|
--node-b-address "akka.tcp://scadabridge@scadabridge-site-c-b:8082" \
|
|
--grpc-node-a-address "http://scadabridge-site-c-a:8083" \
|
|
--grpc-node-b-address "http://scadabridge-site-c-b:8083" \
|
|
|| echo " (Site-C may already exist)"
|
|
|
|
echo ""
|
|
echo "Creating Engineering Alerts notification list..."
|
|
$CLI $URL $AUTH notification create \
|
|
--name "Engineering Alerts" \
|
|
--emails "engineer@company.com" \
|
|
|| echo " (Engineering Alerts may already exist)"
|
|
|
|
echo ""
|
|
echo "Creating MxGateway data connections (shared gateway) on each site..."
|
|
# A shared MxGateway data connection pointing at the MxAccess Gateway. Data
|
|
# connections are site-scoped (the DCL runs on site clusters only — central
|
|
# nodes do not host data connections), so one is created per site. The same
|
|
# gateway endpoint + API key is reused across all sites.
|
|
#
|
|
# Config is the typed MxGatewayEndpointConfig JSON (camelCase keys), matching
|
|
# MxGatewayEndpointConfigSerializer.
|
|
MXGW_ENDPOINT="http://10.100.0.48:5120"
|
|
# The windev gateway API key is NOT kept in the repo. Supply it via the
|
|
# MXGW_APIKEY env var, or a private file (default
|
|
# ~/.config/scadabridge/windev-mxgw-apikey, override with MXGW_APIKEY_FILE).
|
|
# Without a key the MxGateway data connection step is skipped.
|
|
MXGW_APIKEY_FILE="${MXGW_APIKEY_FILE:-$HOME/.config/scadabridge/windev-mxgw-apikey}"
|
|
if [ -z "${MXGW_APIKEY:-}" ] && [ -r "$MXGW_APIKEY_FILE" ]; then
|
|
MXGW_APIKEY=$(tr -d '\r\n' < "$MXGW_APIKEY_FILE")
|
|
fi
|
|
MXGW_APIKEY="${MXGW_APIKEY:-}"
|
|
MXGW_CONFIG="{\"endpoint\":\"${MXGW_ENDPOINT}\",\"apiKey\":\"${MXGW_APIKEY}\",\"clientName\":\"\",\"writeUserId\":0,\"useTls\":false,\"caFile\":\"\",\"serverName\":\"\",\"readTimeoutMs\":5000}"
|
|
|
|
if [ -z "$MXGW_APIKEY" ]; then
|
|
echo " (no MXGW_APIKEY / $MXGW_APIKEY_FILE — skipping MxGateway connections)"
|
|
else
|
|
for ident in site-a site-b site-c; do
|
|
SITE_ID=$($CLI $URL $AUTH --format json site list \
|
|
| python3 -c "import sys,json; print(next((s['id'] for s in json.load(sys.stdin) if s.get('siteIdentifier')=='$ident'), ''))" 2>/dev/null)
|
|
if [ -z "$SITE_ID" ]; then
|
|
echo " ($ident not found — skipping MxGateway connection)"
|
|
continue
|
|
fi
|
|
# Per-site connection name (e.g. site-a -> "ScadaBridge Site A").
|
|
SITE_LETTER=$(printf '%s' "${ident#site-}" | tr '[:lower:]' '[:upper:]')
|
|
CONN_NAME="ScadaBridge Site ${SITE_LETTER}"
|
|
echo " $ident (id=$SITE_ID): creating '$CONN_NAME'..."
|
|
$CLI $URL $AUTH data-connection create \
|
|
--site-id "$SITE_ID" \
|
|
--name "$CONN_NAME" \
|
|
--protocol "MxGateway" \
|
|
--primary-config "$MXGW_CONFIG" \
|
|
|| echo " ('$CONN_NAME' may already exist on $ident)"
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo "Seeding LDAP group mappings (Designer + Deployer)..."
|
|
# SecurityConfiguration.HasData declares 4 mappings but the InitialSchema
|
|
# migration only inserts the Admin row, so a fresh ScadaBridgeConfig starts
|
|
# with multi-role getting Admin only -- no Design and no Deployment access.
|
|
# Insert the missing three idempotently.
|
|
docker exec -i scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \
|
|
-S localhost -U sa -P 'ScadaBridge_Dev1#' -C \
|
|
-d ScadaBridgeConfig -Q "
|
|
SET IDENTITY_INSERT LdapGroupMappings ON;
|
|
IF NOT EXISTS (SELECT 1 FROM LdapGroupMappings WHERE Id = 2)
|
|
INSERT INTO LdapGroupMappings (Id, LdapGroupName, Role) VALUES (2, 'SCADA-Designers', 'Designer');
|
|
IF NOT EXISTS (SELECT 1 FROM LdapGroupMappings WHERE Id = 3)
|
|
INSERT INTO LdapGroupMappings (Id, LdapGroupName, Role) VALUES (3, 'SCADA-Deploy-All', 'Deployer');
|
|
IF NOT EXISTS (SELECT 1 FROM LdapGroupMappings WHERE Id = 4)
|
|
INSERT INTO LdapGroupMappings (Id, LdapGroupName, Role) VALUES (4, 'SCADA-Deploy-SiteA', 'Deployer');
|
|
-- Role strings MUST match the canonical vocabulary in
|
|
-- src/ZB.MOM.WW.ScadaBridge.Security/Roles.cs ('Designer' / 'Deployer').
|
|
-- These rows previously carried the pre-rename 'Design' / 'Deployment', which
|
|
-- authorized nothing: every Designer/Deployer-gated management command failed
|
|
-- UNAUTHORIZED on a freshly reseeded rig.
|
|
SET IDENTITY_INSERT LdapGroupMappings OFF;
|
|
"
|
|
|
|
echo ""
|
|
echo "Deploying artifacts to all sites (pushes data connections so the sites"
|
|
echo "establish them — the MxGateway DataConnectionActor connects eagerly)..."
|
|
$CLI $URL $AUTH deploy artifacts \
|
|
|| echo " (artifact deploy reported an issue — check 'deploy status')"
|
|
|
|
echo ""
|
|
echo "=== Site seeding complete ==="
|
|
echo ""
|
|
echo "Verify with: $CLI $URL $AUTH site list"
|
|
echo "Verify connections: $CLI $URL $AUTH data-connection list"
|
|
echo "Verify MxGateway is live (per site container):"
|
|
echo " docker logs scadabridge-site-a-a 2>&1 | grep -i mxgateway"
|
|
echo "Multi-role test user has Admin + Design + Deployment."
|
|
echo "Sign out and back in to refresh session role claims."
|