Skip to main content
Пример создания инфраструктуры с облачным файрволом
Last update:

Пример создания инфраструктуры с облачным файрволом

Это пример создания инфраструктуры, которая состоит:

  • из приватной подсети 192.168.199.0/24, в которой находится облачный файрвол, назначенный на порт облачного роутера 192.168.199.1;
  • приватной подсети 10.20.30.0/24, не закрытой файрволом;
  • разрешающего правила на файрволе для исходящего трафика из подсети 192.168.199.0/24 в 10.20.30.0/24;
  • облачного сервера в подсети 192.168.199.0/24;
  • облачного сервера в подсети 10.20.30.0/24.

Мы рекомендуем создавать ресурсы по порядку. Если вы единовременно создаете все ресурсы, которые описаны в конфигурационном файле, может возникнуть ошибка — Terraform создает ресурсы независимо от порядка, в котором они перечислены в файле.


  1. Опционально: настройте провайдеры.
  2. Создайте приватные сети и подсети.
  3. Создайте облачный роутер, подключенный к внешней сети.
  4. Создайте облачный файрвол.
  5. Создайте облачный сервер в приватной подсети, закрытой файрволом.
  6. Создать облачный сервер в приватной подсети, не закрытой файрволом.

Конфигурационные файлы

Пример файла для настройки провайдеров
terraform {
required_providers {
selectel = {
source = "selectel/selectel"
version = "5.4.0"
}
openstack = {
source = "terraform-provider-openstack/openstack"
version = "2.1.0"
}
}
}

provider "selectel" {
domain_name = "123456"
username = "user"
password = "password"
}

resource "selectel_vpc_project_v2" "project_1" {
name = "project"
}

resource "selectel_iam_serviceuser_v1" "serviceuser_1" {
name = "username"
password = "password"
role {
role_name = "member"
scope = "project"
project_id = selectel_vpc_project_v2.project_1.id
}
}

