@@ -5,8 +5,9 @@ pub struct CloudFormationTemplate {
55 pub stack_name : String ,
66 pub region : String ,
77 pub ingress_host : String ,
8- pub ingress_port : u16 ,
8+ pub ingress_port : u16 , // Primary port (first ingress) for backwards compat
99 pub ingress_protocol : String ,
10+ pub port_mappings : Vec < ( u16 , String ) > , // All port mappings (port, protocol)
1011 pub origin_host : String ,
1112 pub origin_port : u16 ,
1213 pub origin_ip : String ,
@@ -334,15 +335,19 @@ impl CloudFormationTemplate {
334335 "CidrIp" : format!( "{}/32" , self . origin_ip) ,
335336 "Description" : "WireGuard from origin"
336337 } ) ,
337- json!( {
338- "IpProtocol" : self . ingress_protocol. as_str( ) ,
339- "FromPort" : self . ingress_port,
340- "ToPort" : self . ingress_port,
341- "CidrIp" : "0.0.0.0/0" ,
342- "Description" : "Ingress traffic"
343- } ) ,
344338 ] ;
345339
340+ // Add rules for each port mapping
341+ for ( port, protocol) in & self . port_mappings {
342+ rules. push ( json ! ( {
343+ "IpProtocol" : protocol. to_lowercase( ) ,
344+ "FromPort" : port,
345+ "ToPort" : port,
346+ "CidrIp" : "0.0.0.0/0" ,
347+ "Description" : format!( "Ingress {} traffic on port {}" , protocol. to_uppercase( ) , port)
348+ } ) ) ;
349+ }
350+
346351 if self . debug {
347352 rules. push ( json ! ( {
348353 "IpProtocol" : "tcp" ,
@@ -386,16 +391,32 @@ impl CloudFormationTemplate {
386391 . map ( |s| format ! ( "{}.0" , s) )
387392 . unwrap_or_else ( || "172.17.0.0" . to_string ( ) ) ;
388393
394+ // Generate Nix list expression for port mappings
395+ // Format: [ { port = 80; protocol = "tcp"; } { port = 443; protocol = "tcp"; } ]
396+ let port_mappings_nix = if self . port_mappings . is_empty ( ) {
397+ "[ ]" . to_string ( )
398+ } else {
399+ let mappings: Vec < String > = self . port_mappings
400+ . iter ( )
401+ . map ( |( port, protocol) | {
402+ format ! (
403+ "{{ port = {}; protocol = \" {}\" ; }}" ,
404+ port,
405+ protocol. to_lowercase( )
406+ )
407+ } )
408+ . collect ( ) ;
409+ format ! ( "[\n {}\n ]" , mappings. join( "\n " ) )
410+ } ;
411+
389412 // Replace placeholders in the Nix template
390413 let nix_config = NIX_TEMPLATE
391414 . replace (
392415 "debug = false" ,
393416 & format ! ( "debug = {}" , if self . debug { "true" } else { "false" } ) ,
394417 )
395418 . replace ( "{PROXY_WG_PRIVATE_KEY}" , & self . proxy_wg_private_key )
396- . replace ( "{PROTOCOL}" , & self . ingress_protocol )
397- . replace ( "{INGRESS_PORT}" , & self . ingress_port . to_string ( ) )
398- . replace ( "{ORIGIN_PORT}" , & self . origin_port . to_string ( ) )
419+ . replace ( "{PORT_MAPPINGS}" , & port_mappings_nix)
399420 . replace ( "{ORIGIN_WG_PUBLIC_KEY}" , & self . origin_wg_public_key )
400421 . replace ( "{PRESHARED_KEY}" , & self . preshared_key )
401422 . replace ( "{ORIGIN_IP}" , & self . wg_origin_ip )
@@ -420,6 +441,7 @@ mod tests {
420441 ingress_host : "test.example.com" . to_string ( ) ,
421442 ingress_port : 80 ,
422443 ingress_protocol : "tcp" . to_string ( ) ,
444+ port_mappings : vec ! [ ( 80 , "tcp" . to_string( ) ) ] ,
423445 origin_host : "localhost" . to_string ( ) ,
424446 origin_port : 8080 ,
425447 origin_ip : "1.2.3.4" . to_string ( ) ,
@@ -445,6 +467,7 @@ mod tests {
445467 ingress_host : "test.example.com" . to_string ( ) ,
446468 ingress_port : 80 ,
447469 ingress_protocol : "tcp" . to_string ( ) ,
470+ port_mappings : vec ! [ ( 80 , "tcp" . to_string( ) ) ] ,
448471 origin_host : "localhost" . to_string ( ) ,
449472 origin_port : 8080 ,
450473 origin_ip : "1.2.3.4" . to_string ( ) ,
@@ -470,6 +493,7 @@ mod tests {
470493 ingress_host : "test.example.com" . to_string ( ) ,
471494 ingress_port : 80 ,
472495 ingress_protocol : "tcp" . to_string ( ) ,
496+ port_mappings : vec ! [ ( 80 , "tcp" . to_string( ) ) ] ,
473497 origin_host : "localhost" . to_string ( ) ,
474498 origin_port : 8080 ,
475499 origin_ip : "1.2.3.4" . to_string ( ) ,
@@ -486,10 +510,11 @@ mod tests {
486510
487511 let userdata = template. generate_userdata ( ) ;
488512 let userdata_str = serde_json:: to_string ( & userdata) . unwrap ( ) ;
489- // Check for NixOS configuration syntax and TCP protocol
513+ // Check for NixOS configuration syntax and port mappings
490514 assert ! ( userdata_str. contains( "{ config, pkgs, lib, ... }:" ) ) ;
491515 assert ! ( userdata_str. contains( "debug = false" ) ) ;
492- assert ! ( userdata_str. contains( "-p tcp --dport 80" ) ) ;
516+ assert ! ( userdata_str. contains( "port = 80" ) ) ;
517+ assert ! ( userdata_str. contains( "protocol = \\ \" tcp\\ \" " ) ) ;
493518 }
494519
495520 #[ test]
@@ -500,6 +525,7 @@ mod tests {
500525 ingress_host : "test.example.com" . to_string ( ) ,
501526 ingress_port : 53 ,
502527 ingress_protocol : "udp" . to_string ( ) ,
528+ port_mappings : vec ! [ ( 53 , "udp" . to_string( ) ) ] ,
503529 origin_host : "localhost" . to_string ( ) ,
504530 origin_port : 53 ,
505531 origin_ip : "1.2.3.4" . to_string ( ) ,
@@ -516,10 +542,11 @@ mod tests {
516542
517543 let userdata = template. generate_userdata ( ) ;
518544 let userdata_str = serde_json:: to_string ( & userdata) . unwrap ( ) ;
519- // Check for NixOS configuration syntax and UDP protocol
545+ // Check for NixOS configuration syntax and port mappings
520546 assert ! ( userdata_str. contains( "{ config, pkgs, lib, ... }:" ) ) ;
521547 assert ! ( userdata_str. contains( "debug = false" ) ) ;
522- assert ! ( userdata_str. contains( "-p udp --dport 53" ) ) ;
548+ assert ! ( userdata_str. contains( "port = 53" ) ) ;
549+ assert ! ( userdata_str. contains( "protocol = \\ \" udp\\ \" " ) ) ;
523550 }
524551
525552 #[ test]
@@ -530,6 +557,7 @@ mod tests {
530557 ingress_host : "test.example.com" . to_string ( ) ,
531558 ingress_port : 80 ,
532559 ingress_protocol : "tcp" . to_string ( ) ,
560+ port_mappings : vec ! [ ( 80 , "tcp" . to_string( ) ) ] ,
533561 origin_host : "localhost" . to_string ( ) ,
534562 origin_port : 8080 ,
535563 origin_ip : "1.2.3.4" . to_string ( ) ,
0 commit comments