resource "oci_core_instance" "relay" { availability_domain = data.oci_identity_availability_domains.available.availability_domains[var.availability_domain_index].name compartment_id = local.compartment_id display_name = "oci-l4-relay" shape = var.shape freeform_tags = var.freeform_tags defined_tags = { "${oci_identity_tag_namespace.relay.name}.${oci_identity_tag.address_list_reader.name}" = "enabled" "${oci_identity_tag_namespace.relay.name}.${oci_identity_tag.instance_principal.name}" = "enabled" } agent_config { are_all_plugins_disabled = false is_management_disabled = false is_monitoring_disabled = false plugins_config { desired_state = "ENABLED" name = "Compute Instance Run Command" } } shape_config { ocpus = var.ocpus memory_in_gbs = var.memory_in_gbs } create_vnic_details { assign_public_ip = false display_name = "oci-l4-relay" nsg_ids = [oci_core_network_security_group.relay.id] subnet_id = oci_core_subnet.relay.id } source_details { boot_volume_size_in_gbs = 50 source_id = local.relay_image_ocid source_type = "image" } metadata = { user_data = base64encode(templatefile("${path.module}/cloud-init.yaml.tftpl", { gateway_relay_address = var.gateway_relay_address log_ingest_hostname = var.log_ingest_hostname smtp_evidence_config_json = jsonencode({ conntrack_emission_burst = var.relay_conntrack_emission_burst conntrack_emission_rate_per_second = var.relay_conntrack_emission_rate_per_second conntrack_event_buffer = var.relay_conntrack_event_buffer conntrack_sample_denominator = var.relay_conntrack_sample_denominator conntrack_services = concat([ { name = "web" ports = [80, 443] target_address = var.gateway_relay_address } ], var.mail_relay_enabled ? [ { name = "smtp" ports = [25] target_address = local.home_tunnel_address }, { name = "authenticated_mail" ports = [465, 993] target_address = local.home_tunnel_address } ] : []) maximum_records = var.smtp_deny_maximum_addresses metrics_listen_address = "${split("/", var.relay_tunnel_address)[0]}:${var.relay_metrics_port}" observation_window_seconds = var.smtp_deny_maximum_observation_window_seconds snapshot_interval_seconds = var.smtp_evidence_snapshot_interval_seconds }) config_json = jsonencode(merge({ admission = { bucket = oci_objectstorage_bucket.address_lists.name maximum_addresses = var.web_allow_maximum_addresses minimum_addresses = var.web_allow_minimum_addresses minimum_intervals = var.web_allow_minimum_intervals namespace = data.oci_objectstorage_namespace.relay.namespace object = var.web_allow_bundle_object } admission_helper = "/usr/local/libexec/oci-l4-relay-admission" gateway_relay_address = var.gateway_relay_address home_wireguard_public_key = local.home_wireguard_public_key log_ingest_hostname = var.log_ingest_hostname log_ingest_secret_ocid = oci_vault_secret.log_ingest.id monitoring_source_ipv4 = var.monitoring_source_ipv4 public_key_secret_ocid = oci_vault_secret.wireguard_public_key.id rate_limit_mbit = var.relay_rate_limit_mbit relay_http_quarantine_enabled = var.relay_http_quarantine_enabled relay_http_quarantine_minutes = var.relay_http_quarantine_minutes relay_https_recent_minutes = var.relay_https_recent_minutes relay_metrics_port = var.relay_metrics_port relay_auth_packet_aggregate_burst = var.relay_auth_packet_aggregate_burst relay_auth_packet_aggregate_rate_per_second = var.relay_auth_packet_aggregate_rate_per_second relay_auth_syn_aggregate_burst = var.relay_auth_syn_aggregate_burst relay_auth_syn_aggregate_rate_per_second = var.relay_auth_syn_aggregate_rate_per_second relay_auth_syn_burst = var.relay_auth_syn_burst relay_auth_syn_rate_per_minute = var.relay_auth_syn_rate_per_minute relay_smtp_packet_aggregate_burst = var.relay_smtp_packet_aggregate_burst relay_smtp_packet_aggregate_rate_per_second = var.relay_smtp_packet_aggregate_rate_per_second relay_smtp_syn_aggregate_burst = var.relay_smtp_syn_aggregate_burst relay_smtp_syn_aggregate_rate_per_second = var.relay_smtp_syn_aggregate_rate_per_second relay_smtp_syn_burst = var.relay_smtp_syn_burst relay_smtp_syn_rate_per_minute = var.relay_smtp_syn_rate_per_minute relay_tracker_max_sources = var.relay_tracker_max_sources relay_tunnel_address = var.relay_tunnel_address relay_tunnel_mtu = var.relay_tunnel_mtu relay_unmatched_http_burst = var.relay_unmatched_http_burst relay_unmatched_http_rate_per_hour = var.relay_unmatched_http_rate_per_hour relay_web_packet_aggregate_burst = var.relay_web_packet_aggregate_burst relay_web_packet_aggregate_rate_per_second = var.relay_web_packet_aggregate_rate_per_second relay_web_syn_aggregate_burst = var.relay_web_syn_aggregate_burst relay_web_syn_aggregate_rate_per_second = var.relay_web_syn_aggregate_rate_per_second relay_web_syn_burst = var.relay_web_syn_burst relay_web_syn_rate_per_minute = var.relay_web_syn_rate_per_minute wireguard_listen_port = var.wireguard_listen_port wireguard_seed_secret_ocid = oci_vault_secret.wireguard_seed.id }, jsondecode(var.mail_relay_enabled ? jsonencode({ mail_relay_address = local.home_tunnel_address smtp_deny = { bucket = oci_objectstorage_bucket.address_lists.name maximum_addresses = var.smtp_deny_maximum_addresses maximum_intervals = var.smtp_deny_maximum_intervals maximum_lifetime_seconds = var.smtp_deny_maximum_lifetime_seconds maximum_observation_window_seconds = var.smtp_deny_maximum_observation_window_seconds minimum_observations = var.smtp_deny_minimum_observations namespace = data.oci_objectstorage_namespace.relay.namespace object = var.smtp_deny_bundle_object } smtp_deny_helper = "/usr/local/libexec/oci-l4-relay-smtp-deny" }) : "{}"))) })) } preserve_boot_volume = false lifecycle { replace_triggered_by = [terraform_data.relay_instance_generation] ignore_changes = [defined_tags["Oracle-Tags.CreatedBy"], defined_tags["Oracle-Tags.CreatedOn"]] } depends_on = [oci_identity_policy.relay] } data "oci_core_vnic_attachments" "relay" { compartment_id = local.compartment_id instance_id = oci_core_instance.relay.id } data "oci_core_private_ips" "relay" { vnic_id = data.oci_core_vnic_attachments.relay.vnic_attachments[0].vnic_id } resource "oci_core_public_ip" "relay" { compartment_id = local.compartment_id display_name = "oci-l4-relay" lifetime = "RESERVED" private_ip_id = one([for address in data.oci_core_private_ips.relay.private_ips : address.id if address.is_primary]) freeform_tags = var.freeform_tags lifecycle { prevent_destroy = true } } resource "oci_identity_dynamic_group" "relay" { compartment_id = local.tenancy_ocid name = "oci-l4-relay" description = "OCI L4 relay instance principal" matching_rule = "ALL {instance.compartment.id = '${local.compartment_id}', tag.${oci_identity_tag_namespace.relay.name}.${oci_identity_tag.instance_principal.name}.value = 'enabled'}" } resource "oci_identity_policy" "relay" { compartment_id = local.tenancy_ocid name = "oci-l4-relay" description = "Allow relay key derivation and public-key publication" statements = [ "Allow dynamic-group ${oci_identity_dynamic_group.relay.name} to read secret-bundles in compartment id ${local.compartment_id} where target.secret.id = '${oci_vault_secret.wireguard_seed.id}'", "Allow dynamic-group ${oci_identity_dynamic_group.relay.name} to read secret-bundles in compartment id ${local.compartment_id} where target.secret.id = '${oci_vault_secret.wireguard_public_key.id}'", "Allow dynamic-group ${oci_identity_dynamic_group.relay.name} to read secret-bundles in compartment id ${local.compartment_id} where target.secret.id = '${oci_vault_secret.log_ingest.id}'", "Allow dynamic-group ${oci_identity_dynamic_group.relay.name} to {SECRET_UPDATE} in compartment id ${local.compartment_id} where target.secret.id = '${oci_vault_secret.wireguard_public_key.id}'", "Allow dynamic-group ${oci_identity_dynamic_group.relay.name} to use instance-agent-command-execution-family in compartment id ${local.compartment_id} where request.instance.id = target.instance.id", ] } resource "terraform_data" "relay_instance_generation" { triggers_replace = [ "relay", filesha256("${path.module}/cloud-init.yaml.tftpl"), jsonencode(merge({ web_allow_bundle_object = var.web_allow_bundle_object web_allow_maximum_addresses = var.web_allow_maximum_addresses web_allow_minimum_addresses = var.web_allow_minimum_addresses web_allow_minimum_intervals = var.web_allow_minimum_intervals gateway_relay_address = var.gateway_relay_address log_ingest_hostname = var.log_ingest_hostname relay_image_ocid = local.relay_image_ocid monitoring_source_ipv4 = var.monitoring_source_ipv4 relay_http_quarantine_enabled = var.relay_http_quarantine_enabled relay_http_quarantine_minutes = var.relay_http_quarantine_minutes relay_https_recent_minutes = var.relay_https_recent_minutes relay_auth_packet_aggregate_burst = var.relay_auth_packet_aggregate_burst relay_auth_packet_aggregate_rate_per_second = var.relay_auth_packet_aggregate_rate_per_second relay_auth_syn_aggregate_burst = var.relay_auth_syn_aggregate_burst relay_auth_syn_aggregate_rate_per_second = var.relay_auth_syn_aggregate_rate_per_second relay_auth_syn_burst = var.relay_auth_syn_burst relay_auth_syn_rate_per_minute = var.relay_auth_syn_rate_per_minute relay_rate_limit_mbit = var.relay_rate_limit_mbit relay_smtp_packet_aggregate_burst = var.relay_smtp_packet_aggregate_burst relay_smtp_packet_aggregate_rate_per_second = var.relay_smtp_packet_aggregate_rate_per_second relay_smtp_syn_aggregate_burst = var.relay_smtp_syn_aggregate_burst relay_smtp_syn_aggregate_rate_per_second = var.relay_smtp_syn_aggregate_rate_per_second relay_smtp_syn_burst = var.relay_smtp_syn_burst relay_smtp_syn_rate_per_minute = var.relay_smtp_syn_rate_per_minute relay_web_packet_aggregate_burst = var.relay_web_packet_aggregate_burst relay_web_packet_aggregate_rate_per_second = var.relay_web_packet_aggregate_rate_per_second relay_web_syn_aggregate_burst = var.relay_web_syn_aggregate_burst relay_web_syn_aggregate_rate_per_second = var.relay_web_syn_aggregate_rate_per_second relay_tracker_max_sources = var.relay_tracker_max_sources relay_tunnel_mtu = var.relay_tunnel_mtu relay_tunnel_address = var.relay_tunnel_address relay_metrics_port = var.relay_metrics_port relay_conntrack_emission_burst = var.relay_conntrack_emission_burst relay_conntrack_emission_rate_per_second = var.relay_conntrack_emission_rate_per_second relay_conntrack_event_buffer = var.relay_conntrack_event_buffer relay_conntrack_sample_denominator = var.relay_conntrack_sample_denominator relay_unmatched_http_burst = var.relay_unmatched_http_burst relay_unmatched_http_rate_per_hour = var.relay_unmatched_http_rate_per_hour relay_web_syn_burst = var.relay_web_syn_burst relay_web_syn_rate_per_minute = var.relay_web_syn_rate_per_minute wireguard_listen_port = var.wireguard_listen_port }, jsondecode(var.mail_relay_enabled ? jsonencode({ mail_relay_address = local.home_tunnel_address smtp_deny_bundle_object = var.smtp_deny_bundle_object smtp_deny_maximum_addresses = var.smtp_deny_maximum_addresses smtp_deny_maximum_intervals = var.smtp_deny_maximum_intervals smtp_deny_maximum_lifetime_seconds = var.smtp_deny_maximum_lifetime_seconds smtp_deny_maximum_observation_window_seconds = var.smtp_deny_maximum_observation_window_seconds smtp_deny_minimum_observations = var.smtp_deny_minimum_observations smtp_evidence_snapshot_interval_seconds = var.smtp_evidence_snapshot_interval_seconds }) : "{}"))) ] } resource "oci_identity_tag_namespace" "relay" { compartment_id = local.tenancy_ocid name = "quorate_relay" description = "Authorization boundary for OCI L4 relay resources" is_retired = false } resource "oci_identity_tag" "instance_principal" { tag_namespace_id = oci_identity_tag_namespace.relay.id name = "instance_principal" description = "Admits an instance to the OCI L4 relay dynamic group" is_retired = false } resource "oci_identity_tag" "address_list_reader" { tag_namespace_id = oci_identity_tag_namespace.relay.id name = "address_list_reader" description = "Admits an instance to read validated relay address-list objects" is_retired = false }