Skip to content

Terraform Module to deploy a SQL Server, SQL Database, Storage Account in a Resource Group. The module can create an auto-failover group with a private link and geo-redundant database for high availability needs.

License

Notifications You must be signed in to change notification settings

nefischer/terraform-azurerm-mssql-db

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azure SQL Database Terraform Module

Terraform module to create an MS SQL server with initial database, Azure AD login, Firewall rules, geo-replication using auto-failover groups, Private endpoints, and corresponding private DNS zone. It also supports creating a database with a custom SQL script initialization.

A single database is the quickest and simplest deployment option for Azure SQL Database. You manage a single database within a SQL Database server, which is inside an Azure resource group in a specified Azure region with this module.

You can also create a single database in the provisioned or serverless compute tier. A provisioned database is pre-allocated a fixed amount of computing resources, including CPU and memory, and uses one of two purchasing models. This module creates a provisioned database using the vCore-based purchasing model, but you can choose a DTU-based model as well.

Resources supported

Module Usage

# Azurerm provider configuration
provider "azurerm" {
  features {}
}

data "azurerm_log_analytics_workspace" "example" {
  name                = "loganalytics-we-sharedtest2"
  resource_group_name = "rg-shared-westeurope-01"
}

module "mssql-server" {
  source  = "kumarvna/mssql-db/azurerm"
  version = "1.3.0"

  # By default, this module will create a resource group
  # proivde a name to use an existing resource group and set the argument 
  # to `create_resource_group = false` if you want to existing resoruce group. 
  # If you use existing resrouce group location will be the same as existing RG.
  create_resource_group = false
  resource_group_name   = "rg-shared-westeurope-01"
  location              = "westeurope"

  # SQL Server and Database details
  # The valid service objective name for the database include S0, S1, S2, S3, P1, P2, P4, P6, P11 
  sqlserver_name               = "te-sqldbserver01"
  database_name                = "demomssqldb"
  sql_database_edition         = "Standard"
  sqldb_service_objective_name = "S1"

  # SQL server extended auditing policy defaults to `true`. 
  # To turn off set enable_sql_server_extended_auditing_policy to `false`  
  # DB extended auditing policy defaults to `false`. 
  # to tun on set the variable `enable_database_extended_auditing_policy` to `true` 
  # To enable Azure Defender for database set `enable_threat_detection_policy` to true 
  enable_threat_detection_policy = true
  log_retention_days             = 30

  # schedule scan notifications to the subscription administrators
  # Manage Vulnerability Assessment set `enable_vulnerability_assessment` to `true`
  enable_vulnerability_assessment = false
  email_addresses_for_alerts      = ["[email protected]", "[email protected]"]

  # AD administrator for an Azure SQL server
  # Allows you to set a user or group as the AD administrator for an Azure SQL server
  ad_admin_login_name = "[email protected]"

  # (Optional) To enable Azure Monitoring for Azure SQL database including audit logs
  # Log Analytic workspace resource id required
  # (Optional) Specify `storage_account_id` to save monitoring logs to storage. 
  enable_log_monitoring      = true
  log_analytics_workspace_id = data.azurerm_log_analytics_workspace.example.id

  # Firewall Rules to allow azure and external clients and specific Ip address/ranges. 
  enable_firewall_rules = true
  firewall_rules = [
    {
      name             = "access-to-azure"
      start_ip_address = "0.0.0.0"
      end_ip_address   = "0.0.0.0"
    },
    {
      name             = "desktop-ip"
      start_ip_address = "49.204.225.49"
      end_ip_address   = "49.204.225.49"
    }
  ]

  # Adding additional TAG's to your Azure resources
  tags = {
    ProjectName  = "demo-project"
    Env          = "dev"
    Owner        = "[email protected]"
    BusinessUnit = "CORP"
    ServiceClass = "Gold"
  }
}

Default Local Administrator and the Password

