diff --git a/deployments/infra/stacks/ami_pipeline_stack.go b/deployments/infra/stacks/ami_pipeline_stack.go index 3a238b0ee..f5ea05aa2 100644 --- a/deployments/infra/stacks/ami_pipeline_stack.go +++ b/deployments/infra/stacks/ami_pipeline_stack.go @@ -2,6 +2,7 @@ package stacks import ( _ "embed" + "encoding/base64" "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/aws-cdk-go/awscdk/v2/awsiam" "github.com/aws/aws-cdk-go/awscdk/v2/awsimagebuilder" @@ -14,6 +15,10 @@ import ( //go:embed docker-compose.template.yml var dockerComposeTemplate string +func getEncodedDockerCompose() string { + return base64.StdEncoding.EncodeToString([]byte(dockerComposeTemplate)) +} + type AmiPipelineStackProps struct { awscdk.StackProps } @@ -186,19 +191,24 @@ phases: action: ExecuteBash inputs: commands: - - sudo mkdir -p /opt/tn/{configs/{mainnet,testnet},scripts,data} - - sudo mkdir -p /opt/tn/configs/mainnet - - sudo mkdir -p /opt/tn/configs/testnet + - sudo mkdir -p /opt/tn/{configs/network/v2,data} - sudo chown -R tn:tn /opt/tn + - name: DownloadNetworkConfigs + action: ExecuteBash + inputs: + commands: + - cd /tmp + - curl -fsSL https://raw.githubusercontent.com/trufnetwork/truf-node-operator/main/configs/network/v2/genesis.json -o genesis.json + - sudo mv genesis.json /opt/tn/configs/network/v2/ + - sudo chown -R tn:tn /opt/tn/configs + - name: CreateDockerComposeFile action: ExecuteBash inputs: commands: - | - cat > /opt/tn/docker-compose.yml << 'EOF' - ` + dockerComposeTemplate + ` - EOF + echo "` + getEncodedDockerCompose() + `" | base64 -d > /opt/tn/docker-compose.yml - sudo chown tn:tn /opt/tn/docker-compose.yml - sudo chmod 644 /opt/tn/docker-compose.yml @@ -236,7 +246,6 @@ phases: set -e # Default values - NETWORK="testnet" PRIVATE_KEY="" ENABLE_MCP=false MCP_TRANSPORT="sse" @@ -245,10 +254,6 @@ phases: # Parse command line arguments while [[ $# -gt 0 ]]; do case $1 in - --network) - NETWORK="$2" - shift 2 - ;; --private-key) PRIVATE_KEY="$2" shift 2 @@ -273,7 +278,7 @@ phases: done echo "Configuring TRUF.NETWORK node..." - echo "Network: $NETWORK" + echo "Network: mainnet (tn-v2.1)" echo "MCP enabled: $ENABLE_MCP" # Chain ID is always tn-v2.1 regardless of network @@ -294,8 +299,8 @@ phases: # Handle private key if provided if [ -n "$PRIVATE_KEY" ]; then echo "Converting private key to nodekey.json..." - # TODO: Implement private key to nodekey.json conversion - echo "Private key conversion will be implemented" + echo "TN_PRIVATE_KEY=$PRIVATE_KEY" >> .env + echo "Private key will be converted on container startup" fi # Enable and start the service diff --git a/deployments/infra/stacks/docker-compose.template.yml b/deployments/infra/stacks/docker-compose.template.yml index cd7843380..cd891a57a 100644 --- a/deployments/infra/stacks/docker-compose.template.yml +++ b/deployments/infra/stacks/docker-compose.template.yml @@ -1,39 +1,33 @@ services: kwil-postgres: - image: kwildb/postgres:16.8-1 + image: kwildb/postgres:latest container_name: tn-postgres environment: - POSTGRES_DB: kwild - POSTGRES_USER: kwild - POSTGRES_PASSWORD: kwild + POSTGRES_HOST_AUTH_METHOD: trust volumes: - postgres_data:/var/lib/postgresql/data ports: - - "5432:5432" + - "127.0.0.1:5432:5432" networks: - tn-network restart: unless-stopped + shm_size: 1gb healthcheck: - test: ["CMD-SHELL", "pg_isready -U kwild"] + test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 12 tn-node: - image: ghcr.io/trufnetwork/node:latest + image: ghcr.io/trufnetwork/node:sha-eb8d9f0 container_name: tn-node - environment: - - SETUP_CHAIN_ID=${CHAIN_ID:-tn-v2.1} - - SETUP_DB_OWNER=${DB_OWNER:-postgres://kwild:kwild@kwil-postgres:5432/kwild} - - CONFIG_PATH=/root/.kwild + entrypoint: "" volumes: - node_data:/root/.kwild - - /opt/tn/configs:/opt/configs:ro + - /opt/tn/configs:/opt/tn/configs:ro ports: - - "50051:50051" - - "50151:50151" - - "8080:8080" - "8484:8484" + - "6600:6600" - "26656:26656" - "26657:26657" depends_on: @@ -42,19 +36,59 @@ services: networks: - tn-network restart: unless-stopped + command: | + sh -c " + # Generate config in temporary directory first + rm -rf /tmp/my-node-config + echo 'Initializing node configuration in temp directory...' + /app/kwild setup init --genesis /opt/tn/configs/network/v2/genesis.json --root /tmp/my-node-config --p2p.bootnodes \"4e0b5c952be7f26698dc1898ff3696ac30e990f25891aeaf88b0285eab4663e1#ed25519@node-1.mainnet.truf.network:26656,0c830b69790eaa09315826403c2008edc65b5c7132be9d4b7b4da825c2a166ae#ed25519@node-2.mainnet.truf.network:26656\" --state-sync.enable --state-sync.trusted-providers \"0c830b69790eaa09315826403c2008edc65b5c7132be9d4b7b4da825c2a166ae#ed25519@node-2.mainnet.truf.network:26656\" --rpc.private --db.host kwil-postgres + + # Only copy if initialization succeeded + if [ -f /tmp/my-node-config/config.toml ]; then + echo 'Copying config to /root/.kwild...' + mkdir -p /root/.kwild + cp -r /tmp/my-node-config/* /root/.kwild/ + + # Ensure database host is set correctly for Docker environment + sed -i \"s/host = '127.0.0.1'/host = 'kwil-postgres'/\" /root/.kwild/config.toml + sed -i \"s/host = 'localhost'/host = 'kwil-postgres'/\" /root/.kwild/config.toml + + echo 'Configuration setup complete!' + else + echo 'ERROR: kwild setup init failed!' + exit 1 + fi + + # Convert private key to nodekey.json if TN_PRIVATE_KEY is provided + if [ -n \"$${TN_PRIVATE_KEY:-}\" ]; then + echo 'Converting private key to nodekey.json format...' + CLEAN_KEY=\"$${TN_PRIVATE_KEY#0x}\" + if ! echo \"$$CLEAN_KEY\" | grep -qE '^[a-fA-F0-9]{64}$$'; then + echo 'Error: Private key must be 64 hex characters (32 bytes)' + exit 1 + fi + echo '{\"key\":\"'$$CLEAN_KEY'\",\"type\":\"secp256k1\"}' > /root/.kwild/nodekey.json + echo 'Nodekey created successfully' + fi + + echo 'Starting TrufNetwork node...' + /app/kwild start -r /root/.kwild + " postgres-mcp: image: crystaldba/postgres-mcp:latest container_name: tn-mcp environment: - - DATABASE_URI=postgresql://kwild:kwild@kwil-postgres:5432/kwild + - DATABASE_URI=postgresql://postgres@kwil-postgres:5432/kwild - MCP_ACCESS_MODE=restricted - MCP_TRANSPORT=sse ports: - "8000:8000" depends_on: - - kwil-postgres - - tn-node + kwil-postgres: + condition: service_healthy + tn-node: + condition: service_started networks: - tn-network restart: unless-stopped diff --git a/scripts/test-ami.sh b/scripts/test-ami.sh index 45d4a0897..ea4b6fd19 100755 --- a/scripts/test-ami.sh +++ b/scripts/test-ami.sh @@ -148,32 +148,29 @@ cat > /tmp/test-config.sh << 'EOF' #!/bin/bash set -e -NETWORK="testnet" PRIVATE_KEY="" ENABLE_MCP=false while [[ $# -gt 0 ]]; do case $1 in - --network) NETWORK="$2"; shift 2 ;; --private-key) PRIVATE_KEY="$2"; shift 2 ;; --enable-mcp) ENABLE_MCP=true; shift ;; *) echo "Unknown option $1"; exit 1 ;; esac done -echo "Network: $NETWORK" +echo "Network: mainnet (tn-v2.1)" echo "MCP enabled: $ENABLE_MCP" -[[ "$NETWORK" == "mainnet" ]] || { echo "Network parsing failed"; exit 1; } -[[ "$PRIVATE_KEY" == "test123" ]] || { echo "Private key parsing failed"; exit 1; } +[[ "$PRIVATE_KEY" == "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" ]] || { echo "Private key parsing failed"; exit 1; } [[ "$ENABLE_MCP" == true ]] || { echo "MCP flag parsing failed"; exit 1; } echo "Configuration script logic validation passed" EOF chmod +x /tmp/test-config.sh -echo "Testing: /tmp/test-config.sh --network mainnet --private-key test123 --enable-mcp" -if /tmp/test-config.sh --network mainnet --private-key "test123" --enable-mcp; then +echo "Testing: /tmp/test-config.sh --private-key 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef --enable-mcp" +if /tmp/test-config.sh --private-key "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" --enable-mcp; then echo -e "${GREEN}✅ Configuration script logic works correctly${NC}" TESTS_PASSED=$((TESTS_PASSED + 1)) else @@ -182,6 +179,148 @@ else fi rm -f /tmp/test-config.sh +# Test 6.2: Private Key Validation +echo "6.2 Testing private key validation..." +echo "Testing that invalid private keys are rejected..." + +# Test invalid key (too short) +cat > /tmp/test-validation.sh << 'EOF' +#!/bin/bash +set -e + +# Simulate the validation logic from Docker container +PRIVATE_KEY="$1" +CLEAN_KEY="${PRIVATE_KEY#0x}" + +if ! echo "$CLEAN_KEY" | grep -qE '^[a-fA-F0-9]{64}$'; then + echo "Error: Private key must be 64 hex characters (32 bytes)" + exit 1 +fi + +echo "Valid private key" +EOF + +chmod +x /tmp/test-validation.sh + +# Test 1: Invalid short key should fail +if /tmp/test-validation.sh "test123" 2>/dev/null; then + echo -e "${RED}❌ Short private key validation failed - should reject invalid keys${NC}" + TESTS_FAILED=$((TESTS_FAILED + 1)) +else + echo -e "${GREEN}✅ Short private key correctly rejected${NC}" + TESTS_PASSED=$((TESTS_PASSED + 1)) +fi + +# Test 2: Valid key should pass +if /tmp/test-validation.sh "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; then + echo -e "${GREEN}✅ Valid private key correctly accepted${NC}" + TESTS_PASSED=$((TESTS_PASSED + 1)) +else + echo -e "${RED}❌ Valid private key validation failed${NC}" + TESTS_FAILED=$((TESTS_FAILED + 1)) +fi + +# Test 3: Key with 0x prefix should work +if /tmp/test-validation.sh "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; then + echo -e "${GREEN}✅ Private key with 0x prefix correctly accepted${NC}" + TESTS_PASSED=$((TESTS_PASSED + 1)) +else + echo -e "${RED}❌ Private key with 0x prefix validation failed${NC}" + TESTS_FAILED=$((TESTS_FAILED + 1)) +fi + +rm -f /tmp/test-validation.sh + +# Test 6.3: Negative Private Key Tests +echo "6.3 Testing negative private key validation cases..." +echo "Testing various invalid private key formats..." + +cat > /tmp/test-negative.sh << 'EOF' +#!/bin/bash +set -e + +# Simulate the validation logic from Docker container +PRIVATE_KEY="$1" +CLEAN_KEY="${PRIVATE_KEY#0x}" + +if ! echo "$CLEAN_KEY" | grep -qE '^[a-fA-F0-9]{64}$'; then + echo "Error: Private key must be 64 hex characters (32 bytes)" + exit 1 +fi + +echo "Valid private key" +EOF + +chmod +x /tmp/test-negative.sh + +# Array of invalid test cases +INVALID_KEYS=( + "test123" # Too short + "" # Empty string + "123" # Way too short + "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" # Non-hex characters (g) + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcde" # 63 chars (too short by 1) + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1" # 65 chars (too long by 1) + "xyz1567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" # Non-hex at start + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdez" # Non-hex at end + "1234 67890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" # Contains space + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdeG" # Non-hex character G at end + "G234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" # Non-hex character G at start + "!@#\$567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" # Special characters + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdXX" # Non-hex character +) + +DESCRIPTIONS=( + "short alphanumeric" + "empty string" + "very short number" + "non-hex characters (g)" + "63 characters (too short)" + "65 characters (too long)" + "non-hex at start" + "non-hex at end" + "contains space" + "non-hex character G at end" + "non-hex character G at start" + "special characters" + "non-hex character XX" +) + +NEGATIVE_TESTS_PASSED=0 +NEGATIVE_TESTS_FAILED=0 + +for i in "${!INVALID_KEYS[@]}"; do + KEY="${INVALID_KEYS[$i]}" + DESC="${DESCRIPTIONS[$i]}" + + echo "Testing invalid key: $DESC" + + if /tmp/test-negative.sh "$KEY" 2>/dev/null; then + echo -e "${RED}❌ FAILED: Invalid key '$DESC' was incorrectly accepted${NC}" + NEGATIVE_TESTS_FAILED=$((NEGATIVE_TESTS_FAILED + 1)) + TESTS_FAILED=$((TESTS_FAILED + 1)) + else + echo -e "${GREEN}✅ PASSED: Invalid key '$DESC' correctly rejected${NC}" + NEGATIVE_TESTS_PASSED=$((NEGATIVE_TESTS_PASSED + 1)) + TESTS_PASSED=$((TESTS_PASSED + 1)) + fi +done + +echo "" +echo "Negative test summary: $NEGATIVE_TESTS_PASSED passed, $NEGATIVE_TESTS_FAILED failed" + +# Test edge case: Mixed case should actually be VALID (hex is case-insensitive) +echo "Testing edge case: Mixed case hex (should be valid)..." +if /tmp/test-negative.sh "1234567890ABCDEF1234567890abcdef1234567890ABCDEF1234567890abcdef"; then + echo -e "${GREEN}✅ Mixed case hex correctly accepted (case-insensitive)${NC}" + TESTS_PASSED=$((TESTS_PASSED + 1)) +else + echo -e "${RED}❌ Mixed case hex incorrectly rejected${NC}" + TESTS_FAILED=$((TESTS_FAILED + 1)) +fi + +rm -f /tmp/test-negative.sh + # Test 7: Environment File Generation echo "7. Testing environment file generation..." echo "Testing environment file creation for different network configurations..." @@ -358,7 +497,7 @@ if [ "${TESTS_FAILED}" -eq 0 ]; then echo "📝 Next steps:" echo " 1. Deploy the AMI infrastructure: cd deployments/infra && cdk deploy AMI-Pipeline-default-Stack" echo " 2. Test AMI build: Go to GitHub Actions and run the 'Build AMI' workflow" - echo " 3. Test user experience: Launch AMI and run tn-node-configure --network testnet --enable-mcp" + echo " 3. Test user experience: Launch AMI and run tn-node-configure --enable-mcp" echo "" exit 0 else