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:
193
scripts/unifi/allow-default-network-to-vlan11-node.js
Executable file
193
scripts/unifi/allow-default-network-to-vlan11-node.js
Executable file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create firewall rule to allow 192.168.0.0/24 (UDM Pro default network) to access VLAN 11
|
||||
* This fixes the "Destination Host Unreachable" issue when pinging 192.168.11.10 from 192.168.0.23
|
||||
*/
|
||||
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { homedir } from 'os';
|
||||
|
||||
// Load environment variables
|
||||
const envPath = join(homedir(), '.env');
|
||||
function loadEnvFile(filePath) {
|
||||
try {
|
||||
const envFile = readFileSync(filePath, 'utf8');
|
||||
const envVars = envFile.split('\n').filter(
|
||||
(line) => line.includes('=') && !line.trim().startsWith('#')
|
||||
);
|
||||
for (const line of envVars) {
|
||||
const [key, ...values] = line.split('=');
|
||||
if (key && values.length > 0 && /^[A-Z_][A-Z0-9_]*$/.test(key.trim())) {
|
||||
let value = values.join('=').trim();
|
||||
if (
|
||||
(value.startsWith('"') && value.endsWith('"')) ||
|
||||
(value.startsWith("'") && value.endsWith("'"))
|
||||
) {
|
||||
value = value.slice(1, -1);
|
||||
}
|
||||
process.env[key.trim()] = value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
loadEnvFile(envPath);
|
||||
|
||||
const baseUrl = process.env.UNIFI_UDM_URL || 'https://192.168.0.1';
|
||||
const apiKey = process.env.UNIFI_API_KEY;
|
||||
const siteId = '88f7af54-98f8-306a-a1c7-c9349722b1f6';
|
||||
|
||||
if (!apiKey) {
|
||||
console.error('❌ UNIFI_API_KEY not set in environment');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('Creating Firewall Rule: Allow 192.168.0.0/24 → VLAN 11');
|
||||
console.log('================================================================');
|
||||
console.log('');
|
||||
|
||||
// Fetch networks
|
||||
async function fetchNetworks() {
|
||||
const response = await fetch(`${baseUrl}/proxy/network/integration/v1/sites/${siteId}/networks`, {
|
||||
headers: {
|
||||
'X-API-KEY': apiKey,
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch networks: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const networks = data.data || [];
|
||||
|
||||
const vlanMap = {};
|
||||
for (const net of networks) {
|
||||
const vlanId = net.vlanId;
|
||||
if (vlanId && vlanId > 1) {
|
||||
vlanMap[vlanId] = {
|
||||
id: net.id,
|
||||
name: net.name,
|
||||
subnet: net.ipSubnet,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return vlanMap;
|
||||
}
|
||||
|
||||
// Create ACL rule using IP address filter
|
||||
async function createACLRule(ruleConfig) {
|
||||
const { name, description, action, index, sourceIP, destNetworkId, protocolFilter } = ruleConfig;
|
||||
|
||||
const rule = {
|
||||
type: 'IPV4',
|
||||
enabled: true,
|
||||
name,
|
||||
description,
|
||||
action,
|
||||
index,
|
||||
sourceFilter: sourceIP
|
||||
? { type: 'IP_ADDRESSES_OR_SUBNETS', ipAddressesOrSubnets: [sourceIP] }
|
||||
: null,
|
||||
destinationFilter: destNetworkId
|
||||
? { type: 'NETWORKS', networkIds: [destNetworkId] }
|
||||
: null,
|
||||
protocolFilter: protocolFilter || null,
|
||||
enforcingDeviceFilter: null,
|
||||
};
|
||||
|
||||
const response = await fetch(`${baseUrl}/proxy/network/integration/v1/sites/${siteId}/acl-rules`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-API-KEY': apiKey,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(rule),
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
let responseData;
|
||||
try {
|
||||
responseData = JSON.parse(responseText);
|
||||
} catch {
|
||||
responseData = responseText;
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
return { success: true, data: responseData };
|
||||
} else {
|
||||
return { success: false, error: responseData, status: response.status };
|
||||
}
|
||||
}
|
||||
|
||||
// Main function
|
||||
async function main() {
|
||||
try {
|
||||
console.log('Fetching network IDs...');
|
||||
const vlanMap = await fetchNetworks();
|
||||
|
||||
const vlan11Network = vlanMap[11];
|
||||
if (!vlan11Network) {
|
||||
console.error('❌ VLAN 11 (MGMT-LAN) not found');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`✅ Found VLAN 11 (MGMT-LAN): ${vlan11Network.name}`);
|
||||
console.log(` Network ID: ${vlan11Network.id}`);
|
||||
console.log(` Subnet: ${vlan11Network.subnet}`);
|
||||
console.log('');
|
||||
|
||||
// Create rule to allow 192.168.0.0/24 → VLAN 11
|
||||
console.log('Creating firewall rule...');
|
||||
console.log('');
|
||||
|
||||
const ruleConfig = {
|
||||
name: 'Allow Default Network to Management VLAN',
|
||||
description: 'Allow 192.168.0.0/24 (UDM Pro default network) to access VLAN 11 (MGMT-LAN)',
|
||||
action: 'ALLOW',
|
||||
index: 5, // Higher priority than service VLAN rules
|
||||
sourceIP: '192.168.0.0/24',
|
||||
destNetworkId: vlan11Network.id,
|
||||
protocolFilter: null, // Allow all protocols (ICMP, TCP, UDP)
|
||||
};
|
||||
|
||||
console.log(`Rule: ${ruleConfig.name}`);
|
||||
console.log(`Source: ${ruleConfig.sourceIP}`);
|
||||
console.log(`Destination: VLAN 11 (${vlan11Network.name})`);
|
||||
console.log(`Protocol: All`);
|
||||
console.log('');
|
||||
|
||||
const result = await createACLRule(ruleConfig);
|
||||
|
||||
if (result.success) {
|
||||
console.log('✅ Rule created successfully!');
|
||||
console.log('');
|
||||
console.log('This rule allows devices on 192.168.0.0/24 to access VLAN 11 (192.168.11.0/24)');
|
||||
console.log('You should now be able to ping 192.168.11.10 from 192.168.0.23');
|
||||
} else {
|
||||
console.log(`❌ Failed to create rule (HTTP ${result.status})`);
|
||||
if (result.error && typeof result.error === 'object') {
|
||||
console.log(`Error: ${JSON.stringify(result.error, null, 2)}`);
|
||||
} else {
|
||||
console.log(`Error: ${result.error}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error:', error.message);
|
||||
if (error.stack) {
|
||||
console.error(error.stack);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user