Before we can create the subnets we still need to create security lists. They will control what ingress and egress traffic will be allowed within subnets.
I will create two security lists for this project, one for private subnet and another one for public subnet. Security lists can have have multiple rules in them and you can assign multiple security lists to a subnet.
Usually if you are having connection issues first thing I would look is the security list and it’s rules.
By default the rules are stateful so if you have allowed ingress traffic on port 80 you don’t need to open port 80 for the egress traffic. With stateless rules you need to keep it updated both ways.
I will make public security list which allows ingress traffic from anywhere to port 22 (SSH). Usually if I need to access it from outside I restrict it to my corporate CIDR block or then just use my own /32 IP so port is blocked from most of locations.
Traffic will be also allowed from public subnet to private subnet port 22 (SSH) and port 1521 (DB listener) to demonstrate how you can access the database and add multiple rules to security list. Finally all traffic from private subnet to public subnet will be allowed.
This time there are more variables to be added into main.tf and variables.tf than just names. We will need to define multiple rules for security list and each rule will contain:
Depending on what you are implementing check if you need to have ICMP traffic allowed. We got recommendation that with our VPN connection we should allow all ICMP type traffic for optimal network performance.
// PUBLIC AND PRIVATE SECURITYLIST VARIABLES
variable "public_sl_display_name" {
default = "PublicSL"
} // Name for the public securitylist
variable "private_sl_display_name" {
default = "PrivateSL"
} // Name for the private securitylist
variable "egress_destination" {
default = "0.0.0.0/0"
} // Outside traffic is allowed
variable "tcp_protocol" {
default = "6"
} // 6 for TCP traffic
variable "public_ssh_sl_source" {
default = "0.0.0.0/0"
}
variable "rule_stateless" {
default = "false"
} // All rules are stateful by default so no need to define rules both ways
variable "public_sl_ssh_tcp_port" {
default = "22"
} // Open port 22 for SSH access
variable "private_sl_ssh_tcp_port" {
default = "22"
} // Open port 22 for SSH access
variable "private_sl_db_tcp_port" {
default = "1521"
} // Open port 1521 for DB listener
And here are above variables used in main.tf. Really nothing complicated but just passing all necessary variables here into use.
resource "oci_core_security_list" "CreatePublicSecurityList" {
compartment_id = "${oci_identity_compartment.CreateCompartment.id}"
vcn_id = "${oci_core_virtual_network.CreateVCN.id}"
display_name = "${var.public_sl_display_name}"
// Allow outbound tcp traffic on all ports
egress_security_rules {
destination = "${var.egress_destination}"
protocol = "${var.tcp_protocol}"
}
// allow inbound ssh traffic from a specific port
ingress_security_rules = [{
protocol = "${var.tcp_protocol}" // tcp = 6
source = "${var.public_ssh_sl_source}" // Can be restricted for specific IP address
stateless = "${var.rule_stateless}"
tcp_options {
// These values correspond to the destination port range.
"min" = "${var.public_sl_ssh_tcp_port}"
"max" = "${var.public_sl_ssh_tcp_port}"
}
},
{
protocol = "${var.tcp_protocol}" // tcp = 6
source = "${var.vcn_cidr_block}" // open all ports for VCN CIDR and do not block subnet traffic
stateless = "${var.rule_stateless}"
},
]
}
resource "oci_core_security_list" "CreatePrivateSecurityList" {
compartment_id = "${oci_identity_compartment.CreateCompartment.id}"
vcn_id = "${oci_core_virtual_network.CreateVCN.id}"
display_name = "${var.private_sl_display_name}"
// Allow outbound tcp traffic on all ports
egress_security_rules {
destination = "${var.egress_destination}"
protocol = "${var.tcp_protocol}"
}
// allow inbound traffic from VCN
ingress_security_rules = [
{
protocol = "${var.tcp_protocol}" // tcp = 6
source = "${var.vcn_cidr_block}" // open all ports for VCN CIDR and do not block subnet traffic
stateless = "${var.rule_stateless}"
tcp_options {
// These values correspond to the destination port range.
"min" = "${var.private_sl_ssh_tcp_port}"
"max" = "${var.private_sl_ssh_tcp_port}"
}
},
{
protocol = "${var.tcp_protocol}" // tcp = 6
source = "${var.vcn_cidr_block}" // open all ports for VCN CIDR and do not block subnet traffic
stateless = "${var.rule_stateless}"
tcp_options {
// These values correspond to the destination port range.
"min" = "${var.private_sl_db_tcp_port}"
"max" = "${var.private_sl_db_tcp_port}"
}
}
]
}
I’ve run Terraform plan and apply. Output can be seen below and when I go to verify everything from console I see same rules exist now. You can see from Terraform output that there are multiple rules created.
oci_core_security_list.CreatePrivateSecurityList: Creating...
compartment_id: "" => "ocid1.compartment.oc1..xxxxx"
display_name: "" => "PrivateSL"
egress_security_rules.#: "" => "1"
egress_security_rules.1420396200.destination: "" => "0.0.0.0/0"
egress_security_rules.1420396200.destination_type: "" => "<computed>"
egress_security_rules.1420396200.icmp_options.#: "" => "0"
egress_security_rules.1420396200.protocol: "" => "6"
egress_security_rules.1420396200.stateless: "" => "<computed>"
egress_security_rules.1420396200.tcp_options.#: "" => "0"
egress_security_rules.1420396200.udp_options.#: "" => "0"
freeform_tags.%: "" => "<computed>"
ingress_security_rules.#: "" => "2"
ingress_security_rules.2353706552.icmp_options.#: "" => "0"
ingress_security_rules.2353706552.protocol: "" => "6"
ingress_security_rules.2353706552.source: "" => "172.16.0.0/16"
ingress_security_rules.2353706552.source_type: "" => "<computed>"
ingress_security_rules.2353706552.stateless: "" => "false"
ingress_security_rules.2353706552.tcp_options.#: "" => "1"
ingress_security_rules.2353706552.tcp_options.0.max: "" => "1521"
ingress_security_rules.2353706552.tcp_options.0.min: "" => "1521"
ingress_security_rules.2353706552.tcp_options.0.source_port_range.#: "" => "0"
ingress_security_rules.2353706552.udp_options.#: "" => "0"
ingress_security_rules.3291565597.icmp_options.#: "" => "0"
ingress_security_rules.3291565597.protocol: "" => "6"
ingress_security_rules.3291565597.source: "" => "172.16.0.0/16"
ingress_security_rules.3291565597.source_type: "" => "<computed>"
ingress_security_rules.3291565597.stateless: "" => "false"
ingress_security_rules.3291565597.tcp_options.#: "" => "1"
ingress_security_rules.3291565597.tcp_options.0.max: "" => "22"
ingress_security_rules.3291565597.tcp_options.0.min: "" => "22"
ingress_security_rules.3291565597.tcp_options.0.source_port_range.#: "" => "0"
ingress_security_rules.3291565597.udp_options.#: "" => "0"
state: "" => "<computed>"
time_created: "" => "<computed>"
vcn_id: "" => "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"
oci_core_security_list.CreatePublicSecurityList: Creating...
compartment_id: "" => "ocid1.compartment.oc1..xxxxx"
display_name: "" => "PublicSL"
egress_security_rules.#: "" => "1"
egress_security_rules.1420396200.destination: "" => "0.0.0.0/0"
egress_security_rules.1420396200.destination_type: "" => "<computed>"
egress_security_rules.1420396200.icmp_options.#: "" => "0"
egress_security_rules.1420396200.protocol: "" => "6"
egress_security_rules.1420396200.stateless: "" => "<computed>"
egress_security_rules.1420396200.tcp_options.#: "" => "0"
egress_security_rules.1420396200.udp_options.#: "" => "0"
freeform_tags.%: "" => "<computed>"
ingress_security_rules.#: "" => "2"
ingress_security_rules.47193274.icmp_options.#: "" => "0"
ingress_security_rules.47193274.protocol: "" => "6"
ingress_security_rules.47193274.source: "" => "0.0.0.0/0"
ingress_security_rules.47193274.source_type: "" => "<computed>"
ingress_security_rules.47193274.stateless: "" => "false"
ingress_security_rules.47193274.tcp_options.#: "" => "1"
ingress_security_rules.47193274.tcp_options.0.max: "" => "22"
ingress_security_rules.47193274.tcp_options.0.min: "" => "22"
ingress_security_rules.47193274.tcp_options.0.source_port_range.#: "" => "0"
ingress_security_rules.47193274.udp_options.#: "" => "0"
ingress_security_rules.613850372.icmp_options.#: "" => "0"
ingress_security_rules.613850372.protocol: "" => "6"
ingress_security_rules.613850372.source: "" => "172.16.0.0/16"
ingress_security_rules.613850372.source_type: "" => "<computed>"
ingress_security_rules.613850372.stateless: "" => "false"
ingress_security_rules.613850372.tcp_options.#: "" => "0"
ingress_security_rules.613850372.udp_options.#: "" => "0"
state: "" => "<computed>"
time_created: "" => "<computed>"
vcn_id: "" => "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"
oci_core_security_list.CreatePrivateSecurityList: Creation complete after 1s (ID: ocid1.securitylist.oc1.eu-frankfurt-1.a...xxxxx)
oci_core_security_list.CreatePublicSecurityList: Creation complete after 2s (ID: ocid1.securitylist.oc1.eu-frankfurt-1.a...xxxxx)
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Understanding security lists and how they work is essential to create your network configuration so it’s good to put some thought into it so you get everything sorted out properly.
One thing I’d like to point out is that as you can see providing multiple rules to security lists is passed as a list (hence the usage of [] ).
But you can’t pass these through a Terraform module so you end up manually adding necessary rows for new list items. This is one of the biggest things creating unnecessary manual work for us at the moment as hacking the modules when you need to open 4-5 ports comes increasingly difficult and the whole concept of using reusable modules becomes obsolete.
Now since we have security lists completed we are ready to create the subnets next!
Last time I showed how to provision Autonomous Database Serverless (ADB-S) on Google Cloud. This…
I bet few years back folks didn't expect that by 2024 we would be able…
This will NOT be a technical walkthrough on Oracle Database@Azure but rather my opinions and…
Recently OCI announced small but VERY useful service, IP Address Insights. Why this matters? I've…
View Comments
Nice work. Hopefully, we'll be able to variablize the rules in the next TF version.