Consolidating services into Azure

Recently I had an exceedingly poor experience with my external DNS provider, Namecheap. After they had some mail issues, their 2FA emails weren’t coming through…. I could see they weren’t even hitting O365… but of course, their support refused to acknowledge this – and went down a path of (bizarrely) insistently asking for a scan of government issued ID – very scammer like. This was enough to make me re-evaluate my external services and where they lived – with a specific view to bringing them into Azure…

 

Why bring all the services into O365/Azure ?

  • One provider… and MS are a provider that isn’t disappearing anytime soon. I can’t see us moving away from O365 in the foreseeable future – so if that service is anchored – why not move others towards it ?
  • Azure management interface and scripting are generally pretty good
  • MS support is generally terrible…. But they have never tried to get me to send a government issued photo ID. Community support around Azure/O365 varies greatly – but there are many great blog articles etc around.
  • Cost – MS partners can get Azure credit with some partnership options – some months I use it all – other months I don’t – so it makes sense to use as much of the credit as possible

 

DNS

DNS seemed like the easiest candidate and it was also the service that was about to expire on Namecheap.

I logged a call with O365 support, asking about transferring a DNS zone into O365/Azure… The guy was actually reasonably nice and tried to be helpful – but seemed to have it in his head that DNS was a website or something…. Anyway, the upshot of the conversation was “no, you can’t transfer in… you can only use O365 DNS if you purchased the domain from MS”

After this I went off did some searching and found the incredibly aptly named Azure DNS.

5 minutes later, it was all setup and ready to go

  • Go to the Azure portal
  • Create resource
  • Networking -> DNS Zone
  • Create
    • Select your subscription, resource group and zone name
  • Add your records

 

I tested the service before updating my registrar using

Nslookup <record name> ns1-02.azure-dns.com.

I then waited a few days – as I wanted to see how much the DNS zone would cost without usage (as Azure pricing pages are exceedingly difficult to decipher IMO) – and while this will obviously vary greatly for everyone – for my zone after 5 days (with no traffic mind you) – the cost for that service was a whopping $0.05.

 

Based on that, I updated my registrar to point to the Azure DNS servers, then ran an O365 check – just in case – and all was good.

 

Domain transfer

Given the above conversation, I thought it was unlikely, but quickly found these items via google

https://learn.microsoft.com/en-us/answers/questions/2168/how-can-i-transfer-a-domain-from-godaddy-to-azure

https://jrudlin.github.io/2018/10/27/domain-name-registration-transfer-to-azure-app-service-domains/

 

So it is possible – but is a bit of kludge… additionally, according to the first forum post at least – the ability to “transfer in” in on the MS radar

 

Given my domain registrations for my current domains does not run out until 2024 – I am going to wait until they are closer to expiry – then come back and see if MS have an officially supported method of transferring domain registration into O365/Azure.

 

WordPress

WordPress on Azure went GA in August 2022 – and you can find some details about it here – https://learn.microsoft.com/en-us/azure/app-service/quickstart-wordpress

 

Unfortunately, when going to https://portal.azure.com/#create/WordPress.WordPress – I am immediately presented with “MySQLFlexible server is not available for your selection of subscription and location”… changing location does nothing – so its something to do with my partner subscription…. Wouldn’t want partners to be able explore your product set and become more familiar with the wide range of Azure offerings…. (or write blog posts on how to use their products) – can’t have that! Geez MS licensing people make some whacky fucking decisions.

 

Static Websites

Last up was my company website, which is a static HTML website. After some google, I found there were a few methods, such as using an Azure storage account – but that seemed to have some limitations around certificate assignment and host headers (from reading other posts). The other main option appeared to be  Azure static web apps – which was a more complete offering, but also more complex. It required linkage to a GitHub or Azure DevOps account and asked me a bunch of questions that I had NFI about. Remember, I’m an infra nerd… so once it goes past PowerShell (or VBScript.. or JSON if I have to) – its all quantum realm magic to me.

Anyway, after some reading and making a few mistakes, the rough process is:

  • Create a GitHub account (I went GitHub – since I already had an account and some code in there)
  • Create a project in GitHub
  • Upload the static html/css site to the GitHub project
    • For whatever reason, only about 90% of the files uploaded first try – but there were no errors. I only found out some files were missing when I tried to use the published website. I’m a newbie to Github – so maybe I did something wrong – but its worth looking out for
  • Go to the Azure portal
  • Create resource
  • Search for “Static Web app”
  • Create
    • Select your subscription, resource group and name
    • Select your hosting plan…. Free is obviously a good place to start – you can always upgrade it later
    • Deployment details – I selected “GitHub”
    • Authorise the connection between the static web app and GitHub
  • The site will now be ready via the Azure URL – which is great for testing to make sure everything is correct
    • My site was ready fairly quickly – but a number of the images didn’t display.
    • I posted on a forum about this and eventually found that files within the Static web app are case sensitive… so my html referred to background.jpg… when the file was named Background.jpg…. I got rid of the capitalisation once I realised, and all was good.
  • Once everything is correct
    • Add your custom domain
      • Azure static web app -> custom domains
      • Add – custom domain on Azure DNS
      • Select your DNS zone from the drop down
      • In the domain name box, you must enter the FQDN… e.g. www.company.com, not just “www” (give that you select the zone in the other drop down – this is confusing)
      • Now – as per this bug – https://github.com/Azure/static-web-apps/issues/202 – I found I got the error “Failed to add custom domain to SWA with error message”… but the CName entry was still actually added… this was a start… but since it did not show up in “custom domains” – the site still did not work without that host header.
      • Due to this, I simply added it as a “custom domain” (even though the DNS was/is hosted in Azure DNS) – and it took a minute to validate, but worked fine

 

In summary

  • Azure DNS – easy
  • Azure static web sites easy-ish… but wasn’t clear that it was case sensitive and the adding of a custom domain seems very buggy
  • Not being able to transfer to MS as a domain registrar is a bizarre omission
  • Microsoft licensing people still make decisions by rolling a D20 inside a Zorba ball when drunk – this is unlikely to change in my lifetime
  • Run the fuck away from NameCheap

Azure AD Connect – Permissions Issues

I’ve had various versions of AD Sync/Azure AD Connect running in my development environment over the years, and have used a number of different service accounts when testing out different configurations or new features. Needless to say, the permissions for my Sync account were probably a bit of a mess.

Recently, I wanted to try out group writeback. It’s been a preview feature of Azure AD Connect for quite a while now – it allows you to synchronise Exchange Online groups back to your AD environment so that on premise users can send and receive emails from these groups.

Launched the AADConnect configuration, enabled Group Writeback, then kicked off a sync. Of course, I start getting ‘Access Denied’ errors for each of the Exchange Online groups – couldn’t be that easy!

Generally speaking, you need to also run one of the “Initialize-<something>Writeback” commands. When I went looking for the appropriate commands (as I don’t remember these things off the top of my head!), I came across an interesting TechNet Blog article: Advanced AAD Connect Permissions Configuration – it’s pretty much a comprehensive script that handles all the relevant permissions (including locating the configured sync account and sync OUs).

Gave it a whirl, entered credentials as required, and what do you know – permissions all now good!

Using Azure RM Site to Site VPN with a Dynamic IP

In the interests of saving a bit of money, I decided to switch my ADSL service from an expensive business connection to a cheap residential connection. In Australia this also means switching from a static IP address to a dynamic IP address. With most web-based services now able to be proxied via Microsoft’s Web Application Proxy (and other services using unique ports), it seemed like everything would be fine with a combination of a Dynamic DNS service and port forwarding. I only run a development environment at home, so if I could save some money without any real impact, all the better!

After I made the switch, I realised that I’d forgotten about my site-to-site VPN between my development environment and Azure Resource Manager (AzureRM). For those familiar with AzureRM and Site to Site VPN, you’ll know that your on premise IP address is configured in a “Local Network Gateway” object. I thought perhaps that you could enter a DNS entry in the IP address field – no such luck.

So I had a look around online to see if anyone else had some easy solution I could poach. While I could find a solution for Azure Classic, the objects are completely different in AzureRM (and the powershell commands are different) – so while it gave me a direction, I couldn’t use the solution as-is. So I had a look at the available AzureRM powershell cmdlets – primarily Get-AzureRmLocalNetworkGateway  and Set-AzureRmLocalNetworkGateway . The problem I came across was that ‘Set’ command really only accepts two parameters – a LocalNetworkGateway object, and AddressPrefix (for your local address spaces). No option to change the Gateway IP. The documentation didn’t give any additional information either.