This module utilizes sqladmin as a local administrator on SQL servers. If you want to you use custom username, then specify the same by setting up the argument admin_username with a valid user string.

By default, this module generates a strong password for all virtual machines also allows you to change the length of the random password (currently 24) using the random_password_length = 32 variable. If you want to set the custom password, specify the argument admin_password with a valid string.

Resource Group

By default, this module will create a resource group. To use the existing resource group, set the arguments create_resource_group = false and provide a valid resource group name withresource_group_name.

If you are using an existing resource group, then this module uses the same resource group location to create all resources in this module.

Advance usage of module

extended_auditing_policy - Auditing for SQL Database

Auditing for Azure SQL Database and servers tracks database events and writes them to an audit log in an Azure storage account. If server auditing is enabled, it always applies to the database. The database will be audited, regardless of the database auditing settings.

By default, this feature enabled on SQL servers. To manage the threat detection policy for the severs set enable_sql_server_extended_auditing_policyto valid string. For database auditing, set the argument enable_database_extended_auditing_policy to true

threat_detection_policy - SQL Database Advanced Threat Protection

Advanced Threat Protection for single and pooled databases detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases. Advanced Threat Protection can identify Potential SQL injection, Access from an unusual location or data center, Access from the unfamiliar principal or potentially harmful application, and Brute force SQL credentials - see more details in Advanced Threat Protection alerts.

By default, this feature not enabled on this module. To enable the threat detection policy for the database, set the argument enable_threat_detection_policy = true.

Note: Enabling extended_auditing_policy and threat_detection_policy features on SQL servers and database going to create a storage account to keep all audit logs. Log retention policy to be configured to keep the size within limits for this storage account. Note that this module creates resources that can cost money

Adding Active Directory Administrator to SQL Database

Azure Active Directory authentication is a mechanism of connecting to Microsoft Azure SQL Database by using identities in Azure Active Directory (Azure AD). This module adds the provided Azure Active Directory user/group to SQL Database as an administrator so that the user can login to this database with Azure AD authentication.

By default, this feature not enabled on this module. To add the Active Directory Administrator to SQL database, set the argument ad_admin_login_name with a valid Azure AD user login name.

Configuring the Azure SQL Database Firewall

The Azure SQL Database firewall lets you decide which IP addresses may or may not have access to your Azure SQL Server or your Azure SQL database. When creating an Azure SQL Database, one must add firewall rules before anyone to access the database.

By default, no external access to your SQL Database will be allowed until you explicitly assign permission by creating a firewall rule. To add the firewall rules to the SQL database, set the argument enable_firewall_rules = true and provide the required IP ranges.

Additionally, If you enable Private endpoint feature, firewall rules are not relevant. It does not require adding any IP addresses to the firewall on Azure SQL Database or changing the connection string of your application for private links

Azure SQL Geo-Replication and Failover Groups

Microsoft Azure offers different types of business continuity solutions for their SQL database. One of these solutions is Geo-Replication that provides an asynchronous database copy. You can store this copy in the same or different regions. You can setup up to four readable database copies. If we want to automate and make (users will not affect) failover mechanism transparent, we have to create the auto-failover group.

You can put several single databases on the same SQL Database server into the same failover group. If you add a single database to the failover group, it automatically creates a secondary database using the same edition and the compute size on the secondary server.

For more information, check the Microsoft Documentation

By default, this feature not enabled on this module. To create SQL geo-replicated auto-failover groups, set the argument enable_failover_group = true. To create a failover group, set the secondary server location argument secondary_sql_server_location to a valid region.

Using Failover Groups with Private Link for Azure SQL Database

Azure SQL Database offers the ability to manage geo-replication and failover of a group of databases by adding them to the failover group. A failover group spans two servers – a primary server where the databases are accessed by the end-user or application & a secondary server in a different region where a copy of each database is kept in sync using active geo-replication.

