Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This tutorial should use Managed Identities to Access ACR #49186

Closed
berndverst opened this issue Feb 28, 2020 — with docs.microsoft.com · 12 comments
Closed

This tutorial should use Managed Identities to Access ACR #49186

berndverst opened this issue Feb 28, 2020 — with docs.microsoft.com · 12 comments

Comments

Copy link
Member

This tutorial no longer recommends the best practice for authenticating App Service with ACR. It is a bad practice to enable the ACR admin mode to get the necessary credentials. Instead a managed identity should be used.

https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet#using-the-azure-cli
https://docs.microsoft.com/en-us/azure/container-registry/container-registry-authentication-managed-identity#example-2-access-with-a-system-assigned-identity

Example:

# Create and assign a managed Service Principal to a Web App
az webapp identity assign --resource-group beverst_rg_Linux_westus2 --name rockpaperscissorslizardspock
# Give webapp identity access to pull from ACR
az role assignment create --assignee 01eaae16-c9a7-4eba-bf27-05820c4fc163 --scope /subscriptions/59985d08-67e1-493c-82c4-7ad711fdba2b/resourceGroups/kubeflowrelease/providers/Microsoft.ContainerRegistry/registries/kubeflowregistry --role "AcrPull"

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@Grace-MacJones-MSFT
Copy link
Contributor

Hi @berndverst, thanks for bringing this to our attention. Your feedback has been shared with the content owner for further review.

@msangapu can you please look into this? Thanks

Copy link

juchom commented Apr 3, 2020

How do you configure the app service to pull the image from ACR?

@berndverst
Copy link
Member Author

berndverst commented Apr 6, 2020

@juchom should be just like this -- no need to specify username and password if you use the managed identity and gave that identity ACRPull rights from the ACR instance

az webapp config container set --name <app-name> --resource-group myResourceGroup --docker-custom-image-name <azure-container-registry-name>.azurecr.io/mydockerimage:v1.0.0 --docker-registry-server-url https://<azure-container-registry-name>.azurecr.io

@juchom
Copy link

juchom commented Apr 7, 2020

Hi @berndverst,

This command gives me this error:

No credential was provided to access Azure Container Registry. Trying to look up...
Retrieving credentials failed with an exception:'Failed to retrieve container registry credentials. Please either provide the credentials or run 'az acr update -n myacr --admin-enabled true' to enable admin first.'

@berndverst
Copy link
Member Author

berndverst commented Apr 7, 2020

@juchom

The error you are getting makes sense. Looks like the CLI is hardcoded to expect admin enabled on ACR (not a good idea) or a username and password to be manually provided.

https://github.com/Azure/azure-cli/blob/abeb2dd611114ca4bb5c4c40996a36f3fc48a05e/src/azure-cli/azure/cli/command_modules/appservice/custom.py#L1120

Let's assume we are talking about

  • A webapp with name $NAME and in resource group $GROUP
  • A registry $REGISTRYNAME in resource group $REGISTRYGROUP

One good option that should certainly work

You could always do is to create a Service Principal for this particular situation that can only read from ACR.
Caveat: Credential expires in 1 year

az ad sp create-for-rbac --name AppServiceReadFromParticularACR
#Above returns a client ID and secret
az role assignment create --assignee $CLIENT_ID --scope /subscriptions/$YOURAZURESUBSCRIPTIONID/resourceGroups/$REGISTRYGROUP/providers/Microsoft.ContainerRegistry/registries/$REGISTRYNAME --role "AcrPull"

and then using the Service Principal client ID and client secret as username and password.

az webapp config container set --name $NAME --resource-group $GROUP --docker-custom-image-name $REGISTRYNAME.azurecr.io/$IMAGENAME:$IMAGETAG --docker-registry-server-url https://$REGISTRYNAME.azurecr.io --docker-registry-server-user $CLIENT_ID --docker-registry-server-password $CLIENT_SECRET

