Terraform VCN for Oracle Cloud Infrastructure

The Terraform VCN module for Oracle Cloud Infrastructure provides a reusable Terraform module that provisions a minimal VCN on OCI.

It creates the following resources:

  • A VCN with one or more customizable CIDR blocks
  • An optional Internet Gateway with a corresponding route table
  • An optional NAT Gateway with a corresponding route table
  • An optional Service Gateway
  • One or more optional Local Peering Gateways in requestor or acceptor mode, and possibilities to associate a Route Table

It also controls the Default Security List, with a Lockdown mode that can be enabled or disabled.

Custom route rules can be added to the two route tables created by the module.

This module is primarily meant to be reusable to create more advanced infrastructure on OCI either manually in the OCI Console or by extending the Terraform code.

Documentation

Changelog

View the CHANGELOG.

Acknowledgement

Code derived and adapted from Terraform OCI Examples and Hashicorp's Terraform 0.12 examples

Contributors

Folks who contributed with explanations, code, feedback, ideas, testing etc.

Learn how to contribute.

License

Copyright (c) 2019, 2023 Oracle and/or its associates.

Licensed under the Universal Permissive License 1.0 as shown at https://oss.oracle.com/licenses/upl.

Pre-requisites

  1. Local development tools: Git, Terraform, a terminal.
  2. Understanding of Oracle Cloud Infrastructure (OCI) and its services, in particular the Virtual Cloud Networking (VCN) service.

Generate and upload your OCI API keys

Follow the documentation for generating and uploading your API keys.

Note the key fingerprint.

Create an OCI compartment

Follow the documentation for creating a compartment.

Obtain the necessary OCIDs

The following OCIDs are required:

  1. Compartment OCID
  2. Tenancy OCID
  3. User OCID

Follow the documentation for obtaining the tenancy and user OCIDs.

To obtain the compartment OCID:

  1. Navigate to Identity > Compartments
  2. Click on your Compartment
  3. Locate OCID on the page and click on Copy

Configuring Policies

  1. Create a group (e.g. mygroup) and add a user to the group.

  2. Create a policy:

Allow group mygroup to manage virtual-network-family in compartment id ocid1.compartment.oc1..aaa

User Guide

Creating a VCN

Assumptions

  1. You have setup the required keys
  2. You know the required OCIDs
  3. You have the necessary permissions

Pre-requisites

  1. Git is installed
  2. SSH client is installed
  3. Terraform 1.3.0 or greater is installed

Instructions

Provisioning using this git repo

  1. Clone the repo:
git clone https://github.com/oracle-terraform-modules/terraform-oci-vcn.git tfvcn

cd tfvcn

cp terraform.tfvars.example terraform.tfvars
  1. Create a provider.tf file and add the following:
provider "oci" {
  fingerprint          = var.api_fingerprint
  private_key_path     = var.api_private_key_path
  region               = var.region
  tenancy_ocid         = var.tenancy_id
  user_ocid            = var.user_id
}

# provider identity parameters
variable "api_fingerprint" {
  description = "fingerprint of oci api private key"
  type        = string
}

variable "api_private_key_path" {
  description = "path to oci api private key used"
  type        = string
}

variable "tenancy_id" {
  description = "tenancy id where to create the sources"
  type        = string
}

variable "user_id" {
  description = "id of user that terraform will use to create the resources"
  type        = string
}
  1. Set mandatory provider parameters in terraform.tfvars:
  • api_fingerprint
  • api_private_key_path
  • region
  • tenancy_id
  • user_id
  1. Override other parameters in terraform.tfvars:
  • compartment_id
  • label_prefix
  • vcn_name
  1. Optional parameters to override:
  • create_internet_gateway
  • create_nat_gateway
  • create_service_gateway
  • freeform_tags
  • attached_drg_id
  • vcn_dns_label
  1. Run Terraform:
terraform init
terraform plan
terraform apply

Reusing as a Terraform module

You can also use the method below to reuse this in your own module.

  1. Create a variable.tf file in your root project and add the contents of the variables.tf from the example.

  2. Create a provider.tf file in your root directory and add the following:

provider "oci" {
  fingerprint          = var.api_fingerprint
  private_key_path     = var.api_private_key_path
  region               = var.region
  tenancy_ocid         = var.tenancy_id
  user_ocid            = var.user_id
}
  1. Create a main.tf file and add the following:
module "vcn" {
  
  source = "github.com/oracle-terraform-modules/terraform-oci-vcn"
  # to use the terraform registry version comment the previous line and uncomment the 2 lines below
  # source  = "oracle-terraform-modules/vcn/oci"
  # version = "specify_version_number"

  # general oci parameters
  compartment_id = var.compartment_id
  label_prefix   = var.label_prefix
  freeform_tags  = var.freeform_tags
  defined_tags = var.defined_tags

  # vcn parameters
  create_internet_gateway  = var.create_internet_gateway  # boolean: true or false
  lockdown_default_seclist = var.lockdown_default_seclist # boolean: true or false
  create_nat_gateway       = var.create_nat_gateway       # boolean: true or false
  create_service_gateway   = var.create_service_gateway   # boolean: true or false
  enable_ipv6              = var.enable_ipv6
  vcn_cidrs                = var.vcn_cidrs # List of IPv4 CIDRs
  vcn_dns_label            = var.vcn_dns_label
  vcn_name                 = var.vcn_name