Based on previous experience with powershell, I had assumed that the LocalNetworkGateway input object would need to refer to an existing object. As a last resort, I decided to try modify it before setting anyway – and it worked! So essentially we can do something like:

$LNG = Get-AzureRmLocalNetworkGateway -ResourceName <LocalNetworkGatewayName> -ResourceGroupName <ResourceGroupName>
$LNG.GatewayIpAddress = <DynamicIP>
Set-AzureRmLocalNetworkGateway -LocalNetworkGateway $LNG -AddressPrefix @('192.168.0.0/24','192.168.1.0/24')

Obviously this is a fair way from an automated solution that can be run on a schedule! In order to put it into a workable solution, the following overall steps need to be taken:

  1. Configure a dynamic DNS service (such as www.noip.com) – this’ll need to be automatically updated via your router or client software
  2. On the server that will be running the scheduled task, install the Azure Powershell Cmdlets (as per https://azure.microsoft.com/en-us/documentation/articles/powershell-install-configure/)
  3. Create an administrative account in Azure AD that has administrative access on the subscription (they must be listed in the Azure Classic portal under Settings > Administrators). It’s important to note that when using the Login-AzureRM –Credentials  command that the credentials used must be an ‘organisational account’ – you can’t use a Microsoft Live account (even if it’s a subscription administrator).
  4. Use some method of saving credentials for use in Powershell. I prefer to use a key-based encryption so it’s transportable between computers – a guide on doing this can be found here: http://www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-2/
  5. Update the following values in the following script:
    1. DynDNS: the external DNS entry that resolves to your dynamic IP
    2. SubscriptionName: the name of your Azure subscription. This can be retrieved using Get-AzureRMSubscription
    3. User: the organisational administrative account
    4. PasswordFile: the file containing the encrypted password
    5. KeyFile: the file containing the encryption key (obviously you want to keep this safe – as it can be used to reverse engineer the password!)
    6. Address Prefixes on line 42.
  6. When running the script via Task Schedule, ensure you also specify the ‘Start In’ directory – otherwise you need to hard code paths in the script.
#Dynamic DNS Entry for your dynamic IP
$DynDNS = "mydynamicdomain.ddns.net"
#Azure subscription name
$SubscriptionName = "Visual Studio Premium with MSDN"

#UPN of a user account with administrative access to the subscription
$User = "azureadmin@mydomain.net"
#Password file
$PasswordFile = ".\AzurePassword.txt"
#Key file to decrypt the password
$KeyFile = ".\AzureAES.key"

Write-Host "Building Credentials"
#Grab the contents of the key
$key = Get-Content $KeyFile
$SecurePassword = Get-Content $PasswordFile | ConvertTo-SecureString -Key $key
#Build the credential object
$Creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $SecurePassword

#Get the Current Dynamic IP
[string]$DynIP = ([System.Net.DNS]::GetHostAddresses($DynDNS)).IPAddressToString
Write-Host "Current Dynamic IP:" $DynIP

#Log into the Azure Tenant
Login-AzureRmAccount -Credential $Creds
#Select the subscription
Select-AzureRmSubscription -SubscriptionName $SubscriptionName
#Grab the current LocalNetworkGateway
$LNG = Get-AzureRmLocalNetworkGateway -ResourceName Local_Network_Gateway -ResourceGroupName RG_AU_SE
#Output the IP to view
Write-Host "Current LocalNetworkGateway IP:" $LNG.GatewayIPAddress
Write-Host "Current Dynamic IP:" $DynIP

#Determine if we need to change it
If($DynIP -ne $LNG.GatewayIpAddress)
    {
    Write-Host "Dynamic IP is different to LocalNetworkGateway IP - Updating..."
    #Update the IP in the LNG Object
    $LNG.GatewayIpAddress =$DynIP
    #Update the LNG Object in Azure. AddressPrefix is required.
    Set-AzureRmLocalNetworkGateway -LocalNetworkGateway $LNG -AddressPrefix @('192.168.0.0/24','192.168.1.0/24')
    }
else
    {
    Write-Host "No changes required"
    }