azureazure-pipelinesazure-bicepacr

ACR task command fails with unmarshall error


I have a Azure Container registry with few docker images. I want to manage it through DevOps via acr task. I have created an ACR task with following bicep

resource cr_purge_image_task 'Microsoft.ContainerRegistry/registries/tasks@2019-06-01-preview' = {
  parent: cr_res
  name: 'purge_image'
  location: resourceGroup().location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    credentials: {
      customRegistries: {
        '${crName}.azurecr.io': {
          identity: '[system]'
        }
      }
    }
    platform: {
      os: 'linux'
      architecture: 'amd64'
    }
    step: {
      type: 'EncodedTask'
      //encodedTaskContent: base64('acr purge --filter "imagename:.*" --ago 1d --untagged --dry-run') gives same error
      // converted following cmd to base64 string acr purge --filter 'imagename:.*' --ago 1d --untagged --dry-run
      encodedTaskContent: 'YWNyIHB1cmdlIC0tZmlsdGVyICdpbWFnZW5hbWU6LionIC0tYWdvIDFkIC0tdW50YWdnZWQgLS1kcnktcnVu'
    }
  }
}

In the DevOps pipeline yml to run the ACR task

                - task: AzureCLI@2
                  inputs:
                    azureSubscription: 'ServiceConnection-Sub-f2959b76-4f0c-4064-ba70-1f3f1d61bxxx'
                    scriptType: 'bash'
                    scriptLocation: 'inlineScript'
                    inlineScript: |
                        az acr task run -n purge_image -r registryname

On pipeline run gives following error

failed to unmarshal task before running: failed to deserialize task and validate: yaml: unmarshal errors:
  line 1: cannot unmarshal !!str `acr pur...` into graph.Task


Run ID: db18 failed after 1s. Error: failed during run, err: exit status 1

ERROR: Run failed

Is the base64 format wrong that is used while creating task?


Solution

  • ACR task command fails with unmarshall error

    Glad to know that you're able to figure out the solution posting this along with the insights I provided as solution so that it would be helpful for the community who may came across the similar type of blockers.

    So as mentioned in the comments Instead of encoding a command directly, you must encode a YAML task script.

    YAML:

    version: v1.1.0
    steps:
      - cmd: acr purge --filter 'imagename:.*' --ago 1d --untagged --dry-run
        disableWorkingDirectoryOverride: true
        timeout: 3600
    

    Convert the above YAML to base64 and use the base64 output in your Bicep file as encodedTaskContent.

    sample Bicep:

    resource cr_purge_image_task 'Microsoft.ContainerRegistry/registries/tasks@2019-06-01-preview' = {
      parent: cr_res
      name: 'purge_image'
      location: resourceGroup().location
      identity: {
        type: 'SystemAssigned'
      }
      properties: {
        credentials: {
          customRegistries: {
            '${crName}.azurecr.io': {
              identity: '[system]'
            }
          }
        }
        platform: {
          os: 'linux'
          architecture: 'amd64'
        }
        step: {
          type: 'EncodedTask'
          encodedTaskContent: '<BASE64_ENCODED_YAML>'
        }
      }
    }
    

    As you mentioned you can use bicep or CLI to assign the roles to system-assigned managed identity as mentioned

    using bicep:

    resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
      name: guid(cr_purge_image_task.id, 'AcrPull')
      scope: cr_res
      properties: {
        principalId: cr_purge_image_task.identity.principalId
        roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
      }
    }
    

    Once this role assignment is done continue and Run ACR Task from Azure DevOps Pipeline.

    Refer:

    https://learn.microsoft.com/en-us/azure/container-registry/container-registry-rbac-built-in-roles-overview?tabs=registries-configured-with-rbac-registry-abac-repository-permissions#supported-role-assignment-identity-types