Azure Private Endpoint is a network interface that connects you privately and securely to a service powered by Azure Private Link. Private Endpoint uses a private IP address from your VNet, effectively bringing the service into your VNet.

With Private Link, Microsoft offering the ability to associate a logical server to a specific private IP address (also known as private endpoint) within the VNet. This module helps to implement Failover Groups using private endpoint for SQL Database instead of the public endpoint thus ensuring that customers can get security benefits that it offers.

By default, this feature not enabled on this module. To create private link with private endpoints set the variable enable_private_endpoint to true and provide virtual_network_name, private_subnet_address_prefix with a valid values. You can also use the existing private DNS zone to create DNS records. To use this feature, set the existing_private_dns_zone with a valid existing private DNS zone name.

module "mssql-server" {
  source  = "kumarvna/mssql-db/azurerm"
  version = "1.3.0"

  # .... omitted

  # Creating Private Endpoint requires, VNet name and address prefix to create a subnet
  # By default this will create a `privatelink.database.windows.net` DNS zone. 
  # To use existing private DNS zone specify `existing_private_dns_zone` with valid zone name
  enable_private_endpoint       = true
  virtual_network_name          = "vnet-shared-hub-westeurope-001"
  private_subnet_address_prefix = ["10.1.5.0/29"]
  # existing_private_dns_zone = "demo.example.com"

  # ....omitted

}

If you want to use eixsting VNet and Subnet to create a private endpoints, set a variable enable_private_endpoint to true and provide existing_vnet_id, existing_subnet_id with a valid resource ids. You can also use the existing private DNS zone to create DNS records. To use this feature, set the existing_private_dns_zone with a valid existing private DNS zone name.

module "mssql-server" {
  source  = "kumarvna/mssql-db/azurerm"
  version = "1.3.0"

  # .... omitted

  # Creating Private Endpoint requires, VNet name and address prefix to create a subnet
  # By default this will create a `privatelink.database.windows.net` DNS zone. 
  # To use existing private DNS zone specify `existing_private_dns_zone` with valid zone name
  enable_private_endpoint = true
  existing_vnet_id        = data.azurerm_virtual_network.example.id
  existing_subnet_id      = data.azurerm_subnet.example.id
  # existing_private_dns_zone     = "demo.example.com"

  # ....omitted

}

Create schema and Initialize SQL Database

This module uses the tool slqcmd as a local provisioner to connect and inject the SQL initialization. To enable this feature set the argument initialize_sql_script_execution = true and use sqldb_init_script_file argument to provide the path to SQL script.

Note: To create SQL database schema using SQL script from your desktop requires the addition of a firewall rule. Add your machine public IP to firewall rules to run this feature else this will fail to run and exit the terraform plan

Installation of the Microsoft sqlcmd utility on Ubuntu or on Windows found here.

module "mssql-server" {
  source  = "kumarvna/mssql-db/azurerm"
  version = "1.3.0"

  # .... omitted

  # Create and initialize a database with custom SQL script
  # need sqlcmd utility to run this command 
  # your desktop public IP must be added to firewall rules to run this command 
  initialize_sql_script_execution = true
  sqldb_init_script_file          = "../artifacts/db-init-sample.sql"

  # ....omitted

}

Recommended naming and tagging conventions

Applying tags to your Azure resources, resource groups, and subscriptions to logically organize them into a taxonomy. Each tag consists of a name and a value pair. For example, you can apply the name Environment and the value Production to all the resources in production. For recommendations on how to implement a tagging strategy, see Resource naming and tagging decision guide.

Important : Tag names are case-insensitive for operations. A tag with a tag name, regardless of the casing, is updated or retrieved. However, the resource provider might keep the casing you provide for the tag name. You'll see that casing in cost reports. Tag values are case-sensitive.

An effective naming convention assembles resource names by using important resource information as parts of a resource's name. For example, using these recommended naming conventions, a public IP resource for a production SharePoint workload is named like this: pip-sharepoint-prod-westus-001.

