Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Lock down the Azure Database for MySQL Flexible Server instance by using a private endpoint

To start, you need to lock down access to your MySQL database by using a private endpoint. This will protect the database content. A private endpoint is represented by a private IP address within a virtual network. Once you enable it, you can block public access to your MySQL Flexible Server. To accomplish this, you can use the following guidance:

Step by step guidance

  1. To start, you need to create an additional subnet for the private endpoints.

    PRIVATE_ENDPOINTS_SUBNET_CIDR=10.1.4.0/24
    PRIVATE_ENDPOINTS_SUBNET_NAME=private-endpoints-subnet
    
    az network vnet subnet create \
        --name $PRIVATE_ENDPOINTS_SUBNET_NAME \
        --resource-group $RESOURCE_GROUP \
        --vnet-name $VIRTUAL_NETWORK_NAME \
        --address-prefix $PRIVATE_ENDPOINTS_SUBNET_CIDR
    
  2. Next, disable private endpoint network policies in the subnet you will use to create the private endpoints.

    az network vnet subnet update \
       --name $PRIVATE_ENDPOINTS_SUBNET_NAME \
       --resource-group $RESOURCE_GROUP \
       --vnet-name $VIRTUAL_NETWORK_NAME \
       --disable-private-endpoint-network-policies true
    
  3. You can now create a private endpoint for the MySQL instance.

    MYSQL_RESOURCE_ID=$(az resource show -g $RESOURCE_GROUP -n $MYSQL_SERVER_NAME --resource-type "Microsoft.DBforMySQL/flexibleServers" --query "id" -o tsv)
    
    az network private-endpoint create \
        --name pe-openlab-mysql \
        --resource-group $RESOURCE_GROUP \
        --vnet-name $VIRTUAL_NETWORK_NAME  \
        --subnet $PRIVATE_ENDPOINTS_SUBNET_NAME \
        --private-connection-resource-id $MYSQL_RESOURCE_ID \
        --group-id mysqlServer \
        --connection-name openlab-mysql-connection \
        --location $LOCATION
    

    Once you created the private endpoint, you will set up a private Azure DNS zone named privatelink.mysql.database.azure.com with an A DNS record matching the original DNS name with the suffix mysql.database.azure.com but replacing that suffix with privatelink.mysql.database.azure.com. Your apps connecting to the MySQL will not need to be updated, but instead they can continue using the existing connection settings.

  4. To implement this configuration, start by creating a new private DNS zone and linking it to your virtual network.

    az network private-dns zone create \
        --resource-group $RESOURCE_GROUP \
        --name  "privatelink.mysql.database.azure.com"
    
    az network private-dns link vnet create \
        --resource-group $RESOURCE_GROUP \
        --zone-name  "privatelink.mysql.database.azure.com"\
        --name MyMySQLDNSLink  \
        --virtual-network $VIRTUAL_NETWORK_NAME \
        --registration-enabled false
    
  5. Next, create a new A record pointing to the IP address of the newly created private endpoint.

    MYSQL_NIC_ID=$(az network private-endpoint show --name pe-openlab-mysql --resource-group $RESOURCE_GROUP --query 'networkInterfaces[0].id' -o tsv)
    MYSQL_NIC_IPADDRESS=$(az resource show --ids $MYSQL_NIC_ID --api-version 2019-04-01 -o json | jq -r '.properties.ipConfigurations[0].properties.privateIPAddress')
    
    az network private-dns record-set a create \
        --name $MYSQL_SERVER_NAME \
        --zone-name privatelink.mysql.database.azure.com \
        --resource-group $RESOURCE_GROUP
    
    az network private-dns record-set a add-record \
        --record-set-name $MYSQL_SERVER_NAME \
        --zone-name privatelink.mysql.database.azure.com \
        --resource-group $RESOURCE_GROUP \
        -a $MYSQL_NIC_IPADDRESS
    
  6. You can now disable all public access towards your MySQL.

    az mysql flexible-server update \
       --name $MYSQL_SERVER_NAME \
       --resource-group $RESOURCE_GROUP \
       --public-access Disabled
    
  7. Restart the apps in the AKS cluster that use the backend database to make sure they still can use the database. Do this by deleting their pods.

    kubectl get pods
    kubectl delete pod <customers-service-pod> 
    kubectl delete pod <vets-service-pod> 
    kubectl delete pod <visits-service-pod> 
    
  8. In case you see errors or crashloops of your pods, you can use the below statements to diagnose what might be going wrong. A first statement you can try is look at the logs of your pod.

    kubectl logs <pod-name>
    
  9. You should be able to browse the spring petclinic app and see the data again.

  10. In the Azure Portal navigate to your newly created MySQL Flexible Server and select the Networking menu. In the menu you will notice public access is not allowed and the private endpoint is configured on the server.