Of course using managed identities is better

It seems the CLI doesn't quite support this yet, but you could help me test this by doing the following.

# Create and assign a managed Service Principal to a Web App
az webapp identity assign --resource-group $GROUP --name $NAME

# This returns a Service Principal ID... $WEBAPPID

# Give webapp identity access to pull from ACR
az role assignment create --assignee $WEBAPPID --scope /subscriptions/$YOURAZURESUBSCRIPTIONID/resourceGroups/$REGISTRYGROUP/providers/Microsoft.ContainerRegistry/registries/$REGISTRYNAME --role "AcrPull"

# Now try using a bogus username and password
az webapp config container set --name $NAME --resource-group $GROUP --docker-custom-image-name $REGISTRYNAME.azurecr.io/$IMAGENAME:$IMAGETAG --docker-registry-server-url https://$REGISTRYNAME.azurecr.io --docker-registry-server-user $CLIENT_ID --docker-registry-server-password $CLIENT_SECRET

# Restart and try to see if this works?
az webapp restart -g $GROUP -n $NAME

# If it doesn't work, let's also delete the App Settings on the server corresponding to the username and password
az webapp config appsettings delete -g $GROUP -n $NAME --settings "DOCKER_REGISTRY_SERVER_PASSWORD" "DOCKER_REGISTRY_SERVER_USERNAME"
az webapp restart -g $GROUP -n $NAME

@juchom
Copy link

juchom commented Apr 8, 2020

So after doing this command:

# Now try using a bogus username and password
az webapp config container set --name $NAME --resource-group $GROUP --docker-custom-image-name $REGISTRYNAME.azurecr.io/$IMAGENAME:$IMAGETAG --docker-registry-server-url https://$REGISTRYNAME.azurecr.io --docker-registry-server-user $CLIENT_ID --docker-registry-server-password $CLIENT_SECRET

I have this error

2020-04-08 07:42:30.233 INFO  - Pulling image from Docker hub: myacr.azurecr.io/myapp:584
2020-04-08 07:42:30.544 ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://myacr.azurecr.io/v2/myapp/manifests/584: unauthorized: authentication required"}

And after removing the username and password from app settings it doesn't work with same error.

@berndverst
Copy link
Member Author

Thanks for trying @juchom. One last thing to try -- also deleting the app setting for the login server. I really appreciate you being willing to verify this.

If this still doesn't work it seems we have a little bit of engineering work left to tie some of the pieces together. You are trying some cutting edge stuff here :) Hopefully the other approach I provided is still a good option for you as well.

# If it doesn't work, let's also delete the App Settings on the server corresponding to the username, 
 password and login server
az webapp config appsettings delete -g $GROUP -n $NAME --settings "DOCKER_REGISTRY_SERVER_PASSWORD" "DOCKER_REGISTRY_SERVER_USERNAME" "DOCKER_REGISTRY_SERVER_URL"
az webapp restart -g $GROUP -n $NAME

@juchom
Copy link

juchom commented Apr 8, 2020

This doesn't work either:

2020-04-08 17:14:01.287 INFO  - Pulling image from Docker hub: myacr.azurecr.io/showcase:584
2020-04-08 17:14:01.506 ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://myacr.azurecr.io/v2/myapp/manifests/584: unauthorized: authentication required"}

2020-04-08 17:14:01.515 ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2020-04-08 17:14:02.448 INFO  - Stoping site pulumitest-dev-web because it failed during startup.

In the mean time I also found this on uservoice: https://feedback.azure.com/forums/169385-web-apps/suggestions/36145444-web-app-for-containers-acr-access-requires-admin#{toggle_previous_statuses}

@berndverst
Copy link
Member Author

@juchom Thanks for trying. Please note... this bug here is the official request to update the documentation for this feature. It should work now but apparently does not. I'll take it up with the product team internally and then we will get this updated once this has been implemented / fixed.

@logyball
Copy link

logyball commented Mar 4, 2021

@berndverst Any update on this? It would be a great feature to not have to use an insecure method for app service to talk to ACR.

@mattiasholm
Copy link

@juchom

The error you are getting makes sense. Looks like the CLI is hardcoded to expect admin enabled on ACR (not a good idea) or a username and password to be manually provided.

https://github.com/Azure/azure-cli/blob/abeb2dd611114ca4bb5c4c40996a36f3fc48a05e/src/azure-cli/azure/cli/command_modules/appservice/custom.py#L1120

Let's assume we are talking about

  • A webapp with name $NAME and in resource group $GROUP
  • A registry $REGISTRYNAME in resource group $REGISTRYGROUP

One good option that should certainly work

You could always do is to create a Service Principal for this particular situation that can only read from ACR.
Caveat: Credential expires in 1 year

az ad sp create-for-rbac --name AppServiceReadFromParticularACR
#Above returns a client ID and secret
az role assignment create --assignee $CLIENT_ID --scope /subscriptions/$YOURAZURESUBSCRIPTIONID/resourceGroups/$REGISTRYGROUP/providers/Microsoft.ContainerRegistry/registries/$REGISTRYNAME --role "AcrPull"

and then using the Service Principal client ID and client secret as username and password.

az webapp config container set --name $NAME --resource-group $GROUP --docker-custom-image-name $REGISTRYNAME.azurecr.io/$IMAGENAME:$IMAGETAG --docker-registry-server-url https://$REGISTRYNAME.azurecr.io --docker-registry-server-user $CLIENT_ID --docker-registry-server-password $CLIENT_SECRET

Of course using managed identities is better

It seems the CLI doesn't quite support this yet, but you could help me test this by doing the following.

# Create and assign a managed Service Principal to a Web App
az webapp identity assign --resource-group $GROUP --name $NAME

# This returns a Service Principal ID... $WEBAPPID

# Give webapp identity access to pull from ACR
az role assignment create --assignee $WEBAPPID --scope /subscriptions/$YOURAZURESUBSCRIPTIONID/resourceGroups/$REGISTRYGROUP/providers/Microsoft.ContainerRegistry/registries/$REGISTRYNAME --role "AcrPull"

# Now try using a bogus username and password
az webapp config container set --name $NAME --resource-group $GROUP --docker-custom-image-name $REGISTRYNAME.azurecr.io/$IMAGENAME:$IMAGETAG --docker-registry-server-url https://$REGISTRYNAME.azurecr.io --docker-registry-server-user $CLIENT_ID --docker-registry-server-password $CLIENT_SECRET

# Restart and try to see if this works?
az webapp restart -g $GROUP -n $NAME

# If it doesn't work, let's also delete the App Settings on the server corresponding to the username and password
az webapp config appsettings delete -g $GROUP -n $NAME --settings "DOCKER_REGISTRY_SERVER_PASSWORD" "DOCKER_REGISTRY_SERVER_USERNAME"
az webapp restart -g $GROUP -n $NAME

I'd like to clarify to anyone who's implementing the above solution that the 1 year expiration for an Azure AD service principal is in fact just a default value, meaning it can easily be overridden during creation, should you feel the need to.

Simply append "--years " to the "az ad sp create-for-rbac" command.
Although the official documentation lacks this information, I've verified that the maximum allowed expiration year is 9999, which ought to cover most needs...

I guess from a security standpoint, you might actually be better off just keeping the default value, but that's a totally different story! 👍

@fabiansalamo
Copy link

This is what entually worked for me:

az webapp config set -g some-rg -n some-app-name --generic-configurations "{""acrUseManagedIdentityCreds"": true, ""acrUserManagedIdentityId"": ""your-object-Id-here"", ""linuxFxVersion"": ""DOCKER|someacr.azurecr.io/some-image:latest""}"

hope this helps somebody!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants