Scalable, Reliable, Secure WordPress on Azure – 6: Opening Ports to Access the Servers

Next iteration of our famous series -Scalable, Highly Available, Secure WordPress on Azure series.

Today we’d be resolving an issue that we’re facing in terms of our deployment so far.

In my zeal to employ best security principles from the ground-up, I’ve ended up in a situation where I am not able to remote-login into the servers created in the previous task. Which is no good as I need to access the servers to deploy the AMP + WordPress software stack on top of it. What are my options?

Secure Access Options

  • Use a P2S Azure connection using Virtual Gateway
    • Although elegant and secure solution, this option is cost-prohibitive. creating and managing a virtual gateway and having it running costs $. The advantage is that I don’t have to make any changes to network, NSGs and won’t have to open ports either.reate a P2S connection whilst creating a network gateway component inside my virtual network.
  • Utilize the Just In Time access functionality provided by the Azure
    • This option relies on changing the settings in the NSGs to open ports for certain duration for certain users. This option won’t work in our case as their are no public ports available to connect to the servers. The public IP connections would still need to be connected
  • Create a Jump-Box server and deploy the functionality through it
    • Yes, workable but would’ve involved creating and logging into a server which had security open – even if it a limited time window.
  • Roll my own simple implementation
    • The implementation that I have settled on was to create a script which will create temporary public IPs, attach them to the NICs which are linked with VMs and relax the NSG security restrictions. So in essence, you can think of rolling my own Just-In-Time security implementation but with the ability to open ports. The drawback, and its a big one in terms of security, is that the user has to manually remember to close the NSG ports and remove the public IPs created once the installation and configuration of servers is complete.

Implementation Details

The script used to create the servers is located @ ‘6-create-attach-temporary-publicIP.ps1‘. The corresponding script to clean all the resources created by this script is ‘6-detach-remove-temporaryIPaddress.ps1‘.

IMPORTANT: Although its wasn’t mandatory for the other clean-up scripts to be executed, it is an absolutely must for the clean-up script ‘
6-detach-remove-temporaryIPaddress.ps1‘ to be executed after the servers have been installed and configured with the requisite software

The script is again divided into two components. First is the process of creation of public IP addresses and attaching them to the previously created NIC and second is opening ports within our NSGs. Lets take it one by one.

Creating Public IP and Attaching it to NICs

The function implementing the functionality for creating public IPS and attaching them to an existing NICs is called – createAttach_PublicIP_NIC. It takes two parameters, first the name of the public IP address that needs to be plugged in and second the name of the NIC with which the public IP needs to be connected to.

As is the norm with all the scripts written so far, I first check the existence of the public IP address (Cmdlet – Get-AzPublicIpAddress) . If it does not exists, script creates an instance of it using the Azure Cmdlet – New-AzPublicIpAddress

Function createAttach_PublicIP_NIC($IpAddressName, `
                        $nicName                
                        )
{
    #create a temporary public IP address
    $temporaryIP = Get-AzPublicIpAddress `
        -Name $IpAddressName `
        -ResourceGroupName $RESOURCEGROUP_NAME `
        -ErrorAction SilentlyContinue

    if (-not $temporaryIP)
    {
        Write-Host -ForegroundColor Green `
            "create a new static IP address '$IpAddressName'... "
        $temporaryIP = New-AzPublicIpAddress  `
                            -Name $IpAddressName `
                            -ResourceGroupName $RESOURCEGROUP_NAME `
                            -AllocationMethod Static `
                            -Location $LOCATION `
                            -Sku "Standard"
    }

Next script loads a reference to the NIC (Cmdlet – Get-AzNetworkInterface) with which the previously created public IP needs to be attached. If the reference exists, script attaches the public IP with the NIC using Cmdlets Set-AzNetworkInterfaceIpConfig and Set-AzNetworkInterface.

Interesting to note that all the existing connections for the NIC needs to be re-specified for the connections to be maintained whilst calling
Set-AzNetworkInterfaceIpConfig. The new parameter that is specified, that attached the public IP to the NIC is ‘-PublicIpAddress

Once the IP configuration values are specified, the setting are saved with a call to Cmdlet – Set-AzNetworkInterface

    $nic = Get-AzNetworkInterface `
            -Name $nicName `
            -ResourceGroupName $RESOURCEGROUP_NAME `
    if ($nic)
    {
        Write-Host -ForegroundColor Green `
            "Attaching the created public IP to NIC '$nicName'... "
        Set-AzNetworkInterfaceIpConfig `
            -Name $nic.IpConfigurations[0].Name `
            -NetworkInterface $nic `
            -Subnet $nic.IpConfigurations[0].Subnet `
            -PrivateIpAddress $nic.IpConfigurations[0].PrivateIpAddress `
            -LoadBalancerBackendAddressPool $nic.IpConfigurations[0].LoadBalancerBackendAddressPools `
            -LoadBalancerInboundNatRule $nic.IpConfigurations[0].LoadBalancerInboundNatRules `
            -Primary `
            -PublicIpAddress $temporaryIP 
         Set-AzNetworkInterface -NetworkInterface $nic
    }

Opening SSH Ports within NSGs

Once the public IPs are coupled with the NICs, I’ve established connectivity but still the access to the VMs is not allowed because of NSG restrictions. In the last phase of this script, I’ll grant RDP access from outside for these machines. The function that implements this functionality is – openRDPPortForNSGs. For a given NSG, it tries to find if the NSG rule already exists by iterating through all the existing rules that exists within that NSG (Cmdlet – Get-AzNetworkSecurityGroup) and matching each rule name with the one that we are creating. The reason I had to iterate all the rules is because I could not find a single Cmdlett which will tell me if that rule exists within a NSG. If it does not find any, it creates that rule using the Cmdlet – Add-AzNetworkSecurityRuleConfig . Whilst opening the RDP port, I specify all access, but in practise you might want to restrict it. Finally I call the Cmdlet – Set-AzNetworkSecurityGroup to save the settings within the NSG.

Function openRDPPortForNSGs($NsgName)
{
    $NSG = Get-AzNetworkSecurityGroup `
        -ResourceGroupName $RESOURCEGROUP_NAME `
        -Name $NsgName
    if ($NSG)
    {
        Write-Host -ForegroundColor Green "creating new rule for '$NsgName' ... "
        $existingRules = $NSG.SecurityRules
        $ruleExist = $false
        ForEach ($existingrule in $existingRules) { 
            Write-Host $existingrule.Name
            If ($existingrule.Name.StartsWith($rdpSecurityRuleName))
            {
               $ruleExist = $true
               break 
            } 
        }

        if (-not $ruleExist)
        {
            # Add rdpRule to the collection
            Add-AzNetworkSecurityRuleConfig `
                -Access Allow `
                -Direction Inbound `
                -Priority 1050 `
                -Name $rdpSecurityRuleName `
                -NetworkSecurityGroup $NSG `
                -Protocol Tcp `
                -SourcePortRange * `
                -DestinationPortRange 22 `
                -SourceAddressPrefix * `
                -DestinationAddressPrefix *
            Set-AzNetworkSecurityGroup -NetworkSecurityGroup $NSG
        }
...

[Validation Tests]: Log on to the Azure portal and manually validate that following highlighted components have been created:

New Public IPs created

In terms of how the newly created public IP addresses are attached and plugged into our architecture is shown in the following diagram

Public IP Addresses Attachments

[Validation Tests]: Log on to the Azure portal and manually validate that following highlighted NSG ports have been opened up:

Opening of the RDP port – 22

Next Steps

Now that I’ve opened the RDP ports to server from internet, it is imperative that I restrict the time-windows when our servers are exposed and can be compromised; thus I should install the software stack on the servers. ASAP. That is what I’ll do next.

And once I’ve complted the configuration of servers, I’ve to remember to close these ports and remove the public IP addresses I’ve created. It will not only make the solution more secure but also make it less costly – remember, each Public IP address created costs $’s.

Leave a Reply

Your email address will not be published. Required fields are marked *