0

I am attempting to programmatically create an ACI instance in .NET Core, with a simple container as below. I have to point to a private ACR to use with ACI, and the private ACR should be accessed with managed identity, in my case using the Visual Studio's logged in Azure account.

Azure.Core.TokenCredential msiTokenCred = DefaultAzureCredentialProvider.GetCredential(new DefaultAzureCredentialOptions
{
    ExcludeVisualStudioCodeCredential = false,
    ExcludeVisualStudioCredential = false,
    TenantId = "XXXXXXXX-41bc-86f2-XXXX-72f988bfdb47"
});

// authenticate your client
ArmClient client = new ArmClient(msiTokenCred);

// this example assumes you already have this ResourceGroupResource created on azure
// for more information of creating ResourceGroupResource, please refer to the document of ResourceGroupResource
string subscriptionId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX";
string resourceGroupName = "rg-acidemo";
ResourceIdentifier resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(subscriptionId, resourceGroupName);
ResourceGroupResource resourceGroupResource = client.GetResourceGroupResource(resourceGroupResourceId);

// get the collection of this ContainerGroupResource
ContainerGroupCollection collection = resourceGroupResource.GetContainerGroups();

// invoke the operation
string containerGroupName = "demo1";
ContainerGroupData data = new ContainerGroupData(new AzureLocation("eastus"),
[
    new ContainerInstanceContainer("test-container-001","myprivateacr.azurecr.io/alpine",new ContainerResourceRequirements( new ContainerResourceRequestsContent(1,1)))
    {
        Command =
        {
            "/bin/sh","-c","sleep 10"
        }
    }
], ContainerInstanceOperatingSystemType.Linux)
{
    RestartPolicy = ContainerGroupRestartPolicy.Never,
    Sku = ContainerGroupSku.Standard,
    Priority = ContainerGroupPriority.Spot 
};
ArmOperation<ContainerGroupResource> lro = await collection.CreateOrUpdateAsync(WaitUntil.Completed, containerGroupName, data);
ContainerGroupResource result = lro.Value;

ContainerGroupData resourceData = result.Data;
Console.WriteLine($"Succeeded on id: {resourceData.Id}");

This is not working and resulting in an error -

'The image 'myprivateacr.azurecr.io/alpine' in container group 'demo1' is not accessible. Please check the image and registry credential.
Status: 400 (Bad Request)
ErrorCode: InaccessibleImage

Has anyone tried this and any idea why it fails even though TokenCredential used. Please note that this TokenCredential works with ACR and is capable of pulling and pushing images, it's not working with ACI though.

1 Answer 1

1

You are getting error because when ACI pulls image from ACR it does not uses VS Token credentials which you are providing.

There are 2 ways to pull image using Managed Identity in ACI:

  1. System Assigned :- It is not possible, it can be enabled after ACI is created and then can be used to assign required role in ACR to pull image. you cannot enable, assign role and pull images simultaneously.
  2. User Assigned :- Create User Assigned Identity and assign AcrPull role in ACR. and use this identity to pull image. This worked for me.

I created a user assigned identity and assign AcrPull role.

Used your given code and made some changes.

Below is given code which worked:

using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Models;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager.ContainerInstance;
using Azure.ResourceManager.ContainerInstance.Models;


var msiTokenCred = new DefaultAzureCredential (new DefaultAzureCredentialOptions
{
    ExcludeVisualStudioCodeCredential = false,
    ExcludeVisualStudioCredential = false,
    TenantId = "xxxxxxxxxxxxxxxxxxxxxxx"
});

// authenticate your client
ArmClient client = new ArmClient(msiTokenCred);

// this example assumes you already have this ResourceGroupResource created on azure
// for more information of creating ResourceGroupResource, please refer to the document of ResourceGroupResource
string subscriptionId = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
string resourceGroupName = "Vivek-RG";
string identityName = "acruseridentity";
ResourceIdentifier resourceGroupResourceId = ResourceGroupResource.CreateResourceIdentifier(subscriptionId, resourceGroupName);
ResourceGroupResource resourceGroupResource = client.GetResourceGroupResource(resourceGroupResourceId);

// get the collection of this ContainerGroupResource
ContainerGroupCollection collection = resourceGroupResource.GetContainerGroups();

// invoke the operation
string containerGroupName = "demo1";
ContainerGroupData data = new ContainerGroupData(new AzureLocation("eastus"),
[
    new ContainerInstanceContainer("containerinstance4sep-userassigned","vivek.azurecr.io/caddy",new ContainerResourceRequirements( new ContainerResourceRequestsContent(1,1)))
    {
        Command =
        {
            "/bin/sh","-c","sleep 10"
        }
    }
], ContainerInstanceOperatingSystemType.Linux)
{
    RestartPolicy = ContainerGroupRestartPolicy.Never,
    Sku = ContainerGroupSku.Standard,
    Priority = ContainerGroupPriority.Spot,
    Identity = new ManagedServiceIdentity(ManagedServiceIdentityType.UserAssigned)
    {
        UserAssignedIdentities =
        {
            [(new ResourceIdentifier($"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}"))]= new UserAssignedIdentity()
        }
    },
    ImageRegistryCredentials = { new ContainerGroupImageRegistryCredential("vivek.azurecr.io")
    {
        Identity = new ResourceIdentifier($"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}")
    } }
};
ArmOperation<ContainerGroupResource> lro = await collection.CreateOrUpdateAsync(WaitUntil.Completed, containerGroupName, data);
ContainerGroupResource result = lro.Value;

ContainerGroupData resourceData = result.Data;
Console.WriteLine($"Succeeded on id: {resourceData.Id}");

OUTPUT:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.