Использование Terraform для работы с DNS во FreeIPA

ADM-HQ:

В качестве DNS устанавливаем 10.1.1.10 (SRV-HQ)

  • Устанавливаем Terraform (версия указана в задании, если требуется другая, переходим https://hashicorp-releases.yandexcloud.net/terraform/ и смотрим какие есть версии) из-под  суперпользователя root (su -)

wget https://hashicorp-releases.yandexcloud.net/terraform/1.14.5/terraform_1.14.5_linux_amd64.zip
Разархивируем сразу в нужную папку
unzip terraform_1.14.5_linux_amd64.zip -d /usr/local/bin/
  • Проверяем, что всё установилось и версия соответствует заданию из-под системного пользователя user
[user@adm-hq ~]$ terraform --version
Terraform v1.14.5
on linux_amd64
cat <<EOF > ~/.terraformrc
provider_installation {
    network_mirror {
        url = "https://terraform-mirror.mcs.mail.ru"
        include = ["registry.terraform.io/*/*"]
    }
    direct {
        exclude = ["registry.terraform.io/*/*"]
    }
}

EOF
  • Создаём требуемую директорию для хранения файлов Terraform:
mkdir /home/user/terraform
cd /home/user/terraform
  • Создаём файл terraform.tf и указываем каких провайдеров будем использовать (source указан в задании)
  • Пример с camptocamp/freeipa — https://habr.com/ru/articles/568524/:
cat <<EOF > terraform.tf
terraform {
  required_providers {
    freeipa = {
      source  = "camptocamp/freeipa"
      version = "1.0.0"
    }
  }
}

EOF
  • Создаём файл providers.tf и указываем необходимые для подключения параметры для каждого из провайдеров:
cat <<EOF > providers.tf
provider "freeipa" {
  host     = var.freeipa_host
  username = var.freeipa_username
  password = var.freeipa_username_password
  insecure = true
}

EOF
  • Создаём файл variable.tf и указываем переменные которые будет использовать Terraform:
cat <<EOF > variable.tf
variable "freeipa_host" {
  type        = string
  description = "FreeIPA host"
}

variable "freeipa_username" {
  type        = string
  description = "FreeIPA adm username"
}

variable "freeipa_username_password" {
  type        = string
  description = "FreeIPA adm password"
  sensitive   = true
}

EOF
  • Создаём файл terraform.tfvars и указываем значения переменных которые были указаны в файле variable.tf:
cat <<EOF > terraform.tfvars
freeipa_host              = "srv-hq.au.team"
freeipa_username          = "admin"
freeipa_username_password = "P@ssw0rd"

EOF
  • Инициализируем директорию для работы с Terraform и указанным провайдером:
terraform init
    • должно получиться следующее:

  • Проверить структуру:

  • Реализуем необходимый функционал:
cat <<EOF >> variable.tf
variable "reverse_zones" {
  description = "Reverse zones"
  type        = list(string)
  default = [
    "2.1.10.in-addr.arpa.",
    "0.2.10.in-addr.arpa.",
    "1.2.10.in-addr.arpa.",
    "2.2.10.in-addr.arpa.",
    "16.172.in-addr.arpa."
  ]
}

variable "dns_records" {
  description = "DNS recs"
  type = list(object({
    hostname            = string
    ip_address          = string
    forward_zone        = string
    reverse_zone        = optional(string)
    reverse_zone_record = optional(string)
  }))
  default = [
    {
      hostname            = "fw-hq"
      ip_address          = "10.1.1.1"
      forward_zone        = "au.team."
      reverse_zone        = "1.1.10.in-addr.arpa."
      reverse_zone_record = "1"
    },
    {
      hostname            = "adm-hq"
      ip_address          = "10.1.1.46"
      forward_zone        = "au.team."
      reverse_zone        = "1.1.10.in-addr.arpa."
      reverse_zone_record = "46"
    },
    {
      hostname            = "rtr-br"
      ip_address          = "10.2.0.1"
      forward_zone        = "au.team."
      reverse_zone        = "0.2.10.in-addr.arpa."
      reverse_zone_record = "1"
    },
    {
      hostname            = "fw-br"
      ip_address          = "10.2.0.2"
      forward_zone        = "au.team."
      reverse_zone        = "0.2.10.in-addr.arpa."
      reverse_zone_record = "2"
    },
    {
      hostname            = "srv-br"
      ip_address          = "10.2.1.10"
      forward_zone        = "au.team."
      reverse_zone        = "1.2.10.in-addr.arpa."
      reverse_zone_record = "10"
    },
    {
      hostname            = "rtr-cod"
      ip_address          = "172.16.1.254"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "254.1"
    },
    {
      hostname            = "sw-cod"
      ip_address          = "172.16.1.0"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "0.1"
    },
    {
      hostname            = "ha1-cod"
      ip_address          = "172.16.0.1"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "1.0"
    },
    {
      hostname            = "ha2-cod"
      ip_address          = "172.16.0.2"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "2.0"
    },
    {
      hostname            = "srv1-cod"
      ip_address          = "172.16.1.1"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "1.1"
},
    {
      hostname            = "srv2-cod"
      ip_address          = "172.16.1.2"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "2.1"
    },
    {
      hostname            = "srv3-cod"
      ip_address          = "172.16.1.3"
      forward_zone        = "au.team."
      reverse_zone        = "16.172.in-addr.arpa."
      reverse_zone_record = "3.1"
    }
  ]
}

EOF
  • создаём файл dns.tf и указываем требуемые ресурсы
mcedit dns.tf
resource "freeipa_dns_zone" "reverse" {
  for_each  = toset(var.reverse_zones)
  zone_name = each.value
}

resource "freeipa_dns_record" "a" {
  for_each        = { for r in var.dns_records : r.hostname => r }
  dnszoneidnsname = each.value.forward_zone
  idnsname        = each.value.hostname
  records         = [each.value.ip_address]
  type            = "A"
}

resource "freeipa_dns_record" "ptr" {
  for_each        = { for r in var.dns_records : r.hostname => r }
  dnszoneidnsname = each.value.reverse_zone
  idnsname        = each.value.reverse_zone_record
  records         = ["${each.value.hostname}.${each.value.forward_zone}"]
  type            = "PTR"

  depends_on = [freeipa_dns_zone.reverse]
}
  • Запускаем развёртывание ресурсов:
terraform apply -auto-approve
  • должно получиться следующее:

  • Проверить (terraform state list):

  • При повторном запуске, ошибок и изменений возникать не должно:

  • Переходим на ADM-HQ, проверяем работоспособность:
[user@adm-hq terraform]$ host fw-hq.au.team
fw-hq.au.team has address 10.1.1.1
[user@adm-hq terraform]$ host adm-hq.au.team
adm-hq.au.team has address 10.1.1.46
[user@adm-hq terraform]$ host rtr-br.au.team
rtr-br.au.team has address 10.2.0.1
[user@adm-hq terraform]$ host fw-br.au.team
fw-br.au.team has address 10.2.0.2
[user@adm-hq terraform]$ host srv-br.au.team
srv-br.au.team has address 10.2.1.10
[user@adm-hq terraform]$ host rtr-cod.au.team
rtr-cod.au.team has address 172.16.1.254
[user@adm-hq terraform]$ host sw-cod.au.team
sw-cod.au.team has address 172.16.1.0
[user@adm-hq terraform]$ host ha1-cod.au.team
ha1-cod.au.team has address 172.16.0.1
[user@adm-hq terraform]$ host ha2-cod.au.team
ha2-cod.au.team has address 172.16.0.2
[user@adm-hq terraform]$ host srv1-cod.au.team
srv1-cod.au.team has address 172.16.1.1
[user@adm-hq terraform]$ host srv2-cod.au.team
srv2-cod.au.team has address 172.16.1.2
[user@adm-hq terraform]$ host srv3-cod.au.team
srv3-cod.au.team has address 172.16.1.3
[user@adm-hq terraform]$ host 10.1.1.1
1.1.1.10.in-addr.arpa domain name pointer fw-hq.au.team.
[user@adm-hq terraform]$ host 10.1.1.46
46.1.1.10.in-addr.arpa domain name pointer adm-hq.au.team.
[user@adm-hq terraform]$ host 10.2.0.1
1.0.2.10.in-addr.arpa domain name pointer rtr-br.au.team.
[user@adm-hq terraform]$ host 10.2.0.2
2.0.2.10.in-addr.arpa domain name pointer fw-br.au.team.
[user@adm-hq terraform]$ host 10.2.1.10
10.1.2.10.in-addr.arpa domain name pointer srv-br.au.team.
[user@adm-hq terraform]$ host 172.16.1.254
254.1.16.172.in-addr.arpa domain name pointer rtr-cod.au.team.
[user@adm-hq terraform]$ host 172.16.1.0
0.1.16.172.in-addr.arpa domain name pointer sw-cod.au.team.
[user@adm-hq terraform]$ host 172.16.0.1
1.0.16.172.in-addr.arpa domain name pointer ha1-cod.au.team.
[user@adm-hq terraform]$ host 172.16.0.2
2.0.16.172.in-addr.arpa domain name pointer ha2-cod.au.team.
[user@adm-hq terraform]$ host 172.16.1.1
1.1.16.172.in-addr.arpa domain name pointer srv1-cod.au.team.
[user@adm-hq terraform]$ host 172.16.1.2
2.1.16.172.in-addr.arpa domain name pointer srv2-cod.au.team.
[user@adm-hq terraform]$ host 172.16.1.3
3.1.16.172.in-addr.arpa domain name pointer srv3-cod.au.team.

Если не получается через terraform, то вносим необходимые записи через ВЕБ-интерфейс free-ipa (https://10.1.1.10).

Проверить записи (на 2-х страницах).

Проверить обратные зоны.

Если не получилось через terraform, то надо добавить соответствующие записи.

Создаем отсутствующие обратные зоны для всех подсетей согласно таблицы:

Пример добавления записи, например, srv1-cod: