Automate Security for Azure Container Registry

From March 2021 Azure is deprecating the Container Setting in Azure Web Apps, which changes you to use the new Development Center. This look very nice, but there is a change that is going to force you to have weaker security. This change is to have the Admin Credentials enabled, but there is something you can do to be secure.

Before this change, the best practice method was to turn Admin Credentials off in your Azure Container Registry(ACR). This is because the user is a single user, so you can’t tell different peoples interactions while using this one account, and it also has as it says in the name, admin rights meaning it can do anything.

To make this secure, you would disable the Admin Credentials and then anything trying to connect to the repository would have a Service Principle set up or a role added with the correct access. In this post I describe some of these where you can set up the ACR credentials in the App Settings, so the Azure Web App has access to pull the image. This is using Terraform, but it has the basic idea as well.
Use Terraform to connect ACR with Azure Web App

Now when you create a new Azure Web App or go to an existing one you will be presented with an error like this:

Basics Docker Monitoring 
Tags 
Review + create 
Pull container images from Azure Container Registry, Docker Hub or a private Docker repository. App Service will 
deploy the containerized app with your preferred dependencies to production in seconds. 
Options 
Image Source 
Azure container registry options 
Registry * 
Image 
Tag 
Startup Command O 
Single Container 
Azure Container Registry 
Loading... 
Cannot perform credential operations for 
o 
as admin user is 
disabled. Kindly enable admin user as per docs: https://docs.microsoft.com 
/en-us/azure/container-registry/container-registry-authentication*admin- 
account

This is now the message you get telling you to turn on the Admin Credentials, but what makes it confusing is on the documentation they point you to says:

“The admin account is designed for a single user to access the registry, mainly for testing purposes. “

ref: https://docs.microsoft.com/en-us/azure/container-registry/container-registry-authentication#admin-account

However, it seems we need to play by their conflicting rules, so we need to work with this and make it more secure.
Turning on this setting can be insecure, but what we can do is rotate the keys. As you can tell from the UI you don’t need to enter these credentials as the authentication is handled behind the scenes.

Therefore, we can regenerate the passwords without affecting the connection between the ACR and the Resource. This is not perfect, but it does mean if anyone get your password or uses it, then it will be expired very quickly if you want at least.

To do this we can use the ACR and the Azure CLI. With the CLI you can use the ACR commands to trigger a password regeneration.

az acr credential renew -n MyRegistry --password-name password
az acr credential renew -n MyRegistry --password-name password2

ref: https://docs.microsoft.com/en-us/cli/azure/acr/credential?view=azure-cli-latest#az_acr_credential_renew

We can then schedule this and tie it to the ACR by using the ACR Tasks. These can run ACR commands and be put on a repeating timer to trigger when you wish.
ref: https://docs.microsoft.com/en-us/cli/azure/acr/task?view=azure-cli-latest#az_acr_task_create

The below will run the ACR command on the ACR every Monday each week.

$CMD = "az acr credential renew -n MyRegistry --password-name password"
az acr task create --name "$AcrName-RegeneratePassword" --cmd "$CMD" --schedule "0 01 * * 1" --registry $AcrName --context /dev/null

I would still recommend using Roles or Service Principles to access the ACR in other ways, but this does solve the coming issue.

Push Docker Image to ACR without Service Connection in Azure DevOps

If you are like me and using infrastructure as code to deploy your Azure Infrastructure then using the Azure DevOps Docker task doesn’t work. To use this task you need to know what your Azure Container Registry(ACR) is and have it configured to be able to push your docker images to the registry, but you don’t know that yet. Here I show how you can still use Azure DevOps to push your images to a dynamic ACR.

In my case I am using Terraform to create the Container Registry and with that I pass what I want it to be called. For example ‘prc-acr’ which will generate an ACR with the full login server name ‘prc-acr.azurecr.io’. This can then be used later for sending the images to the correct registry.

When using the official Microsoft Docker Task the documentation asks that your have a Service Connection to your ACR. To do this though you need the registry login server name, username and password to connect, which unless you keep the registry static you will not know. Therefore, you can’t create the connection to then push your images up. I did read some potential methods to dynamically create this connection, but then we need to manage these so they do not get out of control.

To push the image we need only two things, a connection to Azure and where to push the image. The first we can get set up as we know the tenant and subscription we will be deploying to. The connection can be made up by following this guide to connection Azure to Azure DevOps. The other part of where to send the image, we mentioned earlier when we created the ACT in Terraform calling it ‘prc-acr’.

With these details we can use the Azure CLI to push the image to the ACR. First your need to login to the ACR using:

az acr login --name 'prc-acr'

This will connect you into the ACR that was created in Azure. From there you will need to tag your image with the acr login server name with registry name and tag. For example:

docker tag prcImage:latest prc-acr.azurecr.io/prc-registry:latest

This will then tell docker where to push the image to while you are logged in to the Azure Container Registry, which means from there we simply just need to push the image with that tag in the standard docker method:

docker push prc-acr.azurecr.io/prc-registry:latest

Now this is very each and simple as we do not need a connection to the Container Registry, but just a connection to the Azure environment. These details can then be used with the Azure CLI Task as below, where I am passing in the following parameters.

Parameter NameExample ValueDescription
azureServiceConnectionAzureServiceConnectionService Connection name to Azure
azureContainerRegistryNamePrc-acrAzure Container Registry Name
dockerImageprcImageDocker Image Name
tagNameLatestDocker Tag Name
registryNamePrc-registryACR Registry Name
steps:
  - task: AzureCLI@2
    displayName: 'Push Docker Image to ACR'
    inputs:
      azureSubscription: ${{parameters.azureServiceConnection}}
      scriptType: 'ps'
      scriptLocation: 'inlineScript'
      inlineScript: |
        az acr login --name ${{parameters.azureContainerRegistryName}}
        docker tag ${{parameters.dockerImage}}:${{parameters.tagName}} ${{parameters.azureContainerRegistryName}}.azurecr.io/${{parameters.registryName}}:${{parameters.tagName}}
        docker push ${{parameters.azureContainerRegistryName}}.azurecr.io/${{parameters.registryName}}:${{parameters.tagName}}

Where to find Azure Tenant ID in Azure Portal?

Some of the documentation about Azure from Microsoft can be confusing and missing, including one I get ask ‘Where is the Tenant ID’. Below I give 3 locations, which there is probably, on where to find the Tenant ID in the portal. I have also added how to get the Tenant ID with the Azure CLI.

The Tenant is  basically the Azure AD instance where you can store and configure users, apps and other security permissions. This is also referred to as the Directory in some of the menu items and documentation. Within the Tenant you can only have a single Azure AD instance, but you can have many Subscriptions associated with it. You can get further information from here https://docs.microsoft.com/en-us/microsoft-365/enterprise/subscriptions-licenses-accounts-and-tenants-for-microsoft-cloud-offerings?view=o365-worldwide

Azure Portal

Azure Active Directory

If you use the Portal menu, once signed in, then you can select the ‘Azure Active Directory’ option.

This will load the Overview page with the summary of your Directory including the Tenant ID.

You can also go to this URL when signed in: https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview

1

Azure AD App Registrations

When configuring external applications or internal products to talk, you can use App Registrations or also know as Service Principal accounts. I know when using the REST API or the Azure SDK you will need the Tenant ID for the authentication, so within the registered app you also get the Tenant ID.

When in the Azure AD, select the ‘App registrations’ from the side menu. Find or add your App then select it.

From the App Overview page you can then find the Tenant ID or also known here as the Directory ID.

Switch Directory

If you have multiple Tenants then you can switch between the Tenants you have access to by switching Directory.

You can do this by selecting your Avatar/Email from the top right of the Portal, which should open a dropdown with your details. There will then be a link call ‘Switch directory’, and by clicking this you can see all the directories you have access to, what your default directory is and switch which one you are on.

As mentioned before the Directory is another word used my Azure for Tenant, so the ID you the see in this view is not just the Directory ID but also the Tenant ID.

Directory +

Azure CLI

From the Azure CLI you can get most every bit of information that is in the Portal depending on your permission.

If you don’t have the CLI then you can install it here: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli

You can sign into the CLI by running:

az login

More information on logging in can be found here: https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli

Once you are signed into the Azure CLI, then you can use this command below to get a list of the Subscriptions you have access to, which intern will report back the Tenant ID. Remove everything after ‘–query’ to get the full details.

(https://docs.microsoft.com/en-us/cli/azure/account?view=azure-cli-latest#az_account_list)

 az account list --query '[].{TenantId:tenantId}'

You can also get the current Tenant ID used to authenticate to Azure, by running this command and again remove after the ‘–query’ to get the full information.

(https://docs.microsoft.com/en-us/cli/azure/account?view=azure-cli-latest#az_account_get_access_token)

 az account get-access-token --query tenant --output tsv