使用目标套用SQL Server创建SQL防火墙规则

时间:2019-10-21 15:58:33

标签: azure azure-sql-database terraform terraform-provider-azure

此服务器有一个azurerm_sql_server和两个azurerm_sql_firewall_rule

如果我有针对性地terraform apply根据SQL Server创建资源,则会创建SQL Server,但不会创建防火墙规则。

我可以要求防火墙规则始终与SQL Server一起部署吗?

“奖励”:SQL Server在一个模块中,而使用该服务器的数据库在另一个模块中:(

示例代码:

infrastructure / main.tf

resource "azurerm_sql_server" "test" {
    count = var.enable_dbs ? 1 : 0

    location            = azurerm_resource_group.test.location
    resource_group_name = azurerm_resource_group.test.name

    name                         = local.dbs_name
    version                      = "12.0"
    administrator_login          = var.dbs_admin_login
    administrator_login_password = var.dbs_admin_password
}

resource "azurerm_sql_firewall_rule" "allow_azure_services" {
    count = var.enable_dbs ? 1 : 0

    resource_group_name = azurerm_resource_group.test.name

    name                = "AllowAccessToAzureServices"
    server_name         = azurerm_sql_server.test[0].name
    start_ip_address    = "0.0.0.0"
    end_ip_address      = "0.0.0.0"
}

webapp / main.tf

resource "azurerm_sql_database" "test" {
    count = var.enable_db ? 1 : 0

    location            = var.location
    resource_group_name = var.resource_group_name
    server_name         = var.dbs_name

    name                             = var.project_name
    requested_service_objective_name = var.db_sku_size
}

main.tf

module "infrastructure" {
    source = "./infrastructure"

    project_name = "infra"

    enable_dbs         = true
    dbs_admin_login    = "someusername"
    dbs_admin_password = "somepassword"
}

module "my_webapp" {
    source = "./webapp"

    location            = module.infrastructure.location
    resource_group_name = module.infrastructure.resource_group_name
    project_name        = local.project_name

    enable_db                       = true
    dbs_name                        = module.infrastructure.dbs_name
    dbs_admin_login                 = module.infrastructure.dbs_admin_login
    dbs_admin_password              = module.infrastructure.dbs_admin_password
}

如果使用terraform apply应用整个脚本,则一切正常。

但是,如果仅应使用terraform apply -target module.my_webapp来应用module.my_webapp,则防火墙规则会丢失,因为它不是目标,并且目标也不需要它。 但是,该规则是必需的,并且应在每次应用数据库服务器本身时应用。

可能的“解决方案”:

将防火墙规则添加为infrastructure模块的输出:

output "dbs_firewall_rules" {
    value = concat(
        azurerm_sql_firewall_rule.allow_azure_services,
        azurerm_sql_firewall_rule.allow_office_ip
    )
}

然后将此输出添加为webapp模块的输入:

variable "dbs_firewall_rules" {
    description = "DB firewall rules required (used for the database in depends_on)"
    type        = list
}

并在主脚本中连接它:

module "my_webapp" {
    ...
    dbs_firewall_rules = module.infrastructure.dbs_firewall_rules
    ...
}

缺点:列表中只能放入一种资源。这就是为什么我将其从dbs_dependencies重命名为dbs_firewall_rules的原因。

1 个答案:

答案 0 :(得分:0)

如果在与SQL Server相同的tf文件中定义了防火墙规则,则应将其部署,因为已引用服务器,从而正确建立了依赖关系图。我遇到了与特定于SQL Server防火墙规则不兼容的问题。我最终要做的是利用SQL Server资源上的depends_on属性来确保始终创建这些属性。看起来像这样:

resource "azurerm_sql_firewall_rule" "test" {
  name                = "FirewallRule1"
  resource_group_name = "${azurerm_resource_group.test.name}"
  server_name         = "${azurerm_sql_server.test.name}"
  start_ip_address    = "10.0.17.62"
  end_ip_address      = "10.0.17.62"
  depends_on = [azurerm_sql_server.test]
}

resource "azurerm_sql_server" "test" {
  name                         = "mysqlserver"
  resource_group_name          = "${azurerm_resource_group.test.name}"
  location                     = "${azurerm_resource_group.test.location}"
  version                      = "12.0"
  administrator_login          = "mradministrator"
  administrator_login_password = "thisIsDog11"

  tags = {
    environment = "production"
  }  
}

然后只添加您想要的每个规则。如果您要在模块之外执行规则,则应该可以将此参数设为可以传递给它的参数,以强制进行链接。