  # gateways parameters
  internet_gateway_display_name = var.internet_gateway_display_name
  nat_gateway_display_name      = var.nat_gateway_display_name
  service_gateway_display_name  = var.service_gateway_display_name
  attached_drg_id               = var.attached_drg_id
}
  1. In order to obtain and reuse the VCN resources created, export the OCIDs in outputs.tf:
# Outputs

output "module_vcn_ids" {
  description = "vcn and gateways information"
  value = {
    internet_gateway_id          = module.vcn.internet_gateway_id
    internet_gateway_route_id    = module.vcn.ig_route_id
    nat_gateway_id               = module.vcn.nat_gateway_id
    nat_gateway_route_id         = module.vcn.nat_route_id
    service_gateway_id           = module.vcn.service_gateway_id
    vcn_dns_label                = module.vcn.vcn_all_attributes.dns_label
    vcn_default_security_list_id = module.vcn.vcn_all_attributes.default_security_list_id
    vcn_default_route_table_id   = module.vcn.vcn_all_attributes.default_route_table_id
    vcn_default_dhcp_options_id  = module.vcn.vcn_all_attributes.default_dhcp_options_id
    vcn_id                       = module.vcn.vcn_id
  }
}
  1. Copy terraform.tfvars.example to terraform.tfvars
cp terraform.tfvars.example terraform.tfvars
  1. Set the mandatory provider parameters:
  • api_fingerprint
  • api_private_key_path
  • region
  • tenancy_id
  • user_id
  1. Override other parameters in terraform.tfvars:
  • compartment_id
  • label_prefix
  • vcn_name
  1. Optional parameters to override:
  • attached_drg_id
  • create_internet_gateway
  • create_nat_gateway
  • create_service_gateway
  • freeform_tags
  • defined_tags
  • vcn_dns_label
  1. Run Terraform:
terraform init
terraform plan
terraform apply

VCN Gateways

Local Peering Gateways

Local Peering Gateways are used to establish a single peering relationship between two VCNs. For more information about how Local Peering works on OCI, see Important Local Peering concepts and Transit Routing.

The VCN module allows you to declare several LPG using the module's local_peering_gateways variable Input:

  • each key of local_peering_gateways is an LPG.
  • the key is the LPG's display name.
  • you can optionally declare a route_table_id to be attached to the LPG. This is useful on to create a Hub VCN for Transit Routing.
  • you can optionally declare a peer_id, so your module will act as a requestor and trigger the peering processus (to be used either in the hub vcn module or the spoke vcn module, but not both).

Using the module outputs to retrieve an LPG OCID

You can dynamically retrieve the OCID of an LPG created with this module using the module's lpg_all_attributes output: module.*<module_name>*.lpg_all_attributes["*<lpg_key>*"]["id"].

This is particularly useful when both VCNs to be peered are in the same Terraform configuration and created using this module.

Generic values for route_table_id or peer_id

If you need to attach a Routing Table or peer with an LPG created outside of the VCN module, you can simply provide the resource OCID using a valid Terraform method (any {uri-tf-namedvalues}[Named Value]).

Examples

This is an example that shows how to declare LPGs in three different ways:

module "vcn_hub" {
  ...
  local_peering_gateways = {
    to_spoke1 = {
      // this LPG will have a Route Table associated with it
      route_table_id = oci_core_route_table.VTR_spokes.id
    }
    to_spoke2 = {
      // this LPG will have a Route Table associated with it and the peering connection will be established (requestor mode)
      route_table_id = oci_core_route_table.VTR_spokes.id
      peer_id = module.vcn_spoke2.lpg_all_attributes["to_hub"]["id"]
    }
    to_spoke3 = {}
      // this LPG will be created without any Route Table associated, and ready to be peered (acceptor mode)
  }
}

See the hub-and-spoke example that for more details on how to use this feature.

Configuring routing rules

When you create an Internet or a NAT gateway, the terraform-oci-vcn module automatically creates a dedicated route table for each gateway:

  • <label_prefix>-internet-route route table is created if create_internet_gateway = true
  • <label_prefix>-nat-route route table is created if create_nat_gateway = true

These automatically created route tables comes with automatic rules, that cannot be controlled by the module user.

internet-route route table

internet-route is meant to be attached to public subnets you provision. It comes with one automatic/non-editable rule that redirects all unknown destination to the Internet Gateway created by this module: 0.0.0.0/0 --> Internet Gateway.

nat-route route table

nat-route table is meant to be attached to private subnets you provision. It comes with one automatic/non-editable rule that redirects all unknown destination to the NAT Gateway created by this module: 0.0.0.0/0 --> NAT Gateway.

If a Service Gateway is also created by the module with create_service_gateway = true, a second rule is added to redirect all Oracle Network Services traffic to the Service Gateway created by this module: All <REGION> services in OSN --> Service Gateway

Custom routes

terraform-oci-vcn module have two optional Input Variables to inject user-defined route rules into internet-route and nat-route route tables using respectively:

  • internet_gateway_route_rules defined as a list(map(string)) with the following expected schema:
variable "internet_gateway_route_rules" {
  description = "(Updatable) List of routing rules to add to Internet Gateway Routing Table"
  type = list(object({
    destination       = string # required
    destination_type  = string # required
    network_entity_id = string # required
    description       = string # optional
  }))
  default = null
}
  • nat_gateway_route_rules defined as a list(map(string)) with the following expected schema:
variable "nat_gateway_route_rules" {
  description = "(Updatable) List of routing rules to add to NAT Gateway Routing Table"
  type = list(object({
    destination       = string # required
    destination_type  = string # required
    network_entity_id = string # required
    description       = string # optional
  }))
  default = null
}

They share the same schema but each Input Variable controls the associated route table:

  • destination accept string value and represent the CIDR that will be affected by the rule,
  • destination_type accept string value, with CIDR_BLOCK or SERVICE_CIDR_BLOCK as valid values,
  • network_entity_id accept string value and represent the gateway to be the target of the rule,
  • description accept arbitrary string value and give context about the goal of the rule.

Special values for network_entity_id

For routing rules targeting a gateway created by the module, network_entity_id accepts some special strings to automatically retrieve the gateway OCID.

  • internet_gateway_route_rules and nat_gateway_route_rules recognise the "drg" string and resolve it to the Dynamic Routing Gateway(DRG) OCID attached to the module (if available),
  • internet_gateway_route_rules recognise the "internet_gateway" string and resolve it to the Internet Gateway OCID created by the module,
  • nat_gateway_route_rules recognise the "nat_gateway" string and resolve it to the NAT Gateway OCID created by the module.

Generic values for network_entity_id

If you need to create a routing rule with a target gateway created outside of the module, you can simply provide the resource OCID using a valid Terraform method (any named value).

Examples

For example configuration using this option, see custom route rules.

Using Resource Manager

git clone https://github.com/oracle-terraform-modules/terraform-oci-vcn.git
zip terraform-oci-vcn.zip *.tf schema.yaml -x main.tf
  1. Create Stack

  2. Upload zip file: Upload zip file

  3. Configure variables as per your needs: Upload zip file

  4. Check the relevant boxes if you need gateways: Upload zip file

  5. Review your stack: Upload zip file

  6. Run Terraform plan and apply: Upload zip file

  7. Check the logs: Upload zip file

Terraform Options

Provider

ParameterDescriptionTypeDefault
regionRegion where to provision the vcn. List of regions. Required.string

General OCI

ParameterDescriptionTypeDefault
compartment_idCompartment id where the VCN Cluster will be provisioned. Required.string
label_prefixa string to be prepended to the name of resources. Required.stringnone
freeform_tagssimple key-value pairs to tag the resources created specified in the form of a mapmap(any)freeform_tags = { environment = "dev" }
defined_tagspredefined and scoped to a namespace to tag the resources created using defined tags.map(string)null

VCN

ParameterDescriptionTypeDefault
attached_drg_idDRG OCID to be attached to the VCN.string
create_internet_gatewayWhether to create an Internet Gateway.boolfalse
create_nat_gatewayWhether to create an NAT gateway.boolfalse
create_service_gatewayWhether to create a service gateway to use Oracle Services.boolfalse
enable_ipv6(Updatable) Whether IPv6 is enabled for the VCN. If enabled, Oracle will assign the VCN a IPv6 /56 CIDR block.boolfalse
internet_gateway_display_name(Updatable) Name of Internet Gateway. Does not have to be unique.stringinternet-gateway
internet_gateway_route_rules(Updatable) List of routing rules to add to Internet Gateway Route Table.list(map(string))null
local_peering_gatewaysMap of Local Peering Gateways to attach to the VCNmap(any)null
lockdown_default_seclistWhether to remove all default security rules from the VCN Default Security Listbooltrue
nat_gateway_display_name(Updatable) Name of NAT Gateway. It does not have to be unique.stringnat-gateway
nat_gateway_public_ip_idOCID of reserved IP address for NAT gateway. If default value "none" is used, then a public IP address is selected from Oracle’s public IP pool.stringnone
nat_gateway_route_rules(Updatable) List of routing rules to add to NAT Gateway Route Tablelist(map(string))null
service_gateway_display_name(Updatable) Name of Service Gateway. Does not have to be unique.stringservice-gateway
vcn_cidrs(Updatable) The list of IPv4 CIDR blocks the VCN will use. The CIDR block specified for the VCN must not overlap with the CIDR block of another network.string["10.0.0.0/16"]
vcn_dns_label(Optional)A DNS label for the VCN, used in conjunction with the VNIC’s hostname and subnet’s DNS label to form a fully qualified domain name (FQDN) for each VNIC within this subnet. DNS resolution for hostnames in the VCN is disabled if null.stringvcnmodule
vcn_name(Optional)(Updatable) The name of the VCN that will be appended to the label_prefix.stringvcn

Subnets

ParameterDescriptionTypeDefault
subnetsSubnets to be created in the VCNany{}