Expose arbitrary port
gyuho opened this issue · 3 comments
gyuho commented
Should allow arbitrary port from user and expose that to a certain IP or public.
gyuho commented
Some example workflow...
- let parameters = Vec::from([
+ let mut parameters = Vec::from([
build_param("Id", &spec.id),
build_param("UserId", &aws_resources.identity.user_id),
build_param("VpcCidr", "10.0.0.0/16"),
build_param("PublicSubnetCidr1", "10.0.64.0/19"),
build_param("PublicSubnetCidr2", "10.0.128.0/19"),
build_param("PublicSubnetCidr3", "10.0.192.0/19"),
- build_param("SshPortIngressIpv4Range", "0.0.0.0/0"),
- build_param("HttpPortIngressIpv4Range", "0.0.0.0/0"),
+ build_param(
+ "SshPortIngressIpv4Range",
+ if !spec.aws_resources.ssh_ingress_ipv4_cidr.is_empty() {
+ spec.aws_resources.ssh_ingress_ipv4_cidr.as_str()
+ } else {
+ "0.0.0.0/0"
+ },
+ ),
+ build_param(
+ "UserDefinedTcpIngressPortsIngressIpv4Range",
+ if !spec
+ .aws_resources
+ .user_defined_tcp_ingress_ports_ipv4_cidr
+ .is_empty()
+ {
+ spec.aws_resources
+ .user_defined_tcp_ingress_ports_ipv4_cidr
+ .as_str()
+ } else {
+ "0.0.0.0/0"
+ },
+ ),
]);
+ if !spec.aws_resources.user_defined_tcp_ingress_ports.is_empty() {
+ let mut ports_in_str: Vec<String> = Vec::new();
+ for p in spec.aws_resources.user_defined_tcp_ingress_ports.iter() {
+ ports_in_str.push(format!("{}", p));
+ }
+ parameters.push(build_param(
+ "UserDefinedTcpIngressPorts",
+ ports_in_str.join(",").as_str(),
+ ));
+ parameters.push(build_param(
+ "UserDefinedTcpIngressPortsCount",
+ format!("{}", ports_in_str.len()).as_str(),
+ ));
+ } else {
+ parameters.push(build_param("UserDefinedTcpIngressPortsCount", "0"));
+ }
+ UserDefinedTcpIngressPorts:
+ Type: CommaDelimitedList
+ Default: 0
+ Description: User-defined ports to TCP open for ingress traffic
+
+ UserDefinedTcpIngressPortsCount:
+ Type: Number
+ Default: 0
+ MinValue: 0
+ MaxValue: 10
+ Description: The number of instance types (must be >0 to enable)
+
# in case, we deploy some sample app
# limit this to your IP
- HttpPortIngressIpv4Range:
+ UserDefinedTcpIngressPortsIngressIpv4Range:
Type: String
Default: 0.0.0.0/0
AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
- Description: IP range for HTTP inbound traffic
-
- HttpPort:
- Type: Number
- Default: 3000
- Description: HTTP port
+ Description: IP range for user-defined TCP inbound traffic
Conditions:
Has2Azs:
@@ -84,6 +91,173 @@ Conditions:
Fn::Not:
- Condition: Has2Azs
+ Has1UserDefinedTcpIngressPorts:
+ Fn::Not:
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
+ - 0
+
+ Has2UserDefinedTcpIngressPorts:
+ Fn::Or:
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
+ - 2
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
+ - 3
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
+ - 4
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
+ - 5
+ - Fn::Equals:
+ - Ref: UserDefinedTcpIngressPortsCount
CidrIp: !Ref SshPortIngressIpv4Range
- HttpIngress:
+ UserDefinedTcpIngress1:
+ Type: AWS::EC2::SecurityGroupIngress
+ Condition: Has1UserDefinedTcpIngressPorts
+ Properties:
+ GroupId: !Ref SecurityGroup
+ IpProtocol: tcp
+ FromPort: !Select [0, !Ref UserDefinedTcpIngressPorts]
+ ToPort: !Select [0, !Ref UserDefinedTcpIngressPorts]
+ CidrIp: !Ref UserDefinedTcpIngressPortsIngressIpv4Range
+
+ UserDefinedTcpIngress2:
+ Type: AWS::EC2::SecurityGroupIngress
+ Condition: Has2UserDefinedTcpIngressPorts
+ Properties:
+ GroupId: !Ref SecurityGroup
+ IpProtocol: tcp
+ FromPort: !Select [1, !Ref UserDefinedTcpIngressPorts]
+ ToPort: !Select [1, !Ref UserDefinedTcpIngressPorts]
+ CidrIp: !Ref UserDefinedTcpIngressPortsIngressIpv4Range
+
+ UserDefinedTcpIngress3:
+ Type: AWS::EC2::SecurityGroupIngress
+ Condition: Has3UserDefinedTcpIngressPorts
+ Properties:
+ GroupId: !Ref SecurityGroup
+ IpProtocol: tcp
+ FromPort: !Select [2, !Ref UserDefinedTcpIngressPorts]
+ ToPort: !Select [2, !Ref UserDefinedTcpIngressPorts]
+ CidrIp: !Ref UserDefinedTcpIngressPortsIngressIpv4Range
.arg(
- Arg::new("INGRESS_IPV4_CIDR")
- .long("ingress-ipv4-cidr")
- .help("Sets the IPv4 CIDR range for ingress traffic HTTP/SSH (leave empty to default to public IP on the local)")
+ Arg::new("SSH_INGRESS_IPV4_CIDR")
+ .long("ssh-ingress-ipv4-cidr")
+ .help("Sets the IPv4 CIDR range for ingress SSH traffic (leave empty to default to public IP on the local)")
+ .required(false)
+ .num_args(1),
+ )
+ .arg(
+ Arg::new("USER_DEFINED_TCP_INGRESS_PORTS_IPV4_CIDR")
+ .long("user-defined-tcp-ingress-ports-ipv4-cidr")
+ .help("Sets the IPv4 CIDR range for ingress SSH traffic (leave empty to default to public IP on the local)")
+ .required(false)
+ .num_args(1),
+ )
+ .arg(
+ Arg::new("USER_DEFINED_TCP_INGRESS_PORTS")
+ .long("user-defined-tcp-ingress-ports")
+ .help("Sets the comma-separated TCP ingress ports (up to 10)")
.required(false)
.num_args(1),
@@ -89,7 +89,11 @@ pub struct Resources {
pub region: String,
#[serde(default)]
- pub ingress_ipv4_cidr: String,
+ pub ssh_ingress_ipv4_cidr: String,
+ #[serde(default)]
+ pub user_defined_tcp_ingress_ports_ipv4_cidr: String,
+ #[serde(default)]
+ pub user_defined_tcp_ingress_ports: Vec<u32>,
#[serde(default)]
pub s3_bucket: String,
@@ -146,7 +150,9 @@ impl Resources {
region: String::from("us-west-2"),
- ingress_ipv4_cidr: String::from("0.0.0.0/0"),
+ ssh_ingress_ipv4_cidr: String::from("0.0.0.0/0"),
+ user_defined_tcp_ingress_ports_ipv4_cidr: String::from("0.0.0.0/0"),
+ user_defined_tcp_ingress_ports: Vec::new(),
s3_bucket: String::from(""),
@@ -209,7 +215,9 @@ pub struct DefaultSpecOption {
pub unsafe_temporary_aws_secret_key_id: String,
pub unsafe_temporary_aws_secret_access_key: String,
- pub ingress_ipv4_cidr: String,
+ pub ssh_ingress_ipv4_cidr: String,
+ pub user_defined_tcp_ingress_ports_ipv4_cidr: String,
+ pub user_defined_tcp_ingress_ports: Vec<u32>,
- let ingress_ipv4_cidr = if !opts.ingress_ipv4_cidr.is_empty() {
- opts.ingress_ipv4_cidr.clone()
+ let ssh_ingress_ipv4_cidr = if !opts.ssh_ingress_ipv4_cidr.is_empty() {
+ opts.ssh_ingress_ipv4_cidr.clone()
} else {
- log::info!("empty ingress_ipv4_cidr, so default to public IP on the local host");
+ log::info!("empty ssh_ingress_ipv4_cidr, so default to public IP on the local host");
+ if let Some(ip) = public_ip::addr().await {
+ log::info!("found public ip address {:?}", ip);
+ format!("{}/32", ip.to_string())
+ } else {
+ log::warn!("failed to get a public IP address -- default to 0.0.0.0/0");
+ "0.0.0.0/0".to_string()
+ }
+ };
+
+ let user_defined_tcp_ingress_ports_ipv4_cidr = if !opts
+ .user_defined_tcp_ingress_ports_ipv4_cidr
+ .is_empty()
+ {
+ opts.user_defined_tcp_ingress_ports_ipv4_cidr.clone()
+ } else {
+ log::info!("empty user_defined_tcp_ingress_ports_ipv4_cidr, so default to public IP on the local host");
@@ -44,7 +44,29 @@ async fn main() {
let plugins: Vec<String> = if s.is_empty() {
Vec::new()
} else {
- s.split(',').map(|x| x.to_string()).collect()
+ s.split(',').map(|x| x.trim().to_string()).collect()
+ };
+
+ let s = sub_matches
+ .get_one::<String>("USER_DEFINED_TCP_INGRESS_PORTS")
+ .unwrap_or(&String::new())
+ .clone();
+ let user_defined_tcp_ingress_ports: Vec<u32> = if s.is_empty() {
+ Vec::new()
+ } else {
+ s.split(',')
+ .map(|x| x.trim().to_string().parse::<u32>().unwrap())
+ .collect()
+ };
+
+ let s = sub_matches
+ .get_one::<String>("INSTANCE_TYPES")
+ .unwrap_or(&String::new())
+ .clone();
+ let instance_types: Vec<String> = if s.is_empty() {
+ Vec::new()
+ } else {
+ s.split(',').map(|x| x.trim().to_string()).collect()
};
- ingress_ipv4_cidr: sub_matches
- .get_one::<String>("INGRESS_IPV4_CIDR")
+ ssh_ingress_ipv4_cidr: sub_matches
+ .get_one::<String>("SSH_INGRESS_IPV4_CIDR")
+ .unwrap_or(&String::new())
+ .clone(),
+
+ user_defined_tcp_ingress_ports_ipv4_cidr: sub_matches
+ .get_one::<String>("USER_DEFINED_TCP_INGRESS_PORTS_IPV4_CIDR")
.unwrap_or(&String::new())
.clone(),
+ user_defined_tcp_ingress_ports,
exdx commented
Use case:
Run grafana on the dev box and be able to open 9090 without going into the AWS console
exdx commented
To start we will just allow a user to set one arbitrary port (default 9090).