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.
- SQL Servers
- SQL Database
- Storage account for diagnostics
- Active Directory Administrator
- Firewall rule for azure services, resources, and client IP
- SQL Auto-Failover Group
- Private Endpoints
- Private DNS zone for
privatelink
A records - SQL Script execution to create Database
- SQL Server and Database Extended Auditing Policy
- Azure Defender for SQL
- SQL Vulnerability Assessment
- SQL Log Monitoring and Diagnostics
# 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 = ["user@example.com", "firstname.lastname@example.com"]
# 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 = "firstname.lastname@example.com"
# (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 = "user@example.com"
BusinessUnit = "CORP"
ServiceClass = "Gold"
}
}
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.
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.
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_policy
to valid string. For database auditing, set the argument enable_database_extended_auditing_policy
to true
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
andthreat_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
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.
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.
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.
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
}
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.
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
}
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
.
Name | Version |
---|---|
terraform | >= 0.13 |
azurerm | >= 2.59.0 |
Name | Version |
---|---|
azurerm | >= 2.59.0 |
random | >= 3.1.0 |
null | >= 3.1.0 |
Name | Description | Type | Default |
---|---|---|---|
create_resource_group |
Whether to create resource group and use it for all networking resources | string | "false" |
resource_group_name |
The name of an existing resource group. | string | "" |
location |
The location for all resources while creating a new resource group. | string | "" |
sqlserver_name |
The name of the Microsoft SQL Server | string | "" |
database_name |
The name of the SQL database | string | "" |
admin_username |
The username of the local administrator used for the SQL Server | string | "azureadmin" |
admin_password |
The Password which should be used for the local-administrator on this SQL Server | string | null |
random_password_length |
The desired length of random password created by this module | number | 32 |
storage_account_name |
The name of the storage account | string | null |
sql_database_edition |
The edition of the database to be created. Valid values are: Basic , Standard , Premium , DataWarehouse , Business , BusinessCritical , Free , GeneralPurpose , Hyperscale , Premium , PremiumRS , Standard , Stretch , System , System2 , or Web |
string | "Standard" |
sqldb_service_objective_name |
The service objective name for the database. Valid values depend on edition and location and may include S0 , S1 , S2 , S3 , P1 , P2 , P4 , P6 , P11 |
string | "S1" |
enable_sql_server_extended_auditing_policy |
Manages Extended Audit policy for SQL servers | string | "true" |
enable_database_extended_auditing_policy |
Manages Extended Audit policy for SQL database | string | "false" |
enable_threat_detection_policy |
Threat detection policy configuration | string | "false" |
enable_log_monitoring |
Enable audit events to Azure Monitor? | string | false |
log_retention_days |
Specifies the number of days to retain logs for in the storage account | number |
30 |
email_addresses_for_alerts |
Account administrators email for alerts | list(any) |
"" |
ad_admin_login_name |
The login name of the principal to set as the server administrator | string | null |
enable_firewall_rules |
Manages a Firewall Rule for a MySQL Server | string | "false" |
firewall_rules |
list of firewall rules to add SQL servers | list(object({})) |
[] |
enable_failover_group |
Create a failover group of databases on a collection of Azure SQL servers | string | "false" |
secondary_sql_server_location |
The location of the secondary SQL server (applicable if Failover groups enabled) | string | "northeurope" |
initialize_sql_script_execution |
enable sqlcmd tool to connect and create database schema | string | "false" |
sqldb_init_script_file |
SQL file to execute via sqlcmd utility to create required database schema | string | "" |
enable_private_endpoint |
Manages a Private Endpoint to Azure Container Registry | string | false |
virtual_network_name |
The name of the virtual network for the private endpoint creation. conflicts with existing_vnet_id and shouldn't use both. |
string | "" |
private_subnet_address_prefix |
Address prefix of the subnet for private endpoint creation. conflicts with existing_subnet_id and shouldn't use both |
list(string) | null |
existing_vnet_id |
The resoruce id of existing Virtual network for private endpoint creation. Conflicts with virtual_network_name and shouldn't use both |
string | null |
existing_subnet_id |
The resource id of existing subnet for private endpoint creation. Conflicts with private_subnet_address_prefix and shouldn't use both |
string | null |
existing_private_dns_zone |
The name of exisging private DNS zone | string | null |
log_analytics_workspace_id |
The id of log analytic workspace to send logs and metrics. | string | "null" |
storage_account_id |
The id of storage account to send logs and metrics | string | "null" |
Tags |
A map of tags to add to all resources | map | {} |
Name | Description |
---|---|
resource_group_name |
The name of the resource group in which resources are created |
resource_group_location |
The location of the resource group in which resources are created |
storage_account_id |
The ID of the storage account |
storage_account_name |
The name of the storage account |
primary_sql_server_id |
The primary Microsoft SQL Server ID |
primary_sql_server_fqdn |
The fully qualified domain name of the primary Azure SQL Server |
secondary_sql_server_id |
The secondary Microsoft SQL Server ID |
secondary_sql_server_fqdn |
The fully qualified domain name of the secondary Azure SQL Server |
sql_server_admin_user |
SQL database administrator login id |
sql_server_admin_password |
SQL database administrator login password |
sql_database_id |
The SQL Database ID |
sql_database_name |
The SQL Database Name |
sql_failover_group_id |
A failover group of databases on a collection of Azure SQL servers |
primary_sql_server_private_endpoint |
id of the Primary SQL server Private Endpoint |
secondary_sql_server_private_endpoint |
id of the Primary SQL server Private Endpoint |
sql_server_private_dns_zone_domain |
DNS zone name of SQL server Private endpoints DNS name records |
primary_sql_server_private_endpoint_ip |
Primary SQL server private endpoint IPv4 Addresses |
primary_sql_server_private_endpoint_fqdn |
Primary SQL server private endpoint IPv4 Addresses |
secondary_sql_server_private_endpoint_ip |
Secondary SQL server private endpoint IPv4 Addresses |
secondary_sql_server_private_endpoint_fqdn |
Secondary SQL server private endpoint FQDN Addresses |
Originally created by Kumaraswamy Vithanala