docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
218
scripts/unifi/create-firewall-rules.sh
Executable file
218
scripts/unifi/create-firewall-rules.sh
Executable file
@@ -0,0 +1,218 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Create firewall rules via UniFi Network API
|
||||
# This script creates ACL rules for network segmentation and security
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Load UNIFI_* from repo .env, unifi-api/.env, or ~/.env
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
set -a && source "$PROJECT_ROOT/.env" 2>/dev/null && set +a
|
||||
fi
|
||||
if [ -f "$PROJECT_ROOT/unifi-api/.env" ]; then
|
||||
set -a && source "$PROJECT_ROOT/unifi-api/.env" 2>/dev/null && set +a
|
||||
fi
|
||||
if [ -f ~/.env ]; then
|
||||
source <(grep "^UNIFI_" ~/.env 2>/dev/null | sed 's/^/export /') 2>/dev/null || true
|
||||
fi
|
||||
|
||||
UDM_URL="${UNIFI_UDM_URL:-https://192.168.0.1}"
|
||||
API_KEY="${UNIFI_API_KEY}"
|
||||
SITE_ID="88f7af54-98f8-306a-a1c7-c9349722b1f6"
|
||||
|
||||
if [ -z "$API_KEY" ]; then
|
||||
echo "❌ UNIFI_API_KEY not set in environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Creating Firewall Rules via API"
|
||||
echo "=================================="
|
||||
echo ""
|
||||
echo "UDM URL: $UDM_URL"
|
||||
echo "Site ID: $SITE_ID"
|
||||
echo ""
|
||||
|
||||
# Get network IDs
|
||||
echo "Fetching network IDs..."
|
||||
NETWORKS_JSON=$(curl -k -s -X GET "$UDM_URL/proxy/network/integration/v1/sites/$SITE_ID/networks" \
|
||||
-H "X-API-KEY: $API_KEY" \
|
||||
-H 'Accept: application/json')
|
||||
|
||||
# Extract network IDs using Python
|
||||
NETWORK_IDS=$(python3 << 'PYEOF'
|
||||
import sys, json
|
||||
data = json.load(sys.stdin)
|
||||
networks = data.get('data', [])
|
||||
vlan_map = {}
|
||||
for net in networks:
|
||||
vlan_id = net.get('vlanId')
|
||||
if vlan_id and vlan_id > 1:
|
||||
vlan_map[vlan_id] = net.get('id')
|
||||
|
||||
# Key VLANs we need
|
||||
key_vlans = {
|
||||
11: 'MGMT-LAN',
|
||||
110: 'BESU-VAL',
|
||||
111: 'BESU-SEN',
|
||||
112: 'BESU-RPC',
|
||||
120: 'BLOCKSCOUT',
|
||||
121: 'CACTI',
|
||||
130: 'CCIP-OPS',
|
||||
132: 'CCIP-COMMIT',
|
||||
133: 'CCIP-EXEC',
|
||||
134: 'CCIP-RMN',
|
||||
140: 'FABRIC',
|
||||
141: 'FIREFLY',
|
||||
150: 'INDY',
|
||||
160: 'SANKOFA-SVC',
|
||||
200: 'PHX-SOV-SMOM',
|
||||
201: 'PHX-SOV-ICCC',
|
||||
202: 'PHX-SOV-DBIS',
|
||||
203: 'PHX-SOV-AR'
|
||||
}
|
||||
|
||||
# Export as shell variables
|
||||
for vlan, name in key_vlans.items():
|
||||
if vlan in vlan_map:
|
||||
print(f"NETWORK_ID_VLAN{vlan}={vlan_map[vlan]}")
|
||||
print(f"NETWORK_NAME_VLAN{vlan}={name}")
|
||||
PYEOF
|
||||
)
|
||||
|
||||
# Source the network IDs
|
||||
eval "$NETWORK_IDS"
|
||||
|
||||
echo "✅ Network IDs loaded"
|
||||
echo ""
|
||||
|
||||
# Function to create ACL rule
|
||||
create_acl_rule() {
|
||||
local name=$1
|
||||
local description=$2
|
||||
local action=$3
|
||||
local index=$4
|
||||
local source_networks=$5
|
||||
local dest_networks=$6
|
||||
local protocol=$7
|
||||
|
||||
echo "Creating rule: $name"
|
||||
|
||||
# Build source filter
|
||||
if [ -n "$source_networks" ]; then
|
||||
SOURCE_FILTER=$(python3 << PYEOF
|
||||
import json
|
||||
networks = "$source_networks".split()
|
||||
network_ids = []
|
||||
for net in networks:
|
||||
var_name = f"NETWORK_ID_VLAN{net}"
|
||||
import os
|
||||
net_id = os.environ.get(var_name)
|
||||
if net_id:
|
||||
network_ids.append(net_id)
|
||||
print(json.dumps({
|
||||
"type": "NETWORK",
|
||||
"networkIds": network_ids
|
||||
}))
|
||||
PYEOF
|
||||
)
|
||||
else
|
||||
SOURCE_FILTER="null"
|
||||
fi
|
||||
|
||||
# Build destination filter
|
||||
if [ -n "$dest_networks" ]; then
|
||||
DEST_FILTER=$(python3 << PYEOF
|
||||
import json
|
||||
networks = "$dest_networks".split()
|
||||
network_ids = []
|
||||
for net in networks:
|
||||
var_name = f"NETWORK_ID_VLAN{net}"
|
||||
import os
|
||||
net_id = os.environ.get(var_name)
|
||||
if net_id:
|
||||
network_ids.append(net_id)
|
||||
print(json.dumps({
|
||||
"type": "NETWORK",
|
||||
"networkIds": network_ids
|
||||
}))
|
||||
PYEOF
|
||||
)
|
||||
else
|
||||
DEST_FILTER="null"
|
||||
fi
|
||||
|
||||
# Build protocol filter
|
||||
if [ -n "$protocol" ]; then
|
||||
PROTOCOL_FILTER="[\"$protocol\"]"
|
||||
else
|
||||
PROTOCOL_FILTER="null"
|
||||
fi
|
||||
|
||||
# Create rule JSON
|
||||
RULE_JSON=$(python3 << PYEOF
|
||||
import json, sys
|
||||
source = json.loads('$SOURCE_FILTER') if '$SOURCE_FILTER' != 'null' else None
|
||||
dest = json.loads('$DEST_FILTER') if '$DEST_FILTER' != 'null' else None
|
||||
protocol = json.loads('$PROTOCOL_FILTER') if '$PROTOCOL_FILTER' != 'null' else None
|
||||
|
||||
rule = {
|
||||
"type": "IPV4",
|
||||
"enabled": True,
|
||||
"name": "$name",
|
||||
"description": "$description",
|
||||
"action": "$action",
|
||||
"index": $index,
|
||||
"sourceFilter": source,
|
||||
"destinationFilter": dest,
|
||||
"protocolFilter": protocol,
|
||||
"enforcingDeviceFilter": None
|
||||
}
|
||||
print(json.dumps(rule))
|
||||
PYEOF
|
||||
)
|
||||
|
||||
# Create the rule
|
||||
RESPONSE=$(curl -k -s -w "\n%{http_code}" -X POST "$UDM_URL/proxy/network/integration/v1/sites/$SITE_ID/acl-rules" \
|
||||
-H "X-API-KEY: $API_KEY" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: application/json' \
|
||||
-d "$RULE_JSON")
|
||||
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
RESPONSE_BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
|
||||
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
|
||||
echo " ✅ Rule created successfully"
|
||||
return 0
|
||||
else
|
||||
echo " ❌ Failed to create rule (HTTP $HTTP_CODE)"
|
||||
echo " Response: $RESPONSE_BODY"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Create firewall rules
|
||||
echo "Creating firewall rules..."
|
||||
echo ""
|
||||
|
||||
# Rule 1: Block sovereign tenant inter-VLAN traffic (VLANs 200-203)
|
||||
create_acl_rule \
|
||||
"Block Sovereign Tenant East-West Traffic" \
|
||||
"Deny traffic between sovereign tenant VLANs (200-203) for isolation" \
|
||||
"BLOCK" \
|
||||
100 \
|
||||
"200 201 202 203" \
|
||||
"200 201 202 203" \
|
||||
""
|
||||
|
||||
echo ""
|
||||
echo "✅ Firewall rule creation complete!"
|
||||
echo ""
|
||||
echo "Note: Additional rules (management access, monitoring) can be added"
|
||||
echo " after verifying the API request format works correctly."
|
||||
Reference in New Issue
Block a user