Requirements

Name Version
terraform >= 0.13
azurerm >= 2.59.0
null >= 3.1.0
random >= 3.1.0

Providers

Name Version
azurerm >= 2.59.0
null >= 3.1.0
random >= 3.1.0

Modules

No modules.

Resources

Name Type
azurerm_monitor_diagnostic_setting.extaudit resource
azurerm_mssql_database_extended_auditing_policy.primary resource
azurerm_mssql_server.primary resource
azurerm_mssql_server.secondary resource
azurerm_mssql_server_extended_auditing_policy.primary resource
azurerm_mssql_server_extended_auditing_policy.secondary resource
azurerm_mssql_server_security_alert_policy.sap_primary resource
azurerm_mssql_server_security_alert_policy.sap_secondary resource
azurerm_mssql_server_vulnerability_assessment.va_primary resource
azurerm_mssql_server_vulnerability_assessment.va_secondary resource
azurerm_private_dns_a_record.arecord1 resource
azurerm_private_dns_a_record.arecord2 resource
azurerm_private_dns_zone.dnszone1 resource
azurerm_private_dns_zone_virtual_network_link.vent-link1 resource
azurerm_private_endpoint.pep1 resource
azurerm_private_endpoint.pep2 resource
azurerm_resource_group.rg resource
azurerm_sql_active_directory_administrator.aduser1 resource
azurerm_sql_active_directory_administrator.aduser2 resource
azurerm_mssql_database.db resource
azurerm_sql_failover_group.fog resource
azurerm_sql_firewall_rule.fw01 resource
azurerm_sql_firewall_rule.fw02 resource
azurerm_storage_account.storeacc resource
azurerm_storage_container.storcont resource
azurerm_subnet.snet-ep resource
null_resource.create_sql resource
random_password.main resource
random_string.str resource
azurerm_client_config.current data source
azurerm_private_endpoint_connection.private-ip1 data source
azurerm_private_endpoint_connection.private-ip2 data source
azurerm_resource_group.rgrp data source
azurerm_virtual_network.vnet01 data source

Inputs

Name Description Type Default Required
ad_admin_login_name The login name of the principal to set as the server administrator any null no
admin_password The password associated with the admin_username user any null no
admin_username The administrator login name for the new SQL Server any null no
create_private_dns_zone Whether or not to create a private DNS zone if existing_private_dns_zone is set to null, e.g. if there is already a DNS zone creatted in a shared subscription and the DNS record is deployed by policy bool true no
create_resource_group Whether to create resource group and use it for all networking resources bool true no
database_name The name of the database; DEPRECATED - use 'databases' string "" no
databases The list of databases to create
list(object({
name = string
edition = string
service_objective_name = string
sqldb_init_script_file = string
}))
[] no
disabled_alerts Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action. list(any) [] no
email_addresses_for_alerts A list of email addresses which alerts should be sent to. list(any) [] no
enable_database_extended_auditing_policy Manages Extended Audit policy for SQL database bool false no
enable_failover_group Create a failover group of databases on a collection of Azure SQL servers bool false no
enable_firewall_rules Manage an Azure SQL Firewall Rule bool false no
enable_log_monitoring Enable audit events to Azure Monitor? bool false no
enable_private_endpoint Manages a Private Endpoint to SQL database bool false no
enable_sql_server_extended_auditing_policy Manages Extended Audit policy for SQL servers bool true no
enable_threat_detection_policy n/a bool false no
enable_vulnerability_assessment Manages the Vulnerability Assessment for a MS SQL Server bool false no
existing_private_dns_zone Name of the existing private DNS zone any null no
existing_subnet_id The resource id of existing subnet any null no
existing_vnet_id The resoruce id of existing Virtual network any null no
extaudit_diag_logs Database Monitoring Category details for Azure Diagnostic setting list
[
"SQLSecurityAuditEvents",
"SQLInsights",
"AutomaticTuning",
"QueryStoreRuntimeStatistics",
"QueryStoreWaitStatistics",
"Errors",
"DatabaseWaitStatistics",
"Timeouts",
"Blocks",
"Deadlocks"
]
no
firewall_rules Range of IP addresses to allow firewall connections.
list(object({
name = string
start_ip_address = string
end_ip_address = string
}))
[] no
identity If you want your SQL Server to have an managed identity. Defaults to false. bool false no
initialize_sql_script_execution Allow/deny to Create and initialize a Microsoft SQL Server database bool false no
location The location/region to keep all your network resources. To get the list of all locations with table format from azure cli, run 'az account list-locations -o table' string "" no
log_analytics_workspace_id Specifies the ID of a Log Analytics Workspace where Diagnostics Data to be sent any null no
log_retention_days Specifies the number of days to keep in the Threat Detection audit logs string "30" no
private_subnet_address_prefix The name of the subnet for private endpoints any null no
public_network_access_enabled Whether or not the database should be accessible from the internet bool true no
random_password_length The desired length of random password created by this module number 32 no
resource_group_name A container that holds related resources for an Azure solution string "" no
secondary_sql_server_location Specifies the supported Azure location to create secondary sql server resource string "northeurope" no
sql_database_edition The edition of the database to be created; DEPRECATED - use 'databases' string "Standard" no
sqldb_init_script_file SQL Script file name to create and initialize the database string "" no
sqldb_service_objective_name The service objective name for the database; DEPRECATED - use 'databases' string "S1" no
sqlserver_name SQL server Name string "" no
storage_account_id The name of the storage account to store the all monitoring logs any null no
storage_account_name The name of the storage account name any null no
tags A map of tags to add to all resources map(string) {} no
threat_detection_audit_logs_retention_days Specifies the number of days to keep in the Threat Detection audit logs. number 0 no
virtual_network_name The name of the virtual network string "" no

Outputs

Name Description
primary_sql_server_fqdn The fully qualified domain name of the primary Azure SQL Server
primary_sql_server_id The primary Microsoft SQL Server ID
primary_sql_server_private_endpoint id of the Primary SQL server Private Endpoint
primary_sql_server_private_endpoint_fqdn Priamary SQL server private endpoint IPv4 Addresses
primary_sql_server_private_endpoint_ip Priamary SQL server private endpoint IPv4 Addresses
resource_group_location The location of the resource group in which resources are created
resource_group_name The name of the resource group in which resources are created
secondary_sql_server_fqdn The fully qualified domain name of the secondary Azure SQL Server
secondary_sql_server_id The secondary Microsoft SQL Server ID
secondary_sql_server_private_endpoint id of the Primary SQL server Private Endpoint
secondary_sql_server_private_endpoint_fqdn Secondary SQL server private endpoint IPv4 Addresses
secondary_sql_server_private_endpoint_ip Secondary SQL server private endpoint IPv4 Addresses
sql_database_id The SQL Database ID; DEPRECATED - use sql_database_ids
sql_database_ids The SQL Database ID
sql_database_name The SQL Database Name; DEPRECATED - use sql_database_names
sql_database_names The SQL Database Name
sql_failover_group_id A failover group of databases on a collection of Azure SQL servers.
sql_server_admin_password SQL database administrator login password
sql_server_admin_user SQL database administrator login id
sql_server_private_dns_zone_domain DNS zone name of SQL server Private endpoints dns name records
storage_account_id The ID of the storage account
storage_account_name The name of the storage account

Resource Graph

Authors

Originally created by Kumaraswamy Vithanala

Other resources

About

Terraform Module to deploy a SQL Server, SQL Database, Storage Account in a Resource Group. The module can create an auto-failover group with a private link and geo-redundant database for high availability needs.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • HCL 100.0%