Building Oracle Cloud infrastructure with Terraform – basic security
- Written by: ilmarkerm
- Category: Blog entry
- Published: April 14, 2024
Here I’m exploring how to control the basic network level resource security accesses. In AWS there is a concept called Security Groups. In OCI Oracle Cloud the similar concept is called Network Security Groups, also there is a little bit less powerful concept called Security Lists. A good imprevement with Network Security Groups over Security Lists is that in rules you can refer to other NSGs, not only CIDR.
Below I create two NSG – one for databases and one for application servers, and allow unrestricted outgoing traffc from them both.
# security.tf
# Rules for appservers
resource "oci_core_network_security_group" "appserver" {
compartment_id = oci_identity_compartment.compartment.id
vcn_id = oci_core_vcn.main.id
display_name = "Application servers"
}
resource "oci_core_network_security_group_security_rule" "appserver_egress" {
network_security_group_id = oci_core_network_security_group.appserver.id
direction = "EGRESS"
protocol = "all"
description = "Allow all Egress traffic"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
}
# Rules for databases
resource "oci_core_network_security_group" "db" {
compartment_id = oci_identity_compartment.compartment.id
vcn_id = oci_core_vcn.main.id
display_name = "Databases"
}
resource "oci_core_network_security_group_security_rule" "db_egress" {
network_security_group_id = oci_core_network_security_group.db.id
direction = "EGRESS"
protocol = "all"
description = "Allow all Egress traffic"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
}
Some rule examples to allow traffic from appservers towards databases. Here referring to the appserver NSG as source – not a CIDR.
# This rule allows port 1521/tcp to be accessed from NSG "appserver" created earlier
resource "oci_core_network_security_group_security_rule" "db_appserver_oracle" {
network_security_group_id = oci_core_network_security_group.db.id
direction = "INGRESS"
protocol = "6" # TCP
description = "Allow ingress from application servers to 1521/tcp"
source_type = "NETWORK_SECURITY_GROUP"
source = oci_core_network_security_group.appserver.id
tcp_options {
destination_port_range {
min = 1521
max = 1521
}
}
}
# This rule allows port 5432/tcp to be accessed from NSG "appserver" created earlier
resource "oci_core_network_security_group_security_rule" "db_appserver_postgres" {
network_security_group_id = oci_core_network_security_group.db.id
direction = "INGRESS"
protocol = "6" # TCP
description = "Allow ingress from application servers to 5432/tcp"
source_type = "NETWORK_SECURITY_GROUP"
source = oci_core_network_security_group.appserver.id
tcp_options {
destination_port_range {
min = 5432
max = 5432
}
}
}
And one example rule for appserver group, here I just want to show that the source NSG can refer to itself – so the port is open only to resources placed in the same NSG.
# This rule allows port 80/tcp to be accessed from the NSG itself
# Example use - the application is running unencrypted HTTP and is expected to have a loadbalancer in front, that does the encryption. In this case loadbalancer could be put to the same NSG.
# Or if the different application servers need to have a backbone communication port between each other - like cluster interconnect
resource "oci_core_network_security_group_security_rule" "appserver_http" {
network_security_group_id = oci_core_network_security_group.appserver.id
direction = "INGRESS"
protocol = "6" # TCP
description = "Allow access port port 80/tcp only from current NSG (self)"
source_type = "NETWORK_SECURITY_GROUP"
source = oci_core_network_security_group.appserver.id
tcp_options {
destination_port_range {
min = 80
max = 80
}
}
}
Now, network security groups need to be attached to the resources they are intended to protect. NSG-s are attached to the virtual network adapers VNICs.
To attach NSG to my previously created compute instance, I have to go back and edit the compute instance declaration to attach a NSG to the primary VNIC of that instance.
# compute.tf
resource "oci_core_instance" "arm_instance" {
compartment_id = oci_identity_compartment.compartment.id
# oci iam availability-domain list
availability_domain = "MpAX:EU-STOCKHOLM-1-AD-1"
# oci compute shape list --compartment-id
shape = "VM.Standard.A1.Flex" # ARM based shape
shape_config {
# How many CPUs and memory
ocpus = 2
memory_in_gbs = 4
}
display_name = "test-arm-1"
source_details {
# The source operating system image
# oci compute image list --all --output table --compartment-id
source_id = data.oci_core_images.oel.images[0].id
source_type = "image"
}
create_vnic_details {
# Network details
subnet_id = oci_core_subnet.subnet.id
assign_public_ip = true
# attaching Network Security Groups - NSGs
nsg_ids = [oci_core_network_security_group.appserver.id]
}
# CloudInit metadata - including my public SSH key
metadata = {
ssh_authorized_keys = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCZ4bqPK+Mwiy+HLabqJxCMcQ/hY7IPx/oEQZWZq7krJxkLLUI6lkw44XRCutgww1q91yTdsSUNDZ9jFz9LihGTEIu7CGKkzmoGtAWHwq2W38GuA5Fqr0r2vPH1qwkTiuN+VmeKJ+qzOfm9Lh1zjD5e4XndjxiaOrw0wI19zpWlUnEqTTjgs7jz9X7JrHRaimzS3PEF5GGrT6oy6gWoKiWSjrQA2VGWI0yNQpUBFTYWsKSHtR+oJHf2rM3LLyzKcEXnlUUJrjDqNsbbcCN26vIdCGIQTvSjyLj6SY+wYWJEHCgPSbBRUcCEcwp+bATDQNm9L4tI7ZON5ZiJstL/sqIBBXmqruh7nSkWAYQK/H6PUTMQrUU5iK8fSWgS+CB8CiaA8zos9mdMfs1+9UKz0vMDV7PFsb7euunS+DiS5iyz6dAz/uFexDbQXPCbx9Vs7TbBW2iPtYc6SNMqFJD3E7sb1SIHhcpUvdLdctLKfnl6cvTz2o2VfHQLod+mtOq845s= ilmars_public_key"
}
}