provider "openstack" {
auth_url = "https://cloud.api.selcloud.ru/identity/v3"
domain_name = "123456"
tenant_id = selectel_vpc_project_v2.project_1.id
user_name = selectel_iam_serviceuser_v1.serviceuser_1.name
password = selectel_iam_serviceuser_v1.serviceuser_1.password
region = "ru-9"
}
Пример файла для создания инфрастуктуры с облачным файрволом
resource "openstack_networking_network_v2" "protected_network_1" {
name = "protected-network"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "protected_subnet_1" {
name = "protected-subnet"
network_id = openstack_networking_network_v2.protected_network_1.id
cidr = "192.168.199.0/24"
}

resource "openstack_networking_network_v2" "unprotected_network_1" {
name = "unprotected-network"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "unprotected_subnet_1" {
name = "unprotected-subnet"
network_id = openstack_networking_network_v2.unprotected_network_1.id
cidr = "10.20.30.0/24"
}

data "openstack_networking_network_v2" "external_network_1" {
external = true
}

resource "openstack_networking_router_v2" "router_1" {
name = "router"
admin_state_up = true
external_network_id = data.openstack_networking_network_v2.external_network_1.id
}

resource "openstack_networking_router_interface_v2" "protected_router_interface_1" {
router_id = openstack_networking_router_v2.router_1.id
subnet_id = openstack_networking_subnet_v2.protected_subnet_1.id
}

resource "openstack_networking_router_interface_v2" "unprotected_router_interface_1" {
router_id = openstack_networking_router_v2.router_1.id
subnet_id = openstack_networking_subnet_v2.unprotected_subnet_1.id
}

resource "openstack_fw_rule_v2" "rule_1" {
name = "allow-protected-network-traffic-rule"
action = "allow"
protocol = "icmp"
}

resource "openstack_fw_rule_v2" "rule_2" {
name = "allow-protected-network-traffic-rule"
action = "allow"
protocol = "tcp"
source_ip_address = "192.168.199.0/24"
destination_ip_address = "10.20.30.0/24"
}

resource "openstack_fw_policy_v2" "firewall_policy_1" {
name = "ingress-firewall-policy"
audited = true
rules = [
openstack_fw_rule_v2.rule_1.id,
]
}

resource "openstack_fw_policy_v2" "firewall_policy_2" {
name = "egress-firewall-policy"
audited = true
rules = [
openstack_fw_rule_v2.rule_2.id,
]
}

resource "openstack_fw_group_v2" "group_1" {
name = "group"
admin_state_up = true
ingress_firewall_policy_id = openstack_fw_policy_v2.firewall_policy_1.id
egress_firewall_policy_id = openstack_fw_policy_v2.firewall_policy_2.id
ports = [
openstack_networking_router_interface_v2.protected_router_interface_1.port_id,
]
}

resource "selectel_vpc_keypair_v2" "keypair_protected_1" {
name = "keypair-protected"
public_key = file("~/.ssh/id_rsa.pub")
user_id = selectel_iam_serviceuser_v1.serviceuser_1.id
}

resource "openstack_networking_port_v2" "port_protected_1" {
name = "port-protected"
network_id = openstack_networking_network_v2.protected_network_1.id

fixed_ip {
subnet_id = openstack_networking_subnet_v2.protected_subnet_1.id
}
}

data "openstack_images_image_v2" "image_protected_1" {
name = "Ubuntu 20.04 LTS 64-bit"
most_recent = true
visibility = "public"
}

resource "openstack_blockstorage_volume_v3" "volume_protected_1" {
name = "boot-volume-for-protected-server"
size = "5"
image_id = data.openstack_images_image_v2.image_protected_1.id
volume_type = "fast.ru-9a"
availability_zone = "ru-9a"
enable_online_resize = true

lifecycle {
ignore_changes = [image_id]
}

}

resource "openstack_compute_instance_v2" "protected_server_1" {
name = "protected-server"
flavor_id = "4011"
key_pair = selectel_vpc_keypair_v2.keypair_protected_1.name
availability_zone = "ru-9a"

network {
port = openstack_networking_port_v2.port_protected_1.id
}

lifecycle {
ignore_changes = [image_id]
}

block_device {
uuid = openstack_blockstorage_volume_v3.volume_protected_1.id
source_type = "volume"
destination_type = "volume"
boot_index = 0
}

vendor_options {
ignore_resize_confirmation = true
}
}

resource "selectel_vpc_keypair_v2" "keypair_unprotected_1" {
name = "keypair-unprotected"
public_key = file("~/.ssh/id_rsa.pub")
user_id = selectel_iam_serviceuser_v1.serviceuser_1.id
}

resource "openstack_networking_port_v2" "port_unprotected_1" {
name = "port-unprotected"
network_id = openstack_networking_network_v2.unprotected_network_1.id

fixed_ip {
subnet_id = openstack_networking_subnet_v2.unprotected_subnet_1.id
}
}

data "openstack_images_image_v2" "image_unprotected_1" {
name = "Ubuntu 20.04 LTS 64-bit"
most_recent = true
visibility = "public"
}

resource "openstack_blockstorage_volume_v3" "volume_unprotected_1" {
name = "boot-volume-for-unprotected-server"
size = "5"
image_id = data.openstack_images_image_v2.image_unprotected_1.id
volume_type = "fast.ru-9a"
availability_zone = "ru-9a"
enable_online_resize = true

lifecycle {
ignore_changes = [image_id]
}

}

resource "openstack_compute_instance_v2" "unprotected_server_1" {
name = "unprotected-server"
flavor_id = "4011"
key_pair = selectel_vpc_keypair_v2.keypair_unprotected_1.name
availability_zone = "ru-9a"

network {
port = openstack_networking_port_v2.port_unprotected_1.id
}

lifecycle {
ignore_changes = [image_id]
}

block_device {
uuid = openstack_blockstorage_volume_v3.volume_unprotected_1.id
source_type = "volume"
destination_type = "volume"
boot_index = 0
}

vendor_options {
ignore_resize_confirmation = true
}
}

1. Опционально: настроить провайдеры

Если вы настроили провайдеры Selectel и OpenStack, пропустите этот шаг.

  1. Убедитесь, что в панели управления вы создали сервисного пользователя с ролями Администратор аккаунта и Администратор пользователей.

  2. Создайте директорию для хранения конфигурационных файлов и отдельный файл с расширением .tf для настройки провайдеров.

  3. В файл для настройки провайдеров добавьте провайдеры Selectel и OpenStack:

    terraform {
    required_providers {
    selectel = {
    source = "selectel/selectel"
    version = "5.4.0"
    }
    openstack = {
    source = "terraform-provider-openstack/openstack"
    version = "2.1.0"
    }
    }
    }

    Здесь version — версии провайдеров. Актуальную версию можно посмотреть в документации Selectel (в Terraform Registry и GitHub) и OpenStack (в Terraform Registry и GitHub).

    Подробнее о продуктах, услугах и сервисах, которыми можно управлять с помощью провайдеров, в инструкции Провайдеры Selectel и OpenStack.

  4. Инициализируйте провайдер Selectel:

    provider "selectel" {
    domain_name = "123456"
    username = "user"
    password = "password"
    }

    Здесь:

    • domain_name — номер аккаунта Selectel. Можно посмотреть в панели управления в правом верхнем углу;
    • username — имя сервисного пользователя с ролями Администратор аккаунта и Администратор пользователей. Можно посмотреть в панели управления: раздел Управление доступомУправление пользователями → вкладка Сервисные пользователи (раздел доступен только Владельцу аккаунта и Администратору пользователей);
    • password — пароль сервисного пользователя. Можно посмотреть при создании пользователя или изменить на новый.
  5. Создайте проект:

    resource "selectel_vpc_project_v2" "project_1" {
    name = "project"
    }

    Посмотрите подробное описание ресурса selectel_vpc_project_v2.

  6. Создайте сервисного пользователя для доступа к проекту и назначьте ему роль Администратор проекта:

    resource "selectel_iam_serviceuser_v1" "serviceuser_1" {
    name = "username"
    password = "password"
    role {
    role_name = "member"
    scope = "project"
    project_id = selectel_vpc_project_v2.project_1.id
    }
    }

    Здесь:

    • username — имя пользователя;
    • password — пароль пользователя. Пароль должен быть не короче восьми символов и содержать латинские буквы разных регистров и цифры;
    • project_id — ID проекта. В панели управления перейдите в раздел Облачная платформа → откройте меню проектов (название текущего проекта) → в строке нужного проекта нажмите .

    Посмотрите подробное описание ресурса selectel_iam_serviceuser_v1.

  7. Инициализируйте провайдер OpenStack:

    provider "openstack" {
    auth_url = "https://cloud.api.selcloud.ru/identity/v3"
    domain_name = "123456"
    tenant_id = selectel_vpc_project_v2.project_1.id
    user_name = selectel_iam_serviceuser_v1.serviceuser_1.name
    password = selectel_iam_serviceuser_v1.serviceuser_1.password
    region = "ru-9"
    }

    Здесь:

    • domain_name — номер аккаунта Selectel. Можно посмотреть в панели управления в правом верхнем углу;
    • regionпул, например ru-9. Все ресурсы будут создаваться в этом пуле. Список доступных пулов можно посмотреть в инструкции Матрицы доступности.
  8. Если одновременно с настройкой провайдеров вы создаете ресурсы, то для ресурсов OpenStack добавьте аргумент depends_on. Например, для ресурса openstack_networking_network_v2:

    resource "openstack_networking_network_v2" "network_1" {
    name = "private-network"
    admin_state_up = "true"

    depends_on = [
    selectel_vpc_project_v2.project_1,
    selectel_iam_serviceuser_v1.serviceuser_1
    ]
    }
  9. Опционально: если вы хотите использовать зеркало, создайте отдельный конфигурационный файл Terraform CLI и добавьте в него блок:

    provider_installation {
    network_mirror {
    url = "https://mirror.selectel.ru/3rd-party/terraform-registry/"
    include = ["registry.terraform.io/*/*"]
    }
    direct {
    exclude = ["registry.terraform.io/*/*"]
    }
    }

    Подробнее о настройках зеркал в инструкции CLI Configuration File документации HashiCorp.

  10. Откройте CLI.

  11. Инициализируйте конфигурацию Terraform в директории:

    terraform init
  12. Проверьте, что конфигурационные файлы составлены без ошибок:

    terraform validate
  13. Отформатируйте конфигурационные файлы:

    terraform fmt
  14. Проверьте, какие ресурсы будут созданы:

    terraform plan
  15. Примените изменения и создайте ресурсы:

    terraform apply
  16. Подтвердите создание — введите yes и нажмите Enter. Созданные ресурсы отобразятся в панели управления.

  17. Если для создания ресурсов оказалось недостаточно квот, увеличьте квоты.

2. Создать приватные сети и подсети

  1. Создайте сеть и подсеть, которые будут закрыты файрволом.
  2. Создайте сеть и подсеть, которые не будут закрыты файрволом.

1. Создать сеть и подсеть, которые будут закрыты файрволом

resource "openstack_networking_network_v2" "protected_network_1" {
name = "protected-network"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "protected_subnet_1" {
name = "protected-subnet"
network_id = openstack_networking_network_v2.protected_network_1.id
cidr = "192.168.199.0/24"
}

Здесь cidr — CIDR приватной подсети, которая будет закрыта файрволом, например 192.168.199.0/24.

Посмотрите подробное описание ресурсов:

2. Создать сеть и подсеть, которые не будут закрыты файрволом

resource "openstack_networking_network_v2" "unprotected_network_1" {
name = "unprotected-network"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "unprotected_subnet_1" {
name = "unprotected-subnet"
network_id = openstack_networking_network_v2.unprotected_network_1.id
cidr = "10.20.30.0/24"
}

Здесь cidr — CIDR приватной подсети, которая будет не закрыта файрволом, например 10.20.30.0/24.

Посмотрите подробное описание ресурсов:

3. Создать облачный роутер, подключенный к внешней сети

Облачный роутер, подключенный к внешней сети, выполняет функцию 1:1 NAT для доступа из приватной сети в интернет через публичный IP-адрес роутера.

data "openstack_networking_network_v2" "external_network_1" {
external = true
}

resource "openstack_networking_router_v2" "router_1" {
name = "router"
admin_state_up = true
external_network_id = data.openstack_networking_network_v2.external_network_1.id
}

resource "openstack_networking_router_interface_v2" "protected_router_interface_1" {
router_id = openstack_networking_router_v2.router_1.id
subnet_id = openstack_networking_subnet_v2.protected_subnet_1.id
}

resource "openstack_networking_router_interface_v2" "unprotected_router_interface_1" {
router_id = openstack_networking_router_v2.router_1.id
subnet_id = openstack_networking_subnet_v2.unprotected_subnet_1.id
}

Посмотрите подробное описание ресурсов:

4. Создать облачный файрвол

  1. Создайте правила.
  2. Создайте политику для входящего трафика.
  3. Создайте политику для исходящего трафика.
  4. Создайте облачный файрвол.

1. Создать правила

У облачного файрвола есть базовое свойство: весь входящий и исходящий трафик, который не разрешен, — запрещен.

Пока вы не добавите разрешающие правила, будут запрещены:

  • трафик, входящий в приватную подсеть, которая подключена к роутеру;
  • трафик, исходящий из этой подсети.
resource "openstack_fw_rule_v2" "rule_1" {
name = "allow-protected-network-traffic-rule"
action = "allow"
protocol = "icmp"
}

resource "openstack_fw_rule_v2" "rule_2" {
name = "allow-protected-network-traffic-rule"
action = "allow"
protocol = "tcp"
source_ip_address = "192.168.199.0/24"
destination_ip_address = "10.20.30.0/24"
}

Посмотрите подробное описание ресурса openstack_fw_rule_v2.

2. Создать политику для входящего трафика

resource "openstack_fw_policy_v2" "firewall_policy_1" {
name = "ingress-firewall-policy"
audited = true
rules = [
openstack_fw_rule_v2.rule_1.id,
]
}

Посмотрите подробное описание ресурса openstack_fw_policy_v2.

3. Создать политику для исходящего трафика

resource "openstack_fw_policy_v2" "firewall_policy_2" {
name = "egress-firewall-policy"
audited = true
rules = [
openstack_fw_rule_v2.rule_2.id,
]
}

Посмотрите подробное описание ресурса openstack_fw_policy_v2.

4. Создать облачный файрвол

resource "openstack_fw_group_v2" "group_1" {
name = "group"
admin_state_up = true
ingress_firewall_policy_id = openstack_fw_policy_v2.firewall_policy_1.id
egress_firewall_policy_id = openstack_fw_policy_v2.firewall_policy_2.id
ports = [
openstack_networking_router_interface_v2.protected_router_interface_1.port_id,
]
}

Посмотрите подробное описание ресурса openstack_fw_group_v2.

5. Создать облачный сервер в приватной подсети, закрытой файрволом

  1. Создайте пару SSH-ключей.
  2. Создайте порт для облачного сервера.
  3. Получите образ.
  4. Создайте загрузочный сетевой диск.
  5. Создайте облачный сервер.

1. Создать пару SSH-ключей

resource "selectel_vpc_keypair_v2" "keypair_protected_1" {
name = "keypair-protected"
public_key = file("~/.ssh/id_rsa.pub")
user_id = selectel_iam_serviceuser_v1.serviceuser_1.id
}

Здесь public_key — путь до публичного SSH-ключа. Если SSH-ключи не созданы, сгенерируйте их.

Посмотрите подробное описание ресурса selectel_vpc_keypair_v2.

2. Создать порт для облачного сервера

resource "openstack_networking_port_v2" "port_protected_1" {
name = "port-protected"
network_id = openstack_networking_network_v2.protected_network_1.id

fixed_ip {
subnet_id = openstack_networking_subnet_v2.protected_subnet_1.id
}
}

Посмотрите подробное описание ресурса openstack_networking_port_v2.

3. Получить образ

data "openstack_images_image_v2" "image_protected_1" {
name = "Ubuntu 20.04 LTS 64-bit"
most_recent = true
visibility = "public"
}

Посмотрите подробное описание источника данных openstack_images_image_v2.

4. Создать загрузочный сетевой диск

resource "openstack_blockstorage_volume_v3" "volume_protected_1" {
name = "boot-volume-for-protected-server"
size = "5"
image_id = data.openstack_images_image_v2.image_protected_1.id
volume_type = "fast.ru-9a"
availability_zone = "ru-9a"
enable_online_resize = true

lifecycle {
ignore_changes = [image_id]
}

}

Здесь:

Посмотрите подробное описание ресурса openstack_blockstorage_volume_v3.

5. Создать облачный сервер

resource "openstack_compute_instance_v2" "protected_server_1" {
name = "protected-server"
flavor_id = "4011"
key_pair = selectel_vpc_keypair_v2.keypair_protected_1.name
availability_zone = "ru-9a"

network {
port = openstack_networking_port_v2.port_protected_1.id
}

lifecycle {
ignore_changes = [image_id]
}

block_device {
uuid = openstack_blockstorage_volume_v3.volume_protected_1.id
source_type = "volume"
destination_type = "volume"
boot_index = 0
}

vendor_options {
ignore_resize_confirmation = true
}
}

Здесь:

Посмотрите подробное описание ресурса openstack_compute_instance_v2.

6. Создать облачный сервер в приватной подсети, не закрытой файрволом

  1. Cоздайте пару SSH-ключей.
  2. Создайте порт для облачного сервера.
  3. Получите образ.
  4. Создайте загрузочный сетевой диск.
  5. Создайте облачный сервер.

1. Cоздать пару SSH-ключей

resource "selectel_vpc_keypair_v2" "keypair_unprotected_1" {
name = "keypair-unprotected"
public_key = file("~/.ssh/id_rsa.pub")
user_id = selectel_iam_serviceuser_v1.serviceuser_1.id
}

Здесь public_key — путь до публичного SSH-ключа. Если SSH-ключи не созданы, сгенерируйте их.

Посмотрите подробное описание ресурса selectel_vpc_keypair_v2.

2. Создать порт для облачного сервера

resource "openstack_networking_port_v2" "port_unprotected_1" {
name = "port-unprotected"
network_id = openstack_networking_network_v2.unprotected_network_1.id

fixed_ip {
subnet_id = openstack_networking_subnet_v2.unprotected_subnet_1.id
}
}

Посмотрите подробное описание ресурса openstack_networking_port_v2.

3. Получить образ

data "openstack_images_image_v2" "image_unprotected_1" {
name = "Ubuntu 20.04 LTS 64-bit"
most_recent = true
visibility = "public"
}

Посмотрите подробное описание источника данных openstack_images_image_v2.

4. Создать загрузочный сетевой диск

resource "openstack_blockstorage_volume_v3" "volume_unprotected_1" {
name = "boot-volume-for-unprotected-server"
size = "5"
image_id = data.openstack_images_image_v2.image_unprotected_1.id
volume_type = "fast.ru-9a"
availability_zone = "ru-9a"
enable_online_resize = true

lifecycle {
ignore_changes = [image_id]
}

}

Здесь:

Посмотрите подробное описание ресурса openstack_blockstorage_volume_v3.

5. Создать облачный сервер

resource "openstack_compute_instance_v2" "unprotected_server_1" {
name = "unprotected-server"
flavor_id = "4011"
key_pair = selectel_vpc_keypair_v2.keypair_unprotected_1.name
availability_zone = "ru-9a"

network {
port = openstack_networking_port_v2.port_unprotected_1.id
}

lifecycle {
ignore_changes = [image_id]
}

block_device {
uuid = openstack_blockstorage_volume_v3.volume_unprotected_1.id
source_type = "volume"
destination_type = "volume"
boot_index = 0
}

vendor_options {
ignore_resize_confirmation = true
}
}

Здесь:

Посмотрите подробное описание ресурса openstack_compute_instance_v2.