1

I have a image registry in Azure Subscription A and I want to deploy an azure Container App in a Azure Subscription B using the image from the Azure Subscription A registry repository. I'm trying to do this using service principles as authentication. Is that possible with terraform? I can do it with scripts where I use the Azure Cli to login to Subscription A, pull the image and then login to Azure Subscription B and deploy it or even with Visual Studio's Publish (when I create the Publish profile I can chose the account for the Container App and for the Registry I can use another account) but I can't seem to manage this in terraform. This is my main.tf (I'm using variables to hide sensitive data) :

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.63.0"
    }
  }

  required_version = ">= 1.1.0"
}

provider "azurerm" {
  subscription_id = var.subsriptionA_sub_id
  tenant_id       = var.subsriptionA_tenant_id
  client_id       = var.subsriptionA_client_id
  client_secret   = var.subsriptionA_client_secret

  features {}
}

provider "azurerm" {
  alias           = "test"
  subscription_id = var.subscriptionB_sub_id
  tenant_id       = var.subscriptionB_tenant_id
  client_id       = var.subscriptionB_client_id
  client_secret   = var.subscriptionB_client_secret

  features {}
}
resource "azurerm_resource_group" "example" {
  provider = azurerm.test
  name     = var.resource_group_name
  location = var.location
}
data "azurerm_container_registry" "acr" {
  provider            = azurerm
  name                = "registryName"
  resource_group_name = var.subscriptionA_resource_group_name
}
resource "azurerm_log_analytics_workspace" "example" {
  provider            = azurerm.test
  name                = "acctest-01"
  location            = var.location
  resource_group_name = var.resource_group_name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

resource "azurerm_container_app_environment" "example" {
  provider                   = azurerm.test
  name                       = "Example-Environment"
  location                   = azurerm_resource_group.example.location
  resource_group_name        = azurerm_resource_group.example.name
  log_analytics_workspace_id = azurerm_log_analytics_workspace.example.id
}
resource "azurerm_container_app" "example" {
  provider                     = azurerm.test
  name                         = "example-app"
  container_app_environment_id = azurerm_container_app_environment.example.id
  resource_group_name          = var.resource_group_name
  revision_mode                = "Single"

  template {
    container {
      name   = "examplecontainerapp"
      image  = "${data.azurerm_container_registry.acr.login_server}/repositoryA:latest"
      cpu    = 0.25
      memory = "0.5Gi"
    }
  }
}

edit : This is the error I'm getting with this setup :

 Error: creating Container App (Subscription: SubscriptionB
│ Resource Group Name: var.resource_group_name
│ Container App Name: "example-app"): performing CreateOrUpdate: containerapps.ContainerAppsClient#CreateOrUpdate: Failure sending request: StatusCode=0 -- Original Error: Code="InvalidParameterValueInContainerTemplate" Message="The following field(s) are either invalid or missing. Field 'template.containers.examplecontainerapp.image' is invalid with details: 'Invalid value: \"${data.azurerm_container_registry.acr.login_server}/repositoryA:latest\": GET https:?scope=repositoryFromSusbscriptionA UNAUTHORIZED: authentication required, visit https://aka.ms/acr/authorization for more information.';."

edit2 : I found my solution, I needed to add these blocks, registry alone wasn't enough I needed a secret to get the password:

 secret {
    name  = "secretname"
    value = var.subsriptionA_client_secret
  }
  registry {
    server               = "server"
    username             = var.subsriptionA_client_id
    password_secret_name = "secretname"
  }

Thank you in advance!

2
  • What's wrong with current code? Any errors? Commented Jul 5, 2023 at 0:37
  • Basically I'm getting unauthorized which kind of makes sense since the provider inside the azurerm_container_app block is from subscriptionA.. I added the error in the edit Commented Jul 5, 2023 at 7:35

1 Answer 1

3

I've found the solution for anyone wondering, there needs to be a registry block that takes the credential and the password needs to be from a secret (you can also use azure key vault for this from what I researched though I haven't tried that) :

resource "azurerm_container_app" "example" {
  provider                     = azurerm.test
  name                         = "example-app"
  container_app_environment_id = azurerm_container_app_environment.example.id
  resource_group_name          = var.resource_group_name
  revision_mode                = "Single"

 secret {
    name  = "secretname"
    value = var.subsriptionA_client_secret
  }
  registry {
    server               = "server"
    username             = var.subsriptionA_client_id
    password_secret_name = "secretname"
  }
  template {
    container {
      name   = "examplecontainerapp"
      image  = "${data.azurerm_container_registry.acr.login_server}/repositoryA:latest"
      cpu    = 0.25
      memory = "0.5Gi"
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Just to complement this solution: Identity can also be used instead of username/password. Imagine your ACR is in a different subscriptions, you probably want to create an identity in there for your subscriptions and reference it there, a safer and more consistent approach than your admin password in some secret variable